Skip to content

Commit

Permalink
add BEASTClassLoader to deal with dynamic loading of jar files #834
Browse files Browse the repository at this point in the history
  • Loading branch information
rbouckaert committed May 20, 2019
1 parent efd7100 commit aafeda4
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 46 deletions.
5 changes: 3 additions & 2 deletions src/beast/evolution/alignment/Alignment.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import beast.core.util.Log;
import beast.evolution.datatype.DataType;
import beast.evolution.datatype.StandardData;
import beast.util.BEASTClassLoader;
import beast.util.PackageManager;

import java.util.*;
Expand Down Expand Up @@ -67,7 +68,7 @@ static public void findDataTypes() {
List<String> m_sDataTypes = PackageManager.find(beast.evolution.datatype.DataType.class, IMPLEMENTATION_DIR);
for (String dataTypeName : m_sDataTypes) {
try {
DataType dataType = (DataType) Class.forName(dataTypeName).newInstance();
DataType dataType = (DataType) Class.forName(dataTypeName, true, BEASTClassLoader.classLoader).newInstance();
if (dataType.isStandard()) {
String description = dataType.getTypeDescription();
if (!types.contains(description)) {
Expand Down Expand Up @@ -265,7 +266,7 @@ protected void initDataType() {
for (String dataTypeName : dataTypes) {
DataType dataType;
try {
dataType = (DataType) Class.forName(dataTypeName).newInstance();
dataType = (DataType) Class.forName(dataTypeName, true, BEASTClassLoader.classLoader).newInstance();
if (dataTypeInput.get().equals(dataType.getTypeDescription())) {
m_dataType = dataType;
break;
Expand Down
52 changes: 52 additions & 0 deletions src/beast/util/BEASTClassLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package beast.util;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;

import javax.swing.plaf.PanelUI;

public class BEASTClassLoader extends URLClassLoader {

// singleton class loader
static final public BEASTClassLoader classLoader = new BEASTClassLoader(new URL[0], BEASTClassLoader.class.getClassLoader());

public BEASTClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}

@Override
public void addURL(URL url) {
super.addURL(url);
}

public void addJar(String jarFile) {
File file = new File(jarFile);
if (file.exists()) {
try {
URL url = file.toURI().toURL();
classLoader.addURL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}


public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
//Class c = cl.loadClass("monos.GenerateLexicalConstraints");
//System.out.println(c.getName());
classLoader.addJar("/home/rbou019/.beast/2.5/NS/lib/NS.addon.jar");
System.out.println("Classloader of this class:"
+ BEASTClassLoader.class.getClassLoader());

System.out.println("Classloader of PanelUI:"
+ Class.forName("beast.core.NSLogger", true, classLoader).getDeclaredConstructor().newInstance().getClass().getClassLoader());

System.out.println("Classloader of ArrayList:"
+ ArrayList.class.getClassLoader());
}
}
78 changes: 41 additions & 37 deletions src/beast/util/PackageManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@
// TODO: on windows allow installation on drive D: and pick up add-ons in drive C:
//@Description("Manage all BEAUti packages and list their dependencies")
public class PackageManager {



public static final BEASTVersion beastVersion = BEASTVersion.INSTANCE;

public enum UpdateStatus {AUTO_CHECK_AND_ASK, AUTO_UPDATE, DO_NOT_CHECK};
Expand Down Expand Up @@ -762,7 +765,7 @@ public static String getBEASTInstallDir() {

URL u;
try {
u = Class.forName("beast.app.beastapp.BeastMain").getProtectionDomain().getCodeSource().getLocation();
u = Class.forName("beast.app.beastapp.BeastMain", true, BEASTClassLoader.classLoader).getProtectionDomain().getCodeSource().getLocation();
} catch (ClassNotFoundException e) {
// e.printStackTrace();
return null;
Expand Down Expand Up @@ -1051,13 +1054,13 @@ public static void loadExternalJars() throws IOException {
// way with java 8 when the -Dbeast.load.jars=true
// directive is given. This can be useful for developers
// but generally slows down application starting.
if (Boolean.getBoolean("beast.load.jars") == false || Utils6.getMajorJavaVersion() != 8) {
externalJarsLoaded = true;
Utils6.logToSplashScreen("PackageManager::findDataTypes");
findDataTypes();
Utils6.logToSplashScreen("PackageManager::Done");
return;
}
// if (Boolean.getBoolean("beast.load.jars") == false || Utils6.getMajorJavaVersion() != 8) {
// externalJarsLoaded = true;
// Utils6.logToSplashScreen("PackageManager::findDataTypes");
// findDataTypes();
// Utils6.logToSplashScreen("PackageManager::Done");
// return;
// }

for (String jarDirName : getBeastDirectories()) {
loadPackage(jarDirName);
Expand All @@ -1070,7 +1073,7 @@ public static void loadExternalJars() throws IOException {

private static void findDataTypes() {
try {
Method findDataTypes = Class.forName("beast.evolution.alignment.Alignment").getMethod("findDataTypes");
Method findDataTypes = Class.forName("beast.evolution.alignment.Alignment", true, BEASTClassLoader.classLoader).getMethod("findDataTypes");
findDataTypes.invoke(null);
} catch (Exception e) {
// too bad, cannot load data types
Expand Down Expand Up @@ -1176,7 +1179,7 @@ private static void loadPackage(String jarDirName) {
className = className.substring(0, className.lastIndexOf('.'));
try {
/*Object o =*/
Class.forName(className);
Class.forName(className, true, BEASTClassLoader.classLoader);
loadedClass = className;
} catch (Exception e) {
// TODO: handle exception
Expand Down Expand Up @@ -1354,30 +1357,31 @@ private static void message(String string) {
* @throws IOException if something goes wrong when adding a url
*/
public static void addURL(URL u) throws IOException {
// ClassloaderUtil clu = new ClassloaderUtil();
PackageManager clu = new PackageManager();
// URLClassLoader sysLoader = (URLClassLoader)
// ClassLoader.getSystemClassLoader();
URLClassLoader sysLoader = (URLClassLoader) clu.getClass().getClassLoader();
URL urls[] = sysLoader.getURLs();
for (URL url : urls) {
if (url.toString().toLowerCase().equals(u.toString().toLowerCase())) {
Log.debug.println("URL " + u + " is already in the CLASSPATH");
return;
}
}
Class<?> sysclass = URLClassLoader.class;
try {
// Parameters
Class<?>[] parameters = new Class[]{URL.class};
Method method = sysclass.getDeclaredMethod("addURL", parameters);
method.setAccessible(true);
method.invoke(sysLoader, u);
Log.debug.println("Loaded URL " + u);
} catch (Throwable t) {
t.printStackTrace();
throw new IOException("Error, could not add URL to system classloader");
}
BEASTClassLoader.classLoader.addURL(u);
// // ClassloaderUtil clu = new ClassloaderUtil();
// PackageManager clu = new PackageManager();
// // URLClassLoader sysLoader = (URLClassLoader)
// // ClassLoader.getSystemClassLoader();
// URLClassLoader sysLoader = (URLClassLoader) clu.getClass().getClassLoader();
// URL urls[] = sysLoader.getURLs();
// for (URL url : urls) {
// if (url.toString().toLowerCase().equals(u.toString().toLowerCase())) {
// Log.debug.println("URL " + u + " is already in the CLASSPATH");
// return;
// }
// }
// Class<?> sysclass = URLClassLoader.class;
// try {
// // Parameters
// Class<?>[] parameters = new Class[]{URL.class};
// Method method = sysclass.getDeclaredMethod("addURL", parameters);
// method.setAccessible(true);
// method.invoke(sysLoader, u);
// Log.debug.println("Loaded URL " + u);
// } catch (Throwable t) {
// t.printStackTrace();
// throw new IOException("Error, could not add URL to system classloader");
// }
String classpath = System.getProperty("java.class.path");
String jar = u + "";
classpath += System.getProperty("path.separator") + jar.substring(5);
Expand Down Expand Up @@ -1556,7 +1560,7 @@ public static List<String> find(String classname, String[] pkgnames) {
result = new ArrayList<String>();

try {
cls = Class.forName(classname);
cls = Class.forName(classname, true, BEASTClassLoader.classLoader);
result = find(cls, pkgnames);
} catch (Exception e) {
e.printStackTrace();
Expand All @@ -1580,7 +1584,7 @@ public static List<String> find(String classname, String pkgname) {
result = new ArrayList<String>();

try {
cls = Class.forName(classname);
cls = Class.forName(classname, true, BEASTClassLoader.classLoader);
result = find(cls, pkgname);
} catch (Exception e) {
e.printStackTrace();
Expand Down Expand Up @@ -1653,7 +1657,7 @@ public static List<String> find(Class<?> cls, String pkgname) {
if (className.startsWith(pkgname)) {
//Log.debug.println(className);
try {
Class<?> clsNew = Class.forName(className);
Class<?> clsNew = Class.forName(className, true, BEASTClassLoader.classLoader);

// no abstract classes
if (!Modifier.isAbstract(clsNew.getModifiers()) &&
Expand Down
14 changes: 7 additions & 7 deletions src/beast/util/XMLParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ void parseNameSpaceAndMap(final Node topNode) throws XMLParserException {
for (final String nameSpace : this.nameSpaces) {
try {
// sanity check: class should exist
if (!isDone && Class.forName(nameSpace + clazz) != null) {
if (!isDone && Class.forName(nameSpace + clazz, true, BEASTClassLoader.classLoader) != null) {
element2ClassMap.put(name, clazz);
Log.debug.println(name + " => " + nameSpace + clazz);
final String reserved = getAttribute(child, "reserved");
Expand Down Expand Up @@ -669,7 +669,7 @@ void parseRunElement(final Node topNode) throws XMLParserException {
*/
boolean checkType(final String className, final BEASTInterface beastObject, Node node) throws XMLParserException {
try {
if (className.equals(INPUT_CLASS) || Class.forName(className).isInstance(beastObject)) {
if (className.equals(INPUT_CLASS) || Class.forName(className, true, BEASTClassLoader.classLoader).isInstance(beastObject)) {
return true;
}
} catch (ClassNotFoundException e) {
Expand Down Expand Up @@ -751,7 +751,7 @@ BEASTInterface createObject(final Node node, final String classname) throws XMLP
for (final String nameSpace : nameSpaces) {
try {
if (!isDone) {
Class.forName(nameSpace + specClass);
Class.forName(nameSpace + specClass, true, BEASTClassLoader.classLoader);
clazzName = nameSpace + specClass;
isDone = true;
}
Expand All @@ -777,7 +777,7 @@ BEASTInterface createObject(final Node node, final String classname) throws XMLP

// sanity check
try {
Class<?> clazz = Class.forName(clazzName);
Class<?> clazz = Class.forName(clazzName, true, BEASTClassLoader.classLoader);
if (!BEASTInterface.class.isAssignableFrom(clazz)) {
throw new XMLParserException(node, "Expected object to be instance of BEASTObject", 108);
}
Expand Down Expand Up @@ -820,7 +820,7 @@ private BEASTInterface createBeastObject(Node node, String ID, String clazzName,
// create new instance using class name
Object o = null;
try {
Class<?> c = Class.forName(clazzName);
Class<?> c = Class.forName(clazzName, true, BEASTClassLoader.classLoader);
o = c.newInstance();
} catch (InstantiationException e) {
// we only get here when the class exists, but cannot be
Expand Down Expand Up @@ -901,7 +901,7 @@ private BEASTInterface createBeastObject(Node node, String ID, String clazzName,
private BEASTInterface useAnnotatedConstructor(Node node, String _id, String clazzName, List<NameValuePair> inputInfo) throws XMLParserException {
Class<?> clazz = null;
try {
clazz = Class.forName(clazzName);
clazz = Class.forName(clazzName, true, BEASTClassLoader.classLoader);
} catch (ClassNotFoundException e) {
// cannot get here, since we checked the class existed before
e.printStackTrace();
Expand Down Expand Up @@ -1166,7 +1166,7 @@ private String resolveClass(String specClass) {
}
for (String nameSpace : nameSpaces) {
try {
if (Class.forName(nameSpace + specClass) != null) {
if (Class.forName(nameSpace + specClass, true, BEASTClassLoader.classLoader) != null) {
String clazzName = nameSpace + specClass;
return clazzName;
}
Expand Down

0 comments on commit aafeda4

Please sign in to comment.