diff --git a/datastore_server/dist/datastore_server.sh b/datastore_server/dist/datastore_server.sh index bf260913703b2c28aafdce450d7f337713869551..13e4aca880593442eecc83330261236b39b8872f 100755 --- a/datastore_server/dist/datastore_server.sh +++ b/datastore_server/dist/datastore_server.sh @@ -160,10 +160,6 @@ CP=`echo $LIB_FOLDER/slf4j-log4j12-1.6.2.jar $LIB_FOLDER/datastore_server.jar $L $LIB_FOLDER/dbmigration*.jar $LIB_FOLDER/*.jar $EXT_LIB_FOLDER/*.jar \ | sed 's/\(.*\) [^ ]*jython27[^ ]* \(.*\)/\1 \2/g' \ | sed 's/ /:/g'` -# TODO: remove the following statement when Jython27ClassLoader works -CP=`echo $LIB_FOLDER/slf4j-log4j12-1.6.2.jar $LIB_FOLDER/datastore_server.jar $LIB_FOLDER/common.jar \ - $LIB_FOLDER/dbmigration*.jar $LIB_FOLDER/*.jar $EXT_LIB_FOLDER/*.jar \ - | sed 's/ /:/g'` CMD="${JAVA_BIN} ${JAVA_OPTS} ${JAVA_MEM_OPTS} -Dnative.libpath=$LIB_FOLDER/native -classpath $CP ch.systemsx.cisd.openbis.dss.generic.DataStoreServer" diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/Jython27ClassLoader.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/Jython27ClassLoader.java index 5fd272dbdea066b22218a5018fee61263ffd709f..f9dee1f7f61c62353b481b26da4287795c803a34 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/Jython27ClassLoader.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/Jython27ClassLoader.java @@ -22,6 +22,9 @@ import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; import org.apache.commons.io.IOUtils; @@ -33,8 +36,9 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; * constructor. * <ul> * <li>This class loader always try first to find and load the class from the specified JAR file. - * <li>If it isn't found and if its fully-qualified class name does not match <tt>*.v27.*</tt> the class is - * loaded by the application class loader. + * Exceptions are classes from packages starting with <tt>sun.</tt> or <tt>java</tt>. + * <li>If it isn't found (or it is from these packages) and if its fully-qualified class name + * does not match <tt>*.v27.*</tt> the class is loaded by the application class loader. * <li>A class not found in the provided JAR file and fully-qualified class name does match <tt>*.v27.*</tt> * are loaded with this class loader. * </ul> @@ -43,7 +47,8 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; */ public class Jython27ClassLoader extends ClassLoader { - private final ClassLoader jythonJarClassLoader; + private final URLClassLoader jythonJarClassLoader; + private final Map<String, Class<?>> cachedClasses = new HashMap<>(); public Jython27ClassLoader(File jythonJar) { @@ -57,8 +62,7 @@ public class Jython27ClassLoader extends ClassLoader } try { - URL url = jythonJar.toURI().toURL(); - jythonJarClassLoader = new URLClassLoader(new URL[] { url }, null); + jythonJarClassLoader = new URLClassLoader(new URL[] { jythonJar.toURI().toURL() }, null); } catch (MalformedURLException ex) { throw CheckedExceptionTunnel.wrapIfNecessary(ex); @@ -66,37 +70,94 @@ public class Jython27ClassLoader extends ClassLoader } @Override - public Class<?> loadClass(String name) throws ClassNotFoundException + protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { - try - { - return jythonJarClassLoader.loadClass(name); - } catch (ClassNotFoundException ex) + Class<?> clazz = cachedClasses.get(name); + if (clazz == null) { - if (name.contains(".v27.") == false) + if (name.startsWith("sun.") == false && name.startsWith("java") == false) { - return super.loadClass(name); + clazz = tryLoadClass(jythonJarClassLoader, name); } - synchronized (getClassLoadingLock(name)) + if (clazz == null) { - InputStream stream = getResourceAsStream(name.replace('.', '/') + ".class"); - if (stream != null) + if (name.contains(".v27.")) { - try - { - byte[] bytes = IOUtils.toByteArray(stream); - return defineClass(name, bytes, 0, bytes.length); - } catch (IOException ex2) + clazz = tryLoadClass(this, name); + if (clazz == null) { - throw CheckedExceptionTunnel.wrapIfNecessary(ex2); - } finally - { - IOUtils.closeQuietly(stream); + return super.loadClass(name, resolve); } + } else + { + return super.loadClass(name, resolve); } - return super.loadClass(name); } } + if (resolve) + { + resolveClass(clazz); + } + cachedClasses.put(name, clazz); + return clazz; + } + + @Override + public URL getResource(String name) + { + URL resource = jythonJarClassLoader.getResource(name); + if (resource != null) + { + return resource; + } + return super.getResource(name); } + @Override + protected URL findResource(String name) + { + URL resource = jythonJarClassLoader.findResource(name); + if (resource != null) + { + return resource; + } + return super.findResource(name); + } + + @Override + protected Enumeration<URL> findResources(String name) throws IOException + { + Enumeration<URL> resources = jythonJarClassLoader.findResources(name); + if (resources != null) + { + return resources; + } + return super.findResources(name); + } + + private Class<?> tryLoadClass(ClassLoader classLoader, String name) + { + synchronized (getClassLoadingLock(name)) + { + InputStream stream = classLoader.getResourceAsStream(name.replace('.', '/') + ".class"); + if (stream != null) + { + try + { + byte[] bytes = IOUtils.toByteArray(stream); + return defineClass(name, bytes, 0, bytes.length); + } catch (SecurityException ex) + { + return null; + } catch (IOException ex) + { + throw CheckedExceptionTunnel.wrapIfNecessary(ex); + } finally + { + IOUtils.closeQuietly(stream); + } + } + return null; + } + } } \ No newline at end of file diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/Jython27FactoriesProvider.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/Jython27FactoriesProvider.java index 381184a4a66880ecce5daa56de0e15a3982f5d3b..aa2b6f0a825fedd089d0405dde43bbecf9186669 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/Jython27FactoriesProvider.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/utils/Jython27FactoriesProvider.java @@ -45,8 +45,7 @@ public class Jython27FactoriesProvider { if (file.getName().startsWith("jython27")) { - // TODO un-comment when Jython27ClassLoader is working. - // return new Jython27ClassLoader(file); + return new Jython27ClassLoader(file); } } }