Author: andygumbrecht
Date: Fri Dec  3 14:32:13 2010
New Revision: 1041836

URL: http://svn.apache.org/viewvc?rev=1041836&view=rev
Log:
Fixed (Possibly a Windows only issue) ClassLoader jar file locking issues which 
were caused by several factors.

1. ClassLoaderUtil was using wrong key to remove and close cached jar files, so 
added a first (most common) and fall-back strategy to create a valid removal 
key. Also added private method to close jar file loaders.

2. DeploymentLoader was not actually using the temp files it created to create 
the lookup ClassLoader.

3. DeploymentLoader was trying to delete temp jar files before jar file 
references had been removed.

The order of action is:

Create temporary ClassLoader.
Destroy temporary ClassLoader.
System.gc() - required to ensure release.
Delete temporary files.
Create application ClassLoader.
Deploy application.
Undeploy application.
Destroy application ClassLoader.
System.gc() - required to ensure release.

All files are now unlocked (and can be deleted) as expected. Previously it was 
necessary to restart OpenEJB to redeploy an application with the same name.

Modified:
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java
    openejb/trunk/openejb3/pom.xml

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java?rev=1041836&r1=1041835&r2=1041836&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java
 Fri Dec  3 14:32:13 2010
@@ -17,6 +17,12 @@
  */
 package org.apache.openejb;
 
+import org.apache.openejb.core.TempClassLoader;
+import org.apache.openejb.util.LogCategory;
+import org.apache.openejb.util.Logger;
+import org.apache.openejb.util.URLs;
+import org.apache.openejb.util.UrlCache;
+
 import java.beans.Introspector;
 import java.io.File;
 import java.io.ObjectInputStream;
@@ -30,21 +36,16 @@ import java.net.URLClassLoader;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
 import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Collections;
-import java.util.ConcurrentModificationException;
 import java.util.Set;
-import java.util.LinkedHashSet;
+import java.util.Vector;
 import java.util.jar.JarFile;
 
-import org.apache.openejb.core.TempClassLoader;
-import org.apache.openejb.util.URLs;
-import org.apache.openejb.util.Logger;
-import org.apache.openejb.util.LogCategory;
-import org.apache.openejb.util.UrlCache;
-
 /**
  * @version $Revision$ $Date$
  */
@@ -86,52 +87,184 @@ public class ClassLoaderUtil {
         return classLoader;
     }
 
+    /**
+     * Destroy a classloader as forcefully as possible.
+     *
+     * @param classLoader ClassLoader to destroy.
+     */
     public static void destroyClassLoader(ClassLoader classLoader) {
         logger.debug("Destroying classLoader " + toString(classLoader));
 
         // remove from the indexes
         Set<String> apps = appsByClassLoader.remove(classLoader);
+
         if (apps != null) {
+
+            List<ClassLoader> classLoaders;
+
             for (String appId : apps) {
-                List<ClassLoader> classLoaders = classLoadersByApp.get(appId);
+
+                classLoaders = classLoadersByApp.get(appId);
+
                 if (classLoaders != null) {
                     classLoaders.remove(classLoader);
-                    // if this is the last class loader in the app, clean up 
the app
-                    if (classLoaders.isEmpty()) {
-                        destroyClassLoader(appId);
-                    }
+                }
+
+                //If this is the last class loader in the app, clean up the app
+                if (null == classLoaders || classLoaders.isEmpty()) {
+                    destroyClassLoader(appId);
                 }
             }
         }
 
-        // clear the lame openjpa caches
+        // Clear OpenJPA caches
         cleanOpenJPACache(classLoader);
+
+        //Clear open jar files belonging to this ClassLoader
+        for (final String jar : getClosedJarFiles(classLoader)) {
+            clearSunJarFileFactoryCache(jar);
+        }
+
+        classLoader = null;
+    }
+
+    /**
+     * Dirty hack to force closure of file handles in the Oracle VM 
URLClassLoader
+     * Any URLClassLoader passed into this method will be unusable after the 
method completes.
+     *
+     * @param cl ClassLoader of expected type URLClassLoader (Silent failure)
+     */
+    private static List<String> getClosedJarFiles(final ClassLoader cl) {
+
+        final List<String> files = new ArrayList<String>();
+
+        if (null != cl && cl instanceof URLClassLoader) {
+
+            final URLClassLoader ucl = (URLClassLoader) cl;
+            Class clazz = java.net.URLClassLoader.class;
+
+            try {
+
+                java.lang.reflect.Field ucp = clazz.getDeclaredField("ucp");
+                ucp.setAccessible(true);
+                Object cp = ucp.get(ucl);
+                java.lang.reflect.Field loaders = 
cp.getClass().getDeclaredField("loaders");
+                loaders.setAccessible(true);
+                java.util.Collection c = (java.util.Collection) 
loaders.get(cp);
+                java.lang.reflect.Field loader;
+                java.util.jar.JarFile jf;
+
+                for (final Object jl : c.toArray()) {
+                    try {
+                        loader = jl.getClass().getDeclaredField("jar");
+                        loader.setAccessible(true);
+                        jf = (java.util.jar.JarFile) loader.get(jl);
+                        files.add(jf.getName());
+                        jf.close();
+                    } catch (Throwable t) {
+                        //If we got this far, this is probably not a JAR 
loader so skip it
+                    }
+                }
+            } catch (Throwable t) {
+                //Not an Oracle VM
+            }
+        }
+
+        return files;
+    }
+
+    public boolean finalizeNativeLibs(ClassLoader cl) {
+
+        boolean res = false;
+        Class classClassLoader = ClassLoader.class;
+        java.lang.reflect.Field nativeLibraries = null;
+
+        try {
+            nativeLibraries = 
classClassLoader.getDeclaredField("nativeLibraries");
+        } catch (NoSuchFieldException e1) {
+            //Ignore
+        }
+
+        if (nativeLibraries == null) {
+            return res;
+        }
+
+        nativeLibraries.setAccessible(true);
+        Object obj = null;
+
+        try {
+            obj = nativeLibraries.get(cl);
+        } catch (IllegalAccessException e1) {
+            //Ignore
+        }
+
+        if (!(obj instanceof Vector)) {
+            return res;
+        }
+
+        res = true;
+        Vector java_lang_ClassLoader_NativeLibrary = (Vector) obj;
+        java.lang.reflect.Method finalize;
+
+        for (final Object lib : java_lang_ClassLoader_NativeLibrary) {
+
+            finalize = null;
+
+            try {
+                finalize = lib.getClass().getDeclaredMethod("finalize", new 
Class[0]);
+
+                if (finalize != null) {
+
+                    finalize.setAccessible(true);
+
+                    try {
+                        finalize.invoke(lib, new Object[0]);
+                    } catch (Throwable e) {
+                        //Ignore
+                    }
+                }
+            } catch (Throwable e) {
+                //Ignore
+            }
+        }
+        return res;
     }
 
     public static void destroyClassLoader(String appId) {
-        logger.debug("Destroying classLoaders for application " + appId);
 
+        logger.debug("Destroying classLoaders for application " + appId);
         List<ClassLoader> classLoaders = classLoadersByApp.remove(appId);
+
         if (classLoaders != null) {
-            for (ClassLoader classLoader : classLoaders) {
-                // get the apps using the class loader
-                Set<String> apps = appsByClassLoader.get(classLoader);
-                if (apps == null) {
-                    apps = Collections.emptySet();
+
+            final Iterator<ClassLoader> it = classLoaders.iterator();
+            Set<String> apps;
+            ClassLoader cl;
+
+            while (it.hasNext()) {
+
+                cl = it.next();
+                apps = appsByClassLoader.get(cl);
+
+                if (null != apps) {
+                    //This app is no longer using the class loader
+                    apps.remove(appId);
                 }
 
-                // this app is no longer using the class loader
-                apps.remove(appId);
+                //If no apps are using the class loader, destroy it
+                if (null == apps || apps.isEmpty()) {
+                    it.remove();
+                    appsByClassLoader.remove(cl);
+                    destroyClassLoader(cl);
+                    cl = null;
 
-                // if no apps are using the class loader, destroy it
-                if (apps.isEmpty()) {
-                    appsByClassLoader.remove(classLoader);
-                    destroyClassLoader(classLoader);
+                    System.gc();
                 } else {
-                    logger.debug("ClassLoader " + toString(classLoader) + " 
held open by the applications" + apps);
+                    logger.debug("ClassLoader " + toString(cl) + " held open 
by the applications: " + apps);
                 }
             }
         }
+
         urlCache.releaseUrls(appId);
         clearSunJarFileFactoryCache(appId);
     }
@@ -181,17 +314,23 @@ public class ClassLoaderUtil {
                 Map ucf = (Map) urlCacheField.get(null);
 
                 List<URL> urls = new ArrayList<URL>();
-                for (Object item : fileCache.keySet()) {
-                    URL url = null;
+                File file;
+                URL url;
+
+                for (final Object item : fileCache.keySet()) {
+
+                    url = null;
+
                     if (item instanceof URL) {
                         url = (URL) item;
                     } else if (item instanceof String) {
                         url = new URI((String) item).toURL();
                     } else {
                         logger.warning("Don't know how to handle object: " + 
item.toString() + " of type: " + item.getClass().getCanonicalName() + " in Sun 
JarFileFactory cache, skipping");
+                        continue;
                     }
 
-                    File file = null;
+                    file = null;
                     try {
                         file = URLs.toFile(url);
                     } catch (IllegalArgumentException e) {
@@ -203,14 +342,31 @@ public class ClassLoaderUtil {
                     }
                 }
 
-                for (URL url : urls) {
-                    JarFile jarFile = (JarFile) fileCache.remove(url);
+                JarFile jarFile;
+                String key;
+                for (final URL jar : urls) {
+
+                    //Fudge together a sun.net.www.protocol.jar.JarFileFactory 
compatible key
+                    key = ("file:///" + new 
File(URI.create(jar.toString())).getAbsolutePath().replace('\\', '/'));
+                    jarFile = (JarFile) fileCache.remove(key);
+
                     if (jarFile == null) {
-                        continue;
+
+                        key = jar.toExternalForm();
+                        jarFile = (JarFile) fileCache.remove(key);
+
+                        if (jarFile == null) {
+                            continue;
+                        }
                     }
 
                     ucf.remove(jarFile);
-                    jarFile.close();
+
+                    try {
+                        jarFile.close();
+                    } catch (Throwable e) {
+                        //Ignore
+                    }
                 }
             }
         } catch (ConcurrentModificationException e) {
@@ -244,7 +400,8 @@ public class ClassLoaderUtil {
      * This method uses reflection and setAccessable to obtain access to the 
Sun cache.
      * The cache Class synchronizes upon itself for access to the cache Map.
      * This method completely clears the class loader cache which will impact 
preformance of object serialization.
-     * @param clazz the name of the class containing the cache field
+     *
+     * @param clazz     the name of the class containing the cache field
      * @param fieldName the name of the cache field
      */
     public static void clearSunSoftCache(Class clazz, String fieldName) {

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java?rev=1041836&r1=1041835&r2=1041836&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java
 Fri Dec  3 14:32:13 2010
@@ -17,40 +17,14 @@
  */
 package org.apache.openejb.config;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.LinkedHashSet;
-import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-import javax.xml.bind.JAXBException;
-
 import org.apache.openejb.ClassLoaderUtil;
 import org.apache.openejb.OpenEJB;
 import org.apache.openejb.OpenEJBException;
 import org.apache.openejb.api.LocalClient;
 import org.apache.openejb.api.RemoteClient;
-import org.apache.openejb.jee.Connector;
-import org.apache.openejb.loader.SystemInstance;
 import org.apache.openejb.jee.Application;
 import org.apache.openejb.jee.ApplicationClient;
+import org.apache.openejb.jee.Connector;
 import org.apache.openejb.jee.EjbJar;
 import org.apache.openejb.jee.FacesConfig;
 import org.apache.openejb.jee.JavaWsdlMapping;
@@ -63,17 +37,43 @@ import org.apache.openejb.jee.TldTaglib;
 import org.apache.openejb.jee.WebApp;
 import org.apache.openejb.jee.WebserviceDescription;
 import org.apache.openejb.jee.Webservices;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.util.AnnotationFinder;
 import org.apache.openejb.util.JarExtractor;
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Logger;
 import org.apache.openejb.util.URLs;
-import org.apache.openejb.util.UrlCache;
 import static org.apache.openejb.util.URLs.toFile;
-import org.apache.openejb.util.AnnotationFinder;
+import org.apache.openejb.util.UrlCache;
 import org.apache.xbean.finder.ResourceFinder;
 import org.apache.xbean.finder.UrlSet;
 import org.xml.sax.SAXException;
 
+import javax.xml.bind.JAXBException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
 /**
  * @version $Revision$ $Date$
  */
@@ -94,11 +94,11 @@ public class DeploymentLoader {
     public void setScanManagedBeans(boolean scan) {
         scanManagedBeans = scan;
     }
-    
+
     public boolean getScanManagedBeans() {
         return scanManagedBeans;
     }
-    
+
     public AppModule load(File jarFile) throws OpenEJBException {
         // verify we have a valid file
         String jarPath;
@@ -113,35 +113,43 @@ public class DeploymentLoader {
         // create a class loader to use for detection of module type
         // do not use this class loader for any other purposes... it is
         // non-temp class loader and usage will mess up JPA
-        ClassLoader doNotUseClassLoader = 
ClassLoaderUtil.createClassLoader(jarPath, new URL[]{baseUrl}, 
OpenEJB.class.getClassLoader());
+        ClassLoader doNotUseClassLoader = null;// = 
ClassLoaderUtil.createClassLoader(jarPath, new URL[]{baseUrl}, 
OpenEJB.class.getClassLoader());
+        File tmpFile = null;
 
         try {
             // determine the module type
             Class moduleClass;
-            File tmpFile = null;
+
             try {
                 // TODO: ClassFinder is leaking file locks, so copy the jar to 
a temp dir
                 // when we have a possible ejb-jar file (only ejb-jars result 
in a ClassFinder being used)
                 URL tempURL = baseUrl;
                 if (jarFile.isFile() && UrlCache.cacheDir != null &&
-                        !jarFile.getName().endsWith(".ear") &&
-                        !jarFile.getName().endsWith(".war") &&
-                        !jarFile.getName().endsWith(".rar") ) {
+                    !jarFile.getName().endsWith(".ear") &&
+                    !jarFile.getName().endsWith(".war") &&
+                    !jarFile.getName().endsWith(".rar")) {
                     try {
                         tmpFile = File.createTempFile("AppModule-", "", 
UrlCache.cacheDir);
                         JarExtractor.copy(URLs.toFile(baseUrl), tmpFile);
                         tempURL = tmpFile.toURI().toURL();
+
+                        doNotUseClassLoader = 
ClassLoaderUtil.createClassLoader(tmpFile.getCanonicalPath(), new 
URL[]{baseUrl}, OpenEJB.class.getClassLoader());
+
                     } catch (Exception e) {
                         throw new OpenEJBException(e);
                     }
+                } else {
+                    doNotUseClassLoader = 
ClassLoaderUtil.createClassLoader(jarPath, new URL[]{baseUrl}, 
OpenEJB.class.getClassLoader());
                 }
-                                                    
+
                 moduleClass = discoverModuleType(tempURL, 
ClassLoaderUtil.createTempClassLoader(doNotUseClassLoader), true);
             } catch (Exception e) {
                 throw new UnknownModuleTypeException("Unable to determine 
module type for jar: " + baseUrl.toExternalForm(), e);
             } finally {
-                // most likely won't work but give it a try
-                if (tmpFile != null) tmpFile.delete();
+                //Try delete here, but will not work if used in 
doNotUseClassLoader
+                if (tmpFile != null && !tmpFile.delete()) {
+                    tmpFile.deleteOnExit();
+                }
             }
 
             if (AppModule.class.equals(moduleClass)) {
@@ -189,12 +197,23 @@ public class DeploymentLoader {
 
                 return appModule;
             } else {
-                throw new UnsupportedModuleTypeException("Unsupported module 
type: "+moduleClass.getSimpleName());
+                throw new UnsupportedModuleTypeException("Unsupported module 
type: " + moduleClass.getSimpleName());
             }
         } finally {
             // if the application was unpacked appId used to create this class 
loader will be wrong
             // We can safely destroy this class loader in either case, as it 
was not use by any modules
-            ClassLoaderUtil.destroyClassLoader(doNotUseClassLoader);
+            if (null != doNotUseClassLoader) {
+                ClassLoaderUtil.destroyClassLoader(doNotUseClassLoader);
+                doNotUseClassLoader = null;
+
+                //Really try an flush this classloader out
+                System.gc();
+            }
+
+            //Try delete here, but will not work if used in doNotUseClassLoader
+            if (tmpFile != null && !tmpFile.delete()) {
+                tmpFile.deleteOnExit();
+            }
         }
     }
 
@@ -437,9 +456,9 @@ public class DeploymentLoader {
         String mainClass = null;
         if (manifestUrl != null) {
             try {
-            InputStream is = manifestUrl.openStream();
-            Manifest manifest = new Manifest(is);
-            mainClass = 
manifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
+                InputStream is = manifestUrl.openStream();
+                Manifest manifest = new Manifest(is);
+                mainClass = 
manifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
             } catch (IOException e) {
                 throw new OpenEJBException("Unable to determine Main-Class 
defined in META-INF/MANIFEST.MF file", e);
             }
@@ -451,7 +470,7 @@ public class DeploymentLoader {
 
         ApplicationClient applicationClient = null;
         URL clientXmlUrl = descriptors.get("application-client.xml");
-        if (clientXmlUrl != null){
+        if (clientXmlUrl != null) {
             applicationClient = 
ReadDescriptors.readApplicationClient(clientXmlUrl);
         }
 
@@ -471,7 +490,7 @@ public class DeploymentLoader {
 
         EjbJar ejbJar = null;
         URL ejbJarXmlUrl = descriptors.get("ejb-jar.xml");
-        if (ejbJarXmlUrl != null){
+        if (ejbJarXmlUrl != null) {
             ejbJar = ReadDescriptors.readEjbJar(ejbJarXmlUrl);
         }
 
@@ -489,7 +508,7 @@ public class DeploymentLoader {
         addWebservices(ejbModule);
         return ejbModule;
     }
-    
+
     protected void addWebModule(AppModule appModule, URL warUrl, ClassLoader 
parentClassLoader, String contextRoot, String moduleName) throws 
OpenEJBException {
         String warPath = URLs.toFilePath(warUrl);
         WebModule webModule = createWebModule(appModule.getJarLocation(), 
warPath, parentClassLoader, contextRoot, moduleName);
@@ -503,7 +522,7 @@ public class DeploymentLoader {
         if (ejbJarXmlUrl == null) {
             if (webModule.getWebApp() != null && 
webModule.getWebApp().isMetadataComplete()) {
                 addEjbModule = false;
-            } else {                
+            } else {
                 // get urls in web application
                 List<URL> urls = null;
                 try {
@@ -525,23 +544,23 @@ public class DeploymentLoader {
                         }
                     }
                 }
-                
+
                 addEjbModule = checkAnnotations(urls, webClassLoader, true, 
false) != null;
             }
         } else {
             addEjbModule = true;
             ejbJar = ReadDescriptors.readEjbJar(ejbJarXmlUrl);
         }
-        
+
         if (addEjbModule) {
             EjbModule ejbModule = new EjbModule(webClassLoader, 
webModule.getModuleId(), warPath, ejbJar, null);
             ejbModule.getAltDDs().putAll(webModule.getAltDDs());
-            
+
             addWebservices(ejbModule);
-            
+
             appModule.getEjbModules().add(ejbModule);
         }
-                       
+
         // Persistence Units
         addPersistenceUnits(appModule);
     }
@@ -560,7 +579,7 @@ public class DeploymentLoader {
 
         WebApp webApp = null;
         URL webXmlUrl = descriptors.get("web.xml");
-        if (webXmlUrl != null){
+        if (webXmlUrl != null) {
             webApp = ReadDescriptors.readWebApp(webXmlUrl);
         }
 
@@ -644,7 +663,7 @@ public class DeploymentLoader {
         }
 
         // parse the webservices.xml file
-        Map<URL,JavaWsdlMapping> jaxrpcMappingCache = new 
HashMap<URL,JavaWsdlMapping>();
+        Map<URL, JavaWsdlMapping> jaxrpcMappingCache = new HashMap<URL, 
JavaWsdlMapping>();
         Webservices webservices = 
ReadDescriptors.readWebservices(webservicesUrl);
         wsModule.setWebservices(webservices);
         if ("file".equals(webservicesUrl.getProtocol())) {
@@ -723,19 +742,21 @@ public class DeploymentLoader {
             }
         }
     }
+
     /**
      * Finds all faces configuration files and stores them in the WebModule
+     *
      * @param webModule
      * @throws OpenEJBException
      */
     private static void addFacesConfigs(WebModule webModule) throws 
OpenEJBException {
-       
//*************************IMPORTANT*******************************************
-       // This method is an exact copy of 
org.apache.openejb.tomcat.catalina.TomcatWebAppBuilder.addFacesConfigs(WebModule
 webModule)
-       // Any changes to this method here would most probably need to also be 
reflected in the TomcatWebAppBuilder.addFacesConfigs method.
-       
//*************************IMPORTANT*******************************************
-       // TODO : kmalhi :: Add support to scrape META-INF/faces-config.xml in 
jar files
-       // look at section 10.4.2 of the JSF v1.2 spec, bullet 1 for details
-       Set<URL> facesConfigLocations = new HashSet<URL>();
+        
//*************************IMPORTANT*******************************************
+        // This method is an exact copy of 
org.apache.openejb.tomcat.catalina.TomcatWebAppBuilder.addFacesConfigs(WebModule
 webModule)
+        // Any changes to this method here would most probably need to also be 
reflected in the TomcatWebAppBuilder.addFacesConfigs method.
+        
//*************************IMPORTANT*******************************************
+        // TODO : kmalhi :: Add support to scrape META-INF/faces-config.xml in 
jar files
+        // look at section 10.4.2 of the JSF v1.2 spec, bullet 1 for details
+        Set<URL> facesConfigLocations = new HashSet<URL>();
 
         // web.xml contains faces config locations in the context parameter 
javax.faces.CONFIG_FILES
         File warFile = new File(webModule.getJarLocation());
@@ -743,62 +764,63 @@ public class DeploymentLoader {
         if (webApp != null) {
             List<ParamValue> contextParam = webApp.getContextParam();
             for (ParamValue value : contextParam) {
-                               boolean foundContextParam = 
value.getParamName().trim().equals("javax.faces.CONFIG_FILES");
-                               if(foundContextParam){
-                                       // the value is a comma separated list 
of config files
-                                       String commaDelimitedListOfFiles = 
value.getParamValue().trim();
-                                       String[] configFiles = 
commaDelimitedListOfFiles.split(",");
-                                       // trim any extra spaces in each file
-                                       String[] trimmedConfigFiles = new 
String[configFiles.length];
-                                       for (int i = 0; i < configFiles.length; 
i++) {
-                                               trimmedConfigFiles[i] = 
configFiles[i].trim();
-                                       }
-                                       // convert each file to a URL and add 
it to facesConfigLocations
-                                       for (String location : 
trimmedConfigFiles) {
-                                               if(!location.startsWith("/"))
-                                                       logger.error("A faces 
configuration file should be context relative when specified in web.xml. Please 
fix the value of context parameter javax.faces.CONFIG_FILES for the file 
"+location);
-                           try {
-                               File file = new File(warFile, 
location).getCanonicalFile().getAbsoluteFile();
-                               URL url = file.toURI().toURL();
-                               facesConfigLocations.add(url);
-                              
-                           } catch (IOException e) {
-                               logger.error("Faces configuration file location 
bad: " + location, e);
-                           }                                           
-                                       }
-                                       break;
-                               }
-                       }
-               
+                boolean foundContextParam = 
value.getParamName().trim().equals("javax.faces.CONFIG_FILES");
+                if (foundContextParam) {
+                    // the value is a comma separated list of config files
+                    String commaDelimitedListOfFiles = 
value.getParamValue().trim();
+                    String[] configFiles = 
commaDelimitedListOfFiles.split(",");
+                    // trim any extra spaces in each file
+                    String[] trimmedConfigFiles = new 
String[configFiles.length];
+                    for (int i = 0; i < configFiles.length; i++) {
+                        trimmedConfigFiles[i] = configFiles[i].trim();
+                    }
+                    // convert each file to a URL and add it to 
facesConfigLocations
+                    for (String location : trimmedConfigFiles) {
+                        if (!location.startsWith("/"))
+                            logger.error("A faces configuration file should be 
context relative when specified in web.xml. Please fix the value of context 
parameter javax.faces.CONFIG_FILES for the file " + location);
+                        try {
+                            File file = new File(warFile, 
location).getCanonicalFile().getAbsoluteFile();
+                            URL url = file.toURI().toURL();
+                            facesConfigLocations.add(url);
+
+                        } catch (IOException e) {
+                            logger.error("Faces configuration file location 
bad: " + location, e);
+                        }
+                    }
+                    break;
+                }
+            }
+
         }
 
         // Search for WEB-INF/faces-config.xml
-        File webInf = new File(warFile,"WEB-INF");
-        if(webInf.isDirectory()){
-               File facesConfigFile = new File(webInf,"faces-config.xml");
-               if(facesConfigFile.exists()){
-                       try {
-                                       facesConfigFile = 
facesConfigFile.getCanonicalFile().getAbsoluteFile();
-                                       URL url = 
facesConfigFile.toURI().toURL();
-                                       facesConfigLocations.add(url);
-                               } catch (IOException e) {
-                                       // TODO: kmalhi:: Remove the 
printStackTrace after testing
-                                       e.printStackTrace();
-                               }
-               }
+        File webInf = new File(warFile, "WEB-INF");
+        if (webInf.isDirectory()) {
+            File facesConfigFile = new File(webInf, "faces-config.xml");
+            if (facesConfigFile.exists()) {
+                try {
+                    facesConfigFile = 
facesConfigFile.getCanonicalFile().getAbsoluteFile();
+                    URL url = facesConfigFile.toURI().toURL();
+                    facesConfigLocations.add(url);
+                } catch (IOException e) {
+                    // TODO: kmalhi:: Remove the printStackTrace after testing
+                    e.printStackTrace();
+                }
+            }
         }
         // load the faces configuration files
         // TODO:kmalhi:: Its good to have separate FacesConfig objects for 
multiple configuration files, but what if there is a conflict where the same
         // managebean is declared in two different files, which one wins? -- 
check the jsf spec, Hopefully JSF should be able to check for this and
         // flag an error and not allow the application to be deployed.
         for (URL location : facesConfigLocations) {
-           FacesConfig facesConfig = ReadDescriptors.readFacesConfig(location);
+            FacesConfig facesConfig = 
ReadDescriptors.readFacesConfig(location);
             webModule.getFacesConfigs().add(facesConfig);
             if ("file".equals(location.getProtocol())) {
                 webModule.getWatchedResources().add(URLs.toFilePath(location));
             }
         }
     }
+
     private static Set<URL> scanClassLoaderForTagLibs(ClassLoader 
parentClassLoader) throws OpenEJBException {
         Set<URL> urls = new HashSet<URL>();
         if (parentClassLoader == null) return urls;
@@ -865,7 +887,7 @@ public class DeploymentLoader {
         if (files.isEmpty()) return urls;
 
         // recursively scan the directories
-        while(!files.isEmpty()) {
+        while (!files.isEmpty()) {
             File file = files.removeFirst();
             if (file.isDirectory()) {
                 files.addAll(Arrays.asList(file.listFiles()));
@@ -915,7 +937,7 @@ public class DeploymentLoader {
         return urls;
     }
 
-    protected  ConnectorModule createConnectorModule(String appId, String 
rarPath, ClassLoader parentClassLoader, String moduleId) throws 
OpenEJBException {
+    protected ConnectorModule createConnectorModule(String appId, String 
rarPath, ClassLoader parentClassLoader, String moduleId) throws 
OpenEJBException {
         URL baseUrl;// unpack the rar file
         File rarFile = new File(rarPath);
         rarFile = unpack(rarFile);
@@ -925,7 +947,7 @@ public class DeploymentLoader {
         Map<String, URL> descriptors = getDescriptors(baseUrl);
         Connector connector = null;
         URL rarXmlUrl = descriptors.get("ra.xml");
-        if (rarXmlUrl != null){
+        if (rarXmlUrl != null) {
             connector = ReadDescriptors.readConnector(rarXmlUrl);
         }
 
@@ -989,7 +1011,7 @@ public class DeploymentLoader {
                 if (!urlString.contains("META-INF/persistence.xml")) {
                     logger.info("AltDD persistence.xml -> " + urlString);
                 }
-                
+
                 persistenceUrls.add(descriptor);
             }
         }
@@ -1053,7 +1075,7 @@ public class DeploymentLoader {
 
             // don't add and log if the same key/value is already in the map
             if (value.equals(map.get(key))) continue;
-            
+
             if (log) logger.info("AltDD " + key + " -> " + 
value.toExternalForm());
             map.put(key, value);
         }
@@ -1062,7 +1084,7 @@ public class DeploymentLoader {
     }
 
     private static Map<String, URL> getWebDescriptors(File warFile) throws 
IOException {
-        Map<String, URL> descriptors = new TreeMap<String,URL>();
+        Map<String, URL> descriptors = new TreeMap<String, URL>();
 
         // xbean resource finder has a bug when you use any uri but "META-INF"
         // and the jar file does not contain a directory entry for the uri
@@ -1099,7 +1121,7 @@ public class DeploymentLoader {
             String pathname = warUrl.getPath();
 
             // we only support file based jar urls
-            if (!pathname .startsWith("file:")) {
+            if (!pathname.startsWith("file:")) {
                 return null;
             }
 
@@ -1120,17 +1142,17 @@ public class DeploymentLoader {
     }
 
     @SuppressWarnings({"unchecked"})
-    public static <T>T unmarshal(Class<T> type, String descriptor, URL url) 
throws OpenEJBException {
+    public static <T> T unmarshal(Class<T> type, String descriptor, URL url) 
throws OpenEJBException {
         try {
             return (T) JaxbJavaee.unmarshalJavaee(type, url.openStream());
         } catch (SAXException e) {
-            throw new OpenEJBException("Cannot parse the " + descriptor + " 
file: "+ url.toExternalForm(), e);
+            throw new OpenEJBException("Cannot parse the " + descriptor + " 
file: " + url.toExternalForm(), e);
         } catch (JAXBException e) {
-            throw new OpenEJBException("Cannot unmarshall the " + descriptor + 
" file: "+ url.toExternalForm(), e);
+            throw new OpenEJBException("Cannot unmarshall the " + descriptor + 
" file: " + url.toExternalForm(), e);
         } catch (IOException e) {
-            throw new OpenEJBException("Cannot read the " + descriptor + " 
file: "+ url.toExternalForm(), e);
+            throw new OpenEJBException("Cannot read the " + descriptor + " 
file: " + url.toExternalForm(), e);
         } catch (Exception e) {
-            throw new OpenEJBException("Encountered unknown error parsing the 
" + descriptor + " file: "+ url.toExternalForm(), e);
+            throw new OpenEJBException("Encountered unknown error parsing the 
" + descriptor + " file: " + url.toExternalForm(), e);
         }
     }
 
@@ -1187,7 +1209,7 @@ public class DeploymentLoader {
         if (descriptors.containsKey("ejb-jar.xml")) {
             return EjbModule.class;
         }
-        
+
         URL manifestUrl = descriptors.get("MANIFEST.MF");
         if (scanPotentialClientModules && manifestUrl != null) {
             // In this case scanPotentialClientModules really means "require 
application-client.xml"
@@ -1218,6 +1240,7 @@ public class DeploymentLoader {
 
             AnnotationFinder.Filter filter = new AnnotationFinder.Filter() {
                 final String packageName = 
LocalClient.class.getName().replace("LocalClient", "");
+
                 public boolean accept(String annotationName) {
                     if (scanPotentialEjbModules) {
                         if (annotationName.startsWith("javax.ejb.")) {
@@ -1240,9 +1263,9 @@ public class DeploymentLoader {
                 cls = EjbModule.class;
             }
 
-            if (otherTypes.size() > 0){
+            if (otherTypes.size() > 0) {
                 // We may want some ordering/sorting if we add more type 
scanning
-                cls =otherTypes.iterator().next();
+                cls = otherTypes.iterator().next();
             }
         }
         return cls;

Modified: openejb/trunk/openejb3/pom.xml
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/pom.xml?rev=1041836&r1=1041835&r2=1041836&view=diff
==============================================================================
--- openejb/trunk/openejb3/pom.xml (original)
+++ openejb/trunk/openejb3/pom.xml Fri Dec  3 14:32:13 2010
@@ -277,7 +277,7 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-release-plugin</artifactId>
-        <version>2.0-beta-9</version>
+        <version>2.0</version>
         <configuration>
           <useReleaseProfile>false</useReleaseProfile>
           <goals>deploy</goals>


Reply via email to