Author: rmannibucau Date: Mon Aug 12 08:15:25 2013 New Revision: 1513074 URL: http://svn.apache.org/r1513074 Log: OPENEJB-2035 replacing real jar when using deploy time enhacement otherwise existing classloaders are broken + trying to use container classloader to create datasource when possible
Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/DeployTimeEnhancer.java tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/util/classloader/URLClassLoaderFirst.java Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/DeployTimeEnhancer.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/DeployTimeEnhancer.java?rev=1513074&r1=1513073&r2=1513074&view=diff ============================================================================== --- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/DeployTimeEnhancer.java (original) +++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/DeployTimeEnhancer.java Mon Aug 12 08:15:25 2013 @@ -27,7 +27,6 @@ import org.apache.openejb.util.Logger; import org.apache.openejb.util.Saxs; import org.apache.openejb.util.URLs; import org.apache.openejb.util.classloader.URLClassLoaderFirst; -import org.apache.xbean.finder.filter.Filter; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; @@ -39,7 +38,6 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.net.URL; -import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -60,7 +58,6 @@ public class DeployTimeEnhancer { private static final String PROPERTIES_FILE_PROP = "propertiesFile"; private static final String META_INF_PERSISTENCE_XML = "META-INF/persistence.xml"; private static final String TMP_ENHANCEMENT_SUFFIX = ".tmp-enhancement"; - private static final String JAR_ENHANCEMENT_SUFFIX = "-enhanced"; private final Method enhancerMethod; private final Constructor<?> optionsConstructor; @@ -91,37 +88,32 @@ public class DeployTimeEnhancer { // find persistence.xml final Map<String, List<String>> classesByPXml = new HashMap<String, List<String>>(); - final Filter filter = new AlreadyEnhancedFilter(); final List<URL> usedUrls = new ArrayList<URL>(); // for fake classloader for (URL url : event.getUrls()) { final File file = URLs.toFile(url); - if (filter.accept(file.getName())) { - if (file.isDirectory()) { - final String pXmls = getWarPersistenceXml(url); - if (pXmls != null) { - feed(classesByPXml, pXmls); - } + if (file.isDirectory()) { + final String pXmls = getWarPersistenceXml(url); + if (pXmls != null) { + feed(classesByPXml, pXmls); + } - usedUrls.add(url); - } else if (file.getName().endsWith(".jar")) { - try { - final JarFile jar = new JarFile(file); - ZipEntry entry = jar.getEntry(META_INF_PERSISTENCE_XML); - if (entry != null) { - final String path = file.getAbsolutePath(); - final File unpacked = new File(path.substring(0, path.length() - 4) + TMP_ENHANCEMENT_SUFFIX); - JarExtractor.extract(file, unpacked); + usedUrls.add(url); + } else if (file.getName().endsWith(".jar")) { + try { + final JarFile jar = new JarFile(file); + ZipEntry entry = jar.getEntry(META_INF_PERSISTENCE_XML); + if (entry != null) { + final String path = file.getAbsolutePath(); + final File unpacked = new File(path.substring(0, path.length() - 4) + TMP_ENHANCEMENT_SUFFIX); + JarExtractor.extract(file, unpacked); - // replace jar by folder url since otherwise enhancement doesn't work - usedUrls.add(unpacked.toURI().toURL()); + // replace jar by folder url since otherwise enhancement doesn't work + usedUrls.add(unpacked.toURI().toURL()); - feed(classesByPXml, new File(unpacked, META_INF_PERSISTENCE_XML).getAbsolutePath()); - } - } catch (IOException e) { - // ignored + feed(classesByPXml, new File(unpacked, META_INF_PERSISTENCE_XML).getAbsolutePath()); } - } else { - usedUrls.add(url); + } catch (IOException e) { + // ignored } } else { usedUrls.add(url); @@ -159,7 +151,7 @@ public class DeployTimeEnhancer { usedUrls.clear(); } - // clean up extracted jars + // clean up extracted jars and replace jar to keep consistent classloading for (Map.Entry<String, List<String>> entry : classesByPXml.entrySet()) { final List<String> values = entry.getValue(); for (String rawPath : values) { @@ -168,11 +160,13 @@ public class DeployTimeEnhancer { final File file = new File(rawPath.substring(0, rawPath.length() - TMP_ENHANCEMENT_SUFFIX.length() - 1) + ".jar"); if (file.exists()) { String name = dir.getName(); - name = name.substring(0, name.length() - TMP_ENHANCEMENT_SUFFIX.length()) + JAR_ENHANCEMENT_SUFFIX + ".jar"; - try { - JarCreator.jarDir(dir, new File(dir.getParentFile(), name)); - Files.delete(file); // don't delete if any exception is thrown - } catch (IOException e) { + name = name.substring(0, name.length() - TMP_ENHANCEMENT_SUFFIX.length()) + ".jar"; + + final File target = new File(dir.getParentFile(), name); + try { // override existing jar otherwise classloading is broken in tomee + Files.delete(file); + JarCreator.jarDir(dir, target); + } catch (final IOException e) { LOGGER.error("can't repackage enhanced jar file " + file.getName()); } Files.delete(dir); @@ -280,7 +274,7 @@ public class DeployTimeEnhancer { @Override public void characters(final char ch[], final int start, final int length) throws SAXException { if (getIt) { - paths.add(new StringBuilder().append(ch, start, length).toString()); + paths.add(String.valueOf(ch, start, length)); } } @@ -293,13 +287,4 @@ public class DeployTimeEnhancer { return paths; } } - - private static class AlreadyEnhancedFilter implements Filter { - public static final String SUFFIX = JAR_ENHANCEMENT_SUFFIX + ".jar"; - - @Override - public boolean accept(final String s) { - return !s.endsWith(SUFFIX); - } - } } Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java?rev=1513074&r1=1513073&r2=1513074&view=diff ============================================================================== --- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java (original) +++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java Mon Aug 12 08:15:25 2013 @@ -87,56 +87,68 @@ public class DataSourceFactory { "true".equalsIgnoreCase((String) properties.remove(LOG_SQL_PROPERTY))); final DataSourceCreator creator = creator(properties.remove(DATA_SOURCE_CREATOR_PROP), logSql); - DataSource ds; - if (createDataSourceFromClass(impl)) { // opposed to "by driver" - trimNotSupportedDataSourceProperties(properties); - - final ObjectRecipe recipe = new ObjectRecipe(impl); - recipe.allow(Option.CASE_INSENSITIVE_PROPERTIES); - recipe.allow(Option.IGNORE_MISSING_PROPERTIES); - recipe.allow(Option.NAMED_PARAMETERS); - recipe.setAllProperties(properties); - if (!properties.containsKey("url") && properties.containsKey("JdbcUrl")) { // depend on the datasource class so add all well known keys - recipe.setProperty("url", properties.getProperty("JdbcUrl")); - } - - final DataSource dataSource = (DataSource) recipe.create(); - - if (managed) { - if (usePool(properties)) { - ds = creator.poolManaged(name, dataSource, properties); - } else { - ds = creator.managed(name, dataSource); + final boolean useContainerLoader = "true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.resources.use-container-loader", "true")) && (impl == null || impl.getClassLoader() == DataSourceFactory.class.getClassLoader()); + final ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); + if (useContainerLoader) { + Thread.currentThread().setContextClassLoader(DataSourceFactory.class.getClassLoader()); + } + + try { + DataSource ds; + if (createDataSourceFromClass(impl)) { // opposed to "by driver" + trimNotSupportedDataSourceProperties(properties); + + final ObjectRecipe recipe = new ObjectRecipe(impl); + recipe.allow(Option.CASE_INSENSITIVE_PROPERTIES); + recipe.allow(Option.IGNORE_MISSING_PROPERTIES); + recipe.allow(Option.NAMED_PARAMETERS); + recipe.setAllProperties(properties); + if (!properties.containsKey("url") && properties.containsKey("JdbcUrl")) { // depend on the datasource class so add all well known keys + recipe.setProperty("url", properties.getProperty("JdbcUrl")); } - } else { - if (usePool(properties)) { - ds = creator.pool(name, dataSource, properties); + + final DataSource dataSource = (DataSource) recipe.create(); + + if (managed) { + if (usePool(properties)) { + ds = creator.poolManaged(name, dataSource, properties); + } else { + ds = creator.managed(name, dataSource); + } } else { - ds = dataSource; + if (usePool(properties)) { + ds = creator.pool(name, dataSource, properties); + } else { + ds = dataSource; + } } - } - } else { // by driver - if (managed) { - final XAResourceWrapper xaResourceWrapper = SystemInstance.get().getComponent(XAResourceWrapper.class); - if (xaResourceWrapper != null) { - ds = creator.poolManagedWithRecovery(name, xaResourceWrapper, impl.getName(), properties); + } else { // by driver + if (managed) { + final XAResourceWrapper xaResourceWrapper = SystemInstance.get().getComponent(XAResourceWrapper.class); + if (xaResourceWrapper != null) { + ds = creator.poolManagedWithRecovery(name, xaResourceWrapper, impl.getName(), properties); + } else { + ds = creator.poolManaged(name, impl.getName(), properties); + } } else { - ds = creator.poolManaged(name, impl.getName(), properties); + ds = creator.pool(name, impl.getName(), properties); } - } else { - ds = creator.pool(name, impl.getName(), properties); } - } - // ds and creator are associated here, not after the proxying of the next if if active - creatorByDataSource.put(ds, creator); + // ds and creator are associated here, not after the proxying of the next if if active + creatorByDataSource.put(ds, creator); - if (logSql) { - ds = (DataSource) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), - new Class<?>[]{DataSource.class}, new LoggingSqlDataSource(ds)); - } + if (logSql) { + ds = (DataSource) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), + new Class<?>[]{DataSource.class}, new LoggingSqlDataSource(ds)); + } - return ds; + return ds; + } finally { + if (useContainerLoader) { + Thread.currentThread().setContextClassLoader(oldLoader); + } + } } private static void convert(final Properties properties, final Duration duration, final String key, final String oldKey) { Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/util/classloader/URLClassLoaderFirst.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/util/classloader/URLClassLoaderFirst.java?rev=1513074&r1=1513073&r2=1513074&view=diff ============================================================================== --- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/util/classloader/URLClassLoaderFirst.java (original) +++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/util/classloader/URLClassLoaderFirst.java Mon Aug 12 08:15:25 2013 @@ -34,6 +34,7 @@ public class URLClassLoaderFirst extends // log4j is optional, moreover it will likely not work if not skipped and loaded by a temp classloader private static final boolean SKIP_LOG4J = "true".equals(SystemInstance.get().getProperty("openejb.skip.log4j", "true")) && skipLib("org.apache.log4j.Logger"); private static final boolean SKIP_MYFACES = "true".equals(SystemInstance.get().getProperty("openejb.skip.myfaces", "true")) && skipLib("org.apache.myfaces.spi.FactoryFinderProvider"); + private static final boolean SKIP_HSQLDB = skipLib("org.hsqldb.lib.HsqlTimer"); // commons-net is only in tomee-plus private static final boolean SKIP_COMMONS_NET = skipLib("org.apache.commons.net.pop3.POP3Client"); @@ -309,6 +310,7 @@ public class URLClassLoaderFirst extends } // other org packages + if (org.startsWith("hsqldb.") && SKIP_HSQLDB) return true; if (org.startsWith("codehaus.swizzle")) return true; if (org.startsWith("w3c.dom")) return true; if (org.startsWith("quartz")) return true; @@ -353,10 +355,7 @@ public class URLClassLoaderFirst extends try { final Enumeration<URL> resources = loader.getResources(classname); final Collection<URL> thisJSf = Collections.list(resources); - if (thisJSf == null || thisJSf.isEmpty()) { - return true; - } - return thisJSf.size() <= 1; + return thisJSf.isEmpty() || thisJSf.size() <= 1; } catch (final IOException e) { return true; } @@ -392,8 +391,9 @@ public class URLClassLoaderFirst extends } public static boolean shouldSkipSlf4j(final ClassLoader loader, final String name) { - return name != null && name.startsWith("org.slf4j.") - && loader.getResource(SLF4J_BINDER_CLASS).equals(findParent(loader).getResource(SLF4J_BINDER_CLASS)); + final URL resource = loader.getResource(SLF4J_BINDER_CLASS); + return name != null && name.startsWith("org.slf4j.") && resource != null + && resource.equals(findParent(loader).getResource(SLF4J_BINDER_CLASS)); } // useful method for SPI