Author: rmannibucau Date: Tue Mar 5 14:37:53 2013 New Revision: 1452812 URL: http://svn.apache.org/r1452812 Log: TOMEE-783 virtual webapp classloader doesn't work at all
Added: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/QuickContextXmlParser.java Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java tomee/tomee/trunk/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/LazyStopWebappLoader.java tomee/tomee/trunk/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java?rev=1452812&r1=1452811&r2=1452812&view=diff ============================================================================== --- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java (original) +++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java Tue Mar 5 14:37:53 2013 @@ -847,6 +847,13 @@ public class DeploymentLoader implements } webUrls.addAll(addedUrls); + // context.xml can define some additional libraries + final File contextXml = new File(warFile, "META-INF/context.xml"); + if (contextXml.exists()) { + final QuickContextXmlParser parser = QuickContextXmlParser.parse(contextXml); + webUrls.addAll(parser.getAdditionalURLs()); + } + final URL[] webUrlsArray = webUrls.toArray(new URL[webUrls.size()]); // in TomEE this is done in init hook since we don't manage tomee webapp classloader Added: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/QuickContextXmlParser.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/QuickContextXmlParser.java?rev=1452812&view=auto ============================================================================== --- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/QuickContextXmlParser.java (added) +++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/QuickContextXmlParser.java Tue Mar 5 14:37:53 2013 @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.config; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Locale; +import java.util.Set; +import java.util.StringTokenizer; + +public class QuickContextXmlParser extends DefaultHandler { + private static final SAXParserFactory FACTORY = SAXParserFactory.newInstance(); + static { + FACTORY.setNamespaceAware(true); + FACTORY.setValidating(false); + } + + private String virtualClasspath = ""; + + @Override + public void startElement(final String uri, final String localName, + final String qName, final Attributes attributes) throws SAXException { + if ("Loader".equalsIgnoreCase(localName)) { + final String className = attributes.getValue("className"); + if ("org.apache.catalina.loader.VirtualWebappLoader".equals(className)) { + virtualClasspath = attributes.getValue("virtualClasspath"); + } // else ? + } + } + + public Collection<URL> getAdditionalURLs() { + final StringTokenizer tkn = new StringTokenizer(virtualClasspath, ";"); + final Set<URL> set = new LinkedHashSet<URL>(); + while (tkn.hasMoreTokens()) { + String token = tkn.nextToken().trim(); + if (token.isEmpty()) { + continue; + } + + if (token.endsWith("*.jar")) { + token = token.substring(0, token.length() - "*.jar".length()); + + final File directory = new File(token); + if (!directory.isDirectory()) { + continue; + } + + final String filenames[] = directory.list(); + Arrays.sort(filenames); + + for (final String rawFilename : filenames) { + final String filename = rawFilename.toLowerCase(Locale.ENGLISH); + if (!filename.endsWith(".jar")) { + continue; + } + + final File file = new File(directory, rawFilename); + if (!file.isFile()) { + continue; + } + + try { + set.add(file.toURI().toURL()); + } catch (MalformedURLException e) { + // no-op + } + } + } else { + // single file or directory + final File file = new File(token); + if (!file.exists()) { + continue; + } + + try { + set.add(file.toURI().toURL()); + } catch (MalformedURLException e) { + // no-op + } + } + } + return set; + } + + public static QuickContextXmlParser parse(final File contextXml) { + final QuickContextXmlParser handler = new QuickContextXmlParser(); + try { + final SAXParser parser = FACTORY.newSAXParser(); + parser.parse(contextXml, handler); + } catch (final Exception e) { + // no-op: not parseable so ignoring + } + return handler; + } +} Modified: tomee/tomee/trunk/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/LazyStopWebappLoader.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/LazyStopWebappLoader.java?rev=1452812&r1=1452811&r2=1452812&view=diff ============================================================================== --- tomee/tomee/trunk/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/LazyStopWebappLoader.java (original) +++ tomee/tomee/trunk/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/LazyStopWebappLoader.java Tue Mar 5 14:37:53 2013 @@ -18,9 +18,9 @@ package org.apache.tomee.catalina; import org.apache.catalina.Context; import org.apache.catalina.LifecycleException; -import org.apache.catalina.loader.WebappLoader; +import org.apache.catalina.loader.VirtualWebappLoader; -public class LazyStopWebappLoader extends WebappLoader { +public class LazyStopWebappLoader extends VirtualWebappLoader { private static String currentAppId = null; private Context standardContext = null; @@ -74,4 +74,9 @@ public class LazyStopWebappLoader extend } return standardContext.getName(); } + + @Override + public String toString() { + return "LazyStop" + super.toString(); + } } Modified: tomee/tomee/trunk/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java?rev=1452812&r1=1452811&r2=1452812&view=diff ============================================================================== --- tomee/tomee/trunk/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java (original) +++ tomee/tomee/trunk/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java Tue Mar 5 14:37:53 2013 @@ -47,6 +47,7 @@ import org.apache.catalina.deploy.Naming import org.apache.catalina.deploy.ResourceBase; import org.apache.catalina.ha.CatalinaCluster; import org.apache.catalina.ha.tcp.SimpleTcpCluster; +import org.apache.catalina.loader.VirtualWebappLoader; import org.apache.catalina.loader.WebappClassLoader; import org.apache.catalina.loader.WebappLoader; import org.apache.catalina.session.StandardManager; @@ -104,6 +105,7 @@ import org.apache.openejb.server.httpd.E import org.apache.openejb.spi.ContainerSystem; import org.apache.openejb.util.LogCategory; import org.apache.openejb.util.Logger; +import org.apache.openejb.util.reflection.Reflections; import org.apache.tomcat.InstanceManager; import org.apache.tomcat.util.digester.Digester; import org.apache.tomee.catalina.cluster.ClusterObserver; @@ -1017,12 +1019,35 @@ public class TomcatWebAppBuilder impleme sc.setSessionTrackingModes(newModes); } } + initContextLoader(standardContext); + + + } + + private void initContextLoader(final StandardContext standardContext) { + final Loader standardContextLoader = standardContext.getLoader(); + if (standardContextLoader != null + && !VirtualWebappLoader.class.equals(standardContextLoader.getClass()) + && !WebappLoader.class.equals(standardContextLoader.getClass())) { + // custom loader, we don't know it + // and since we don't have a full delegate pattern for our lazy stop loader + // simply skip lazy stop loader - normally sides effect will be an early shutdown for ears and some particular features + // only affecting the app if the classes were not laoded at all + return; + } // we just want to wrap it to lazy stop it (afterstop) // to avoid classnotfound in @PreDestoy or destroyApplication() - final WebappLoader loader = new LazyStopWebappLoader(standardContext); + final VirtualWebappLoader loader = new LazyStopWebappLoader(standardContext); loader.setDelegate(standardContext.getDelegate()); loader.setLoaderClass(LazyStopWebappClassLoader.class.getName()); + + if (VirtualWebappLoader.class.isInstance(standardContextLoader)) { + final VirtualWebappLoader vwl = VirtualWebappLoader.class.cast(standardContextLoader); + loader.setSearchVirtualFirst(vwl.getSearchVirtualFirst()); + loader.setVirtualClasspath(String.class.cast(Reflections.get(vwl, "virtualClasspath"))); + } + final Loader lazyStopLoader = new LazyStopLoader(loader); standardContext.setLoader(lazyStopLoader); }