Repository: tomee Updated Branches: refs/heads/master a455fd3ab -> 31e2251cc
fixing saaj-impl dependency, updating Bootstrap to support another classloader than the system one Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/31e2251c Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/31e2251c Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/31e2251c Branch: refs/heads/master Commit: 31e2251ccac069a319706f4e3eb4f7b806bc3649 Parents: a455fd3 Author: rmannibucau <[email protected]> Authored: Thu May 4 11:57:47 2017 +0200 Committer: rmannibucau <[email protected]> Committed: Thu May 4 11:57:47 2017 +0200 ---------------------------------------------------------------------- .../java/org/apache/openejb/cli/Bootstrap.java | 37 ++++-- .../util/classloader/URLClassLoaderFirst.java | 5 +- .../openejb/loader/BasicURLClassPath.java | 119 +++++++++++++++++-- .../apache/openejb/loader/SystemClassPath.java | 27 ++++- examples/pom.xml | 17 +++ examples/webservice-ws-security/pom.xml | 28 +++-- .../openejb/itest/failover/Repository.java | 1 - .../server/control/StandaloneServer.java | 12 ++ .../RoundRobinConnectionStrategyTest.java | 9 +- server/openejb-cxf/pom.xml | 37 +++++- 10 files changed, 252 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/31e2251c/container/openejb-core/src/main/java/org/apache/openejb/cli/Bootstrap.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/cli/Bootstrap.java b/container/openejb-core/src/main/java/org/apache/openejb/cli/Bootstrap.java index 912f7d1..98f8741 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/cli/Bootstrap.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/cli/Bootstrap.java @@ -17,6 +17,7 @@ package org.apache.openejb.cli; +import org.apache.openejb.loader.ClassPath; import org.apache.openejb.loader.IO; import org.apache.openejb.loader.SystemClassPath; import org.apache.openejb.util.JavaSecurityManagers; @@ -24,6 +25,7 @@ import org.apache.openejb.util.PropertyPlaceHolderHelper; import org.apache.openejb.util.URLs; import java.io.File; +import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.net.URL; import java.util.StringTokenizer; @@ -85,12 +87,13 @@ public class Bootstrap { JavaSecurityManagers.setSystemProperty(prop, val); } - private static void setupClasspath() { + private static ClassLoader setupClasspath() { final String base = JavaSecurityManagers.getSystemProperty(OPENEJB_BASE_PROPERTY_NAME, ""); final String home = JavaSecurityManagers.getSystemProperty("catalina.home", JavaSecurityManagers.getSystemProperty(OPENEJB_HOME_PROPERTY_NAME, base)); try { final File lib = new File(home + File.separator + "lib"); - final SystemClassPath systemCP = new SystemClassPath(); + final ClassPath systemCP = new SystemClassPath(); + systemCP.getClassLoader(); File config = new File(base, "conf/catalina.properties"); if (!config.isFile()) { config = new File(home, "conf/catalina.properties"); @@ -131,10 +134,12 @@ public class Bootstrap { systemCP.addJarsToPath(lib); systemCP.addJarToPath(lib.toURI().toURL()); } + return systemCP.getClassLoader(); } catch (final Exception e) { System.err.println("Error setting up the classpath: " + e.getClass() + ": " + e.getMessage()); e.printStackTrace(); } + return null; } /** @@ -142,14 +147,30 @@ public class Bootstrap { */ public static void main(final String[] args) throws Exception { setupHome(args); - setupClasspath(); + final ClassLoader loader = setupClasspath(); + if (loader != null) { + Thread.currentThread().setContextClassLoader(loader); + if (loader != ClassLoader.getSystemClassLoader()) { + System.setProperty("openejb.classloader.first.disallow-system-loading", "true"); + } + } - final Class<?> clazz = Bootstrap.class.getClassLoader().loadClass(OPENEJB_CLI_MAIN_CLASS_NAME); - final Main main = (Main) clazz.newInstance(); + final Class<?> clazz = (loader == null ? Bootstrap.class.getClassLoader() : loader).loadClass(OPENEJB_CLI_MAIN_CLASS_NAME); try { - main.main(args); - } catch (final SystemExitException e) { - System.exit(e.getExitCode()); + final Object main = clazz.getConstructor().newInstance(); + main.getClass().getMethod("main", String[].class).invoke(main, new Object[]{args}); + } catch (final InvocationTargetException e) { + final Throwable cause = e.getCause(); + if ("org.apache.openejb.cli.SystemExitException".equals(cause.getClass().getName())) { + System.exit(Number.class.cast(cause.getClass().getMethod("getExitCode").invoke(cause)).intValue()); + } + if (Exception.class.isInstance(cause)) { + throw Exception.class.cast(cause); + } + if (Error.class.isInstance(cause)) { + throw Error.class.cast(cause); + } + throw new IllegalStateException(cause); } } http://git-wip-us.apache.org/repos/asf/tomee/blob/31e2251c/container/openejb-core/src/main/java/org/apache/openejb/util/classloader/URLClassLoaderFirst.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/util/classloader/URLClassLoaderFirst.java b/container/openejb-core/src/main/java/org/apache/openejb/util/classloader/URLClassLoaderFirst.java index 2bcd151..a8dcfb6 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/util/classloader/URLClassLoaderFirst.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/util/classloader/URLClassLoaderFirst.java @@ -58,6 +58,7 @@ public class URLClassLoaderFirst extends URLClassLoader { private static final URL SLF4J_CONTAINER = URLClassLoaderFirst.class.getClassLoader().getResource(SLF4J_BINDER_CLASS); private static final String CLASS_EXT = ".class"; public static final ClassLoader SYSTEM_CLASS_LOADER = ClassLoader.getSystemClassLoader(); + private static final boolean ALLOW_OPEN_EJB_SYSTEM_LOADING = !Boolean.getBoolean("openejb.classloader.first.disallow-system-loading"); public static void reloadConfig() { list(FORCED_SKIP, "openejb.classloader.forced-skip"); @@ -111,7 +112,7 @@ public class URLClassLoaderFirst extends URLClassLoader { } return clazz; } - } catch (final ClassNotFoundException ignored) { + } catch (final NoClassDefFoundError | ClassNotFoundException ignored) { // no-op } } @@ -187,7 +188,7 @@ public class URLClassLoaderFirst extends URLClassLoader { // we skip webapp enrichment jars since we want to load them from the webapp or lib // Note: this is not a real limitation since it is first fail it will be done later public static boolean canBeLoadedFromSystem(final String name) { - return !name.startsWith("org.apache.openejb.") || !isWebAppEnrichment(name.substring("org.apache.openejb.".length())); + return ALLOW_OPEN_EJB_SYSTEM_LOADING && (!name.startsWith("org.apache.openejb.") || !isWebAppEnrichment(name.substring("org.apache.openejb.".length()))); } // making all these call inline if far more costly than factorizing packages http://git-wip-us.apache.org/repos/asf/tomee/blob/31e2251c/container/openejb-loader/src/main/java/org/apache/openejb/loader/BasicURLClassPath.java ---------------------------------------------------------------------- diff --git a/container/openejb-loader/src/main/java/org/apache/openejb/loader/BasicURLClassPath.java b/container/openejb-loader/src/main/java/org/apache/openejb/loader/BasicURLClassPath.java index 77ed793..d459664 100644 --- a/container/openejb-loader/src/main/java/org/apache/openejb/loader/BasicURLClassPath.java +++ b/container/openejb-loader/src/main/java/org/apache/openejb/loader/BasicURLClassPath.java @@ -37,11 +37,15 @@ public abstract class BasicURLClassPath implements ClassPath { } private Field ucpField; + private boolean ucpFieldErrorLogged; protected void addJarToPath(final URL jar, final URLClassLoader loader) throws Exception { final Object cp = getURLClassPath(loader); - final Method addURLMethod = getAddURLMethod(loader); - addURLMethod.invoke(cp, jar); + if (cp == null && CustomizableURLClassLoader.class.isInstance(loader)) { + CustomizableURLClassLoader.class.cast(loader).add(jar); + } else { + getAddURLMethod(loader).invoke(cp, jar); + } } private Method getAddURLMethod(final URLClassLoader loader) { @@ -54,7 +58,7 @@ public abstract class BasicURLClassPath implements ClassPath { final Class<?> clazz = cp.getClass(); return clazz.getDeclaredMethod("addURL", URL.class); } catch (final Exception e) { - e.printStackTrace(); + System.err.println("Can't access addURL from URLClassPath"); } return null; @@ -89,14 +93,30 @@ public abstract class BasicURLClassPath implements ClassPath { } final Object cp = getURLClassPath(loader); - final Method addURLMethod = getAddURLMethod(loader); - for (final URL jar : jars) { - addURLMethod.invoke(cp, jar); + if (cp == null && CustomizableURLClassLoader.class.isInstance(loader)) { + final CustomizableURLClassLoader customizableURLClassLoader = CustomizableURLClassLoader.class.cast(loader); + for (final URL jar : jars) { + customizableURLClassLoader.add(jar); + } + } else if (cp == null && loader != null && CustomizableURLClassLoader.class.getName().equals(loader.getClass().getName())) { + final Method add = loader.getClass().getMethod("add", URL.class); + for (final URL jar : jars) { + add.invoke(loader, jar); + } + } else { + final Method addURLMethod = getAddURLMethod(loader); + for (final URL jar : jars) { + addURLMethod.invoke(cp, jar); + } } } protected Object getURLClassPath(final URLClassLoader loader) throws Exception { - return this.getUcpField().get(loader); + final Field ucpField = this.getUcpField(); + if (ucpField == null) { + return null; + } + return ucpField.get(loader); } private Field getUcpField() throws Exception { @@ -109,7 +129,10 @@ public abstract class BasicURLClassPath implements ClassPath { ucp.setAccessible(true); return ucp; } catch (final Exception e2) { - e2.printStackTrace(); + if (!ucpFieldErrorLogged) { + System.err.println("Can't get ucp field of URLClassLoader"); + ucpFieldErrorLogged = true; + } } return null; } @@ -119,4 +142,84 @@ public abstract class BasicURLClassPath implements ClassPath { return ucpField; } + protected static class CustomizableURLClassLoader extends URLClassLoader { + static { + ClassLoader.registerAsParallelCapable(); + } + + protected CustomizableURLClassLoader(final ClassLoader parent) { + super(new URL[0], parent); + } + + public void add(final URL url) { + super.addURL(url); + } + + @Override + protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException { + synchronized (getClassLoadingLock(name)) { + Class<?> clazz = findLoadedClass(name); + if (clazz != null) { + if (resolve) { + resolveClass(clazz); + } + return clazz; + } + + if (name != null && !name.startsWith("org.apache.openejb")) { + try { + return getSystemClassLoader().loadClass(name); + } catch (final ClassNotFoundException ignored) { + // no-op + } + } + + clazz = loadInternal(name, resolve); + if (clazz != null) { + return clazz; + } + + clazz = loadFromParent(name, resolve); + if (clazz != null) { + return clazz; + } + + throw new ClassNotFoundException(name); + } + } + + private Class<?> loadFromParent(final String name, final boolean resolve) { + ClassLoader parent = getParent(); + if (parent == null) { + parent = getSystemClassLoader(); + } + try { + final Class<?> clazz = Class.forName(name, false, parent); + if (clazz != null) { + if (resolve) { + resolveClass(clazz); + } + return clazz; + } + } catch (final ClassNotFoundException ignored) { + // no-op + } + return null; + } + + private Class<?> loadInternal(final String name, final boolean resolve) { + try { + final Class<?> clazz = findClass(name); + if (clazz != null) { + if (resolve) { + resolveClass(clazz); + } + return clazz; + } + } catch (final ClassNotFoundException ignored) { + // no-op + } + return null; + } + } } http://git-wip-us.apache.org/repos/asf/tomee/blob/31e2251c/container/openejb-loader/src/main/java/org/apache/openejb/loader/SystemClassPath.java ---------------------------------------------------------------------- diff --git a/container/openejb-loader/src/main/java/org/apache/openejb/loader/SystemClassPath.java b/container/openejb-loader/src/main/java/org/apache/openejb/loader/SystemClassPath.java index 6f87ea9..16f14ef 100644 --- a/container/openejb-loader/src/main/java/org/apache/openejb/loader/SystemClassPath.java +++ b/container/openejb-loader/src/main/java/org/apache/openejb/loader/SystemClassPath.java @@ -18,16 +18,19 @@ package org.apache.openejb.loader; import java.io.File; import java.lang.reflect.Method; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.net.URLDecoder; import java.security.AccessController; import java.security.PrivilegedAction; +import static org.apache.openejb.loader.JarLocation.jarLocation; + /*-------------------------------------------------------*/ /* System ClassLoader Support */ /*-------------------------------------------------------*/ -// TODO: we should get rid of it in favor of a custom root loader or flat classpath (ContextClassPath) +// TODO: we should get rid of it in favor of a custom root loader or flat classpath (ContextClassPath) and update Bootstrap to handle it public class SystemClassPath extends BasicURLClassPath { private URLClassLoader sysLoader; @@ -35,13 +38,17 @@ public class SystemClassPath extends BasicURLClassPath { @Override public void addJarsToPath(final File dir) throws Exception { this.addJarsToPath(dir, getSystemLoader()); - this.rebuildJavaClassPathVariable(); + if (getSystemLoader() == ClassLoader.getSystemClassLoader()) { + this.rebuildJavaClassPathVariable(); + } } @Override public void addJarToPath(final URL jar) throws Exception { this.addJarToPath(jar, getSystemLoader()); - this.rebuildJavaClassPathVariable(); + if (getSystemLoader() == ClassLoader.getSystemClassLoader()) { + this.rebuildJavaClassPathVariable(); + } } @Override @@ -55,11 +62,23 @@ public class SystemClassPath extends BasicURLClassPath { private URLClassLoader getSystemLoader() throws Exception { if (sysLoader == null) { - sysLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); + final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); + sysLoader = URLClassLoader.class.isInstance(systemClassLoader) ? + URLClassLoader.class.cast(systemClassLoader) : createCustomizableURLClassLoader(systemClassLoader); } return sysLoader; } + private CustomizableURLClassLoader createCustomizableURLClassLoader(final ClassLoader systemClassLoader) { + final CustomizableURLClassLoader customizableURLClassLoader = new CustomizableURLClassLoader(systemClassLoader); + try { + customizableURLClassLoader.add(jarLocation(SystemClassPath.class).toURI().toURL()); + } catch (final MalformedURLException e) { + // no-op + } + return customizableURLClassLoader; + } + private void rebuildJavaClassPathVariable() throws Exception { final URLClassLoader loader = getSystemLoader(); final Object cp = getURLClassPath(loader); http://git-wip-us.apache.org/repos/asf/tomee/blob/31e2251c/examples/pom.xml ---------------------------------------------------------------------- diff --git a/examples/pom.xml b/examples/pom.xml index 1c0cdfa..db89317 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -202,5 +202,22 @@ </plugins> </build> </profile> + <profile> + <id>java9</id> + <activation> + <jdk>9</jdk> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> <!-- requires saaj-impl 1.4 but cxf is not yet ready --> + <skip>true</skip> + </configuration> + </plugin> + </plugins> + </build> + </profile> </profiles> </project> http://git-wip-us.apache.org/repos/asf/tomee/blob/31e2251c/examples/webservice-ws-security/pom.xml ---------------------------------------------------------------------- diff --git a/examples/webservice-ws-security/pom.xml b/examples/webservice-ws-security/pom.xml index a8e08f6..b444580 100644 --- a/examples/webservice-ws-security/pom.xml +++ b/examples/webservice-ws-security/pom.xml @@ -60,14 +60,6 @@ <version>7.0.4-SNAPSHOT</version> <scope>test</scope> </dependency> - <!-- This is required on IBM JDKs (and potentially others) because saaj-impl depends - on Sun's internal copy of Xerces. See OPENEJB-1126. --> - <dependency> - <groupId>com.sun.xml.parsers</groupId> - <artifactId>jaxp-ri</artifactId> - <version>1.4.2</version> - <scope>test</scope> - </dependency> </dependencies> <build> <defaultGoal>install</defaultGoal> @@ -149,4 +141,24 @@ <url>file://${basedir}/target/snapshot-repo/</url> </snapshotRepository> </distributionManagement> + + <profiles> + <profile> + <id>java9</id> + <activation> + <jdk>9</jdk> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> <!-- requires saaj-impl 1.4 but cxf is not yet ready --> + <skip>true</skip> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> </project> http://git-wip-us.apache.org/repos/asf/tomee/blob/31e2251c/itests/failover/src/main/java/org/apache/openejb/itest/failover/Repository.java ---------------------------------------------------------------------- diff --git a/itests/failover/src/main/java/org/apache/openejb/itest/failover/Repository.java b/itests/failover/src/main/java/org/apache/openejb/itest/failover/Repository.java index ea95c3d..692d0a2 100644 --- a/itests/failover/src/main/java/org/apache/openejb/itest/failover/Repository.java +++ b/itests/failover/src/main/java/org/apache/openejb/itest/failover/Repository.java @@ -16,7 +16,6 @@ */ package org.apache.openejb.itest.failover; -import org.apache.openejb.loader.SystemInstance; import org.apache.openejb.loader.provisining.ProvisioningResolver; import org.apache.openejb.util.Join; http://git-wip-us.apache.org/repos/asf/tomee/blob/31e2251c/itests/failover/src/main/java/org/apache/openejb/server/control/StandaloneServer.java ---------------------------------------------------------------------- diff --git a/itests/failover/src/main/java/org/apache/openejb/server/control/StandaloneServer.java b/itests/failover/src/main/java/org/apache/openejb/server/control/StandaloneServer.java index af447b5..b33006e 100644 --- a/itests/failover/src/main/java/org/apache/openejb/server/control/StandaloneServer.java +++ b/itests/failover/src/main/java/org/apache/openejb/server/control/StandaloneServer.java @@ -50,6 +50,7 @@ public class StandaloneServer { private final File java; private final File openejbJar; private boolean debug; + private int debugPort = 5005; private boolean profile; private volatile Process process; private final List<String> jvmOpts = new ArrayList<String>(); @@ -198,6 +199,14 @@ public class StandaloneServer { this.debug = debug; } + public int getDebugPort() { + return debugPort; + } + + public void setDebugPort(final int debugPort) { + this.debugPort = debugPort; + } + public boolean isProfile() { return profile; } @@ -261,6 +270,9 @@ public class StandaloneServer { args.addAll(jvmOpts); final Set<Map.Entry<Object, Object>> collection = properties.entrySet(); args.addAll(Join.strings(collection, new SystemPropertiesCallback())); + if (debug) { + args.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=" + debugPort); + } args.add("-jar"); args.add(openejbJar.getAbsolutePath()); http://git-wip-us.apache.org/repos/asf/tomee/blob/31e2251c/itests/failover/src/test/java/org/apache/openejb/itest/failover/RoundRobinConnectionStrategyTest.java ---------------------------------------------------------------------- diff --git a/itests/failover/src/test/java/org/apache/openejb/itest/failover/RoundRobinConnectionStrategyTest.java b/itests/failover/src/test/java/org/apache/openejb/itest/failover/RoundRobinConnectionStrategyTest.java index a05bfbd..92b6e80 100644 --- a/itests/failover/src/test/java/org/apache/openejb/itest/failover/RoundRobinConnectionStrategyTest.java +++ b/itests/failover/src/test/java/org/apache/openejb/itest/failover/RoundRobinConnectionStrategyTest.java @@ -77,7 +77,6 @@ public class RoundRobinConnectionStrategyTest { final File zip = Repository.getArtifact("org.apache.tomee", "openejb-standalone", "zip"); final File app = Repository.getArtifact("org.apache.openejb.itests", "failover-ejb", "jar"); - final File dir = Files.tmpdir(); final StandaloneServer root; @@ -90,7 +89,8 @@ public class RoundRobinConnectionStrategyTest { root = new StandaloneServer(home, home); root.killOnExit(); - root.getJvmOpts().add("-Dopenejb.classloader.forced-load=org.apache.openejb"); + // root.setDebug(Boolean.getBoolean("openejb.test.standalone." + name + ".debug")); + root.getJvmOpts().add("-Dopenejb.classloader.forced-load=org.apache.openejb.itest"); root.ignoreOut(); root.setProperty("name", name); root.setProperty("openejb.extract.configuration", "false"); @@ -118,7 +118,8 @@ public class RoundRobinConnectionStrategyTest { final StandaloneServer server = new StandaloneServer(home, home); server.killOnExit(); server.ignoreOut(); - server.getJvmOpts().add("-Dopenejb.classloader.forced-load=org.apache.openejb"); + // server.setDebug(Boolean.getBoolean("openejb.test.standalone." + name + ".debug")); + server.getJvmOpts().add("-Dopenejb.classloader.forced-load=org.apache.openejb.itest"); server.setProperty("name", name); server.setProperty("openejb.extract.configuration", "false"); @@ -144,7 +145,7 @@ public class RoundRobinConnectionStrategyTest { servers.put(name, server); - logger.info(String.format("Starting %s server", name)); + logger.info(String.format("Starting %s server, uri=%s", name, uri)); server.start(1, TimeUnit.MINUTES); } http://git-wip-us.apache.org/repos/asf/tomee/blob/31e2251c/server/openejb-cxf/pom.xml ---------------------------------------------------------------------- diff --git a/server/openejb-cxf/pom.xml b/server/openejb-cxf/pom.xml index 9e9df9f..e707fdd 100644 --- a/server/openejb-cxf/pom.xml +++ b/server/openejb-cxf/pom.xml @@ -166,11 +166,6 @@ </exclusion> </exclusions> </dependency> - <dependency> - <groupId>com.sun.xml.messaging.saaj</groupId> - <artifactId>saaj-impl</artifactId> - <version>1.4.0-b03</version> - </dependency> <!-- This is required on IBM JDKs (and potentially others) because saaj-impl depends on Sun's internal copy of Xerces. See OPENEJB-1126. --> <dependency> @@ -180,5 +175,37 @@ <scope>test</scope> </dependency> </dependencies> + + <profiles> + <profile> + <id>default-build</id> + <activation> + <jdk>[1.7,1.9)</jdk> + </activation> + <dependencies> + <dependency> + <groupId>com.sun.xml.messaging.saaj</groupId> + <artifactId>saaj-impl</artifactId> + <version>1.3.23</version> + <!-- not yet supported by wss4j/cxf but needed for java 9, when supported we just upgrade since target=1.7 so fine for the main build + <version>1.4.0-b03</version> + --> + </dependency> + </dependencies> + </profile> + <profile> + <id>java-9</id> + <activation> + <jdk>9</jdk> + </activation> + <dependencies> + <dependency> + <groupId>com.sun.xml.messaging.saaj</groupId> + <artifactId>saaj-impl</artifactId> + <version>1.4.0-b03</version> + </dependency> + </dependencies> + </profile> + </profiles> </project>
