Commits

Anonymous committed 1309569

Refactor finder classes to use ClassLoaderInterface instead of a ClassLoader

git-svn-id: http://svn.opensymphony.com/svn/xwork/trunk@1962e221344d-f017-0410-9bd5-d282ab1896d7

Comments (0)

Files changed (6)

src/java/com/opensymphony/xwork2/util/finder/ClassFinder.java

-/**
- * 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.
+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
  */
 package com.opensymphony.xwork2.util.finder;
 
 import java.util.jar.JarInputStream;
 
 /**
- * ClassFinder searches the classpath of the specified classloader for
+ * ClassFinder searches the classpath of the specified ClassLoaderInterface for
  * packages, classes, constructors, methods, or fields with specific annotations.
  *
  * For security reasons ASM is used to find the annotations.  Classes are not
     private final Map<String, List<Info>> annotated = new HashMap<String, List<Info>>();
     private final Map<String, ClassInfo> classInfos = new LinkedHashMap<String, ClassInfo>();
 
-    private final ClassLoader classLoader;
     private final List<String> classesNotLoaded = new ArrayList<String>();
 
     private boolean extractBaseInterfaces;
+    private ClassLoaderInterface classLoaderInterface;
 
     /**
-     * Creates a ClassFinder that will search the urls in the specified classloader
-     * excluding the urls in the classloader's parent.
+     * Creates a ClassFinder that will search the urls in the specified ClassLoaderInterface
+     * excluding the urls in the ClassLoaderInterface's parent.
      *
-     * To include the parent classloader, use:
+     * To include the parent ClassLoaderInterface, use:
      *
-     *    new ClassFinder(classLoader, false);
+     *    new ClassFinder(ClassLoaderInterface, false);
      *
      * To exclude the parent's parent, use:
      *
-     *    new ClassFinder(classLoader, classLoader.getParent().getParent());
+     *    new ClassFinder(ClassLoaderInterface, ClassLoaderInterface.getParent().getParent());
      *
      * @param classLoader source of classes to scan
      * @throws Exception if something goes wrong
      */
-    public ClassFinder(ClassLoader classLoader) throws Exception {
+    public ClassFinder(ClassLoaderInterface classLoader) throws Exception {
         this(classLoader, true);
     }
 
     /**
-     * Creates a ClassFinder that will search the urls in the specified classloader.
+     * Creates a ClassFinder that will search the urls in the specified ClassLoaderInterface.
      *
      * @param classLoader source of classes to scan
-     * @param excludeParent Allegedly excludes classes from parent classloader, whatever that might mean
+     * @param excludeParent Allegedly excludes classes from parent ClassLoaderInterface, whatever that might mean
      * @throws Exception if something goes wrong.
      */
-    public ClassFinder(ClassLoader classLoader, boolean excludeParent) throws Exception {
+    public ClassFinder(ClassLoaderInterface classLoader, boolean excludeParent) throws Exception {
         this(classLoader, getUrls(classLoader, excludeParent));
     }
 
     /**
      * Creates a ClassFinder that will search the urls in the specified classloader excluding
-     * the urls in the 'exclude' classloader.
+     * the urls in the 'exclude' ClassLoaderInterface.
      *
      * @param classLoader source of classes to scan
      * @param exclude source of classes to exclude from scanning
      * @throws Exception if something goes wrong
      */
-    public ClassFinder(ClassLoader classLoader, ClassLoader exclude) throws Exception {
+    public ClassFinder(ClassLoaderInterface classLoader, ClassLoaderInterface exclude) throws Exception {
         this(classLoader, getUrls(classLoader, exclude));
     }
 
-    public ClassFinder(ClassLoader classLoader, URL url) {
+    public ClassFinder(ClassLoaderInterface classLoader, URL url) {
         this(classLoader, Arrays.asList(url));
     }
 
-    public ClassFinder(ClassLoader classLoader, String... dirNames) {
+    public ClassFinder(ClassLoaderInterface classLoader, String... dirNames) {
         this(classLoader, getURLs(classLoader, dirNames));
     }
 
-    public ClassFinder(ClassLoader classLoader, Collection<URL> urls) {
-        this(classLoader, urls, false);
+    public ClassFinder(ClassLoaderInterface classLoaderInterface, Collection<URL> urls) {
+        this(classLoaderInterface, urls, false);
     }
 
-    public ClassFinder(ClassLoader classLoader, Collection<URL> urls, boolean extractBaseInterfaces) {
-        this(classLoader, urls, extractBaseInterfaces, new HashSet(){
+    public ClassFinder(ClassLoaderInterface classLoaderInterface, Collection<URL> urls, boolean extractBaseInterfaces) {
+        this(classLoaderInterface, urls, extractBaseInterfaces, new HashSet(){
             {
                 add("jar");
             }
         });
     }
 
-    public ClassFinder(ClassLoader classLoader, Collection<URL> urls, boolean extractBaseInterfaces, Set<String> protocols) {
-        this.classLoader = classLoader;
+    public ClassFinder(ClassLoaderInterface classLoaderInterface, Collection<URL> urls, boolean extractBaseInterfaces, Set<String> protocols) {
+        this.classLoaderInterface = classLoaderInterface;
         this.extractBaseInterfaces = extractBaseInterfaces;
 
         List<String> classNames = new ArrayList<String>();
     }
 
     public ClassFinder(List<Class> classes){
-        this.classLoader = null;
+        this.classLoaderInterface = null;
         List<Info> infos = new ArrayList<Info>();
         List<Package> packages = new ArrayList<Package>();
         for (Class clazz : classes) {
         return classes;
     }
 
-    private static List<URL> getURLs(ClassLoader classLoader, String[] dirNames) {
+    private static List<URL> getURLs(ClassLoaderInterface classLoader, String[] dirNames) {
         List<URL> urls = new ArrayList<URL>();
         for (String dirName : dirNames) {
             try {
         return urls;
     }
 
-    private static Collection<URL> getUrls(ClassLoader classLoader, boolean excludeParent) throws IOException {
-        return getUrls(classLoader, excludeParent? classLoader.getParent() : null);
+    private static Collection<URL> getUrls(ClassLoaderInterface classLoaderInterface, boolean excludeParent) throws IOException {
+        return getUrls(classLoaderInterface, excludeParent? classLoaderInterface.getParent() : null);
     }
 
-    private static Collection<URL> getUrls(ClassLoader classLoader, ClassLoader excludeParent) throws IOException {
+    private static Collection<URL> getUrls(ClassLoaderInterface classLoader, ClassLoaderInterface excludeParent) throws IOException {
         UrlSet urlSet = new UrlSet(classLoader);
         if (excludeParent != null){
             urlSet = urlSet.exclude(excludeParent);
             if (clazz != null) return clazz;
             if (notFound != null) throw notFound;
             try {
-                this.clazz = classLoader.loadClass(name);
+                this.clazz = classLoaderInterface.loadClass(name);
                 return clazz;
             } catch (ClassNotFoundException notFound) {
                 classesNotLoaded.add(name);
             className = className.replace('.', '/') + ".class";
         }
         try {
-            URL resource = classLoader.getResource(className);
+            URL resource = classLoaderInterface.getResource(className);
             if (resource != null) {
                 InputStream in = resource.openStream();
                 try {

src/java/com/opensymphony/xwork2/util/finder/ClassLoaderInterface.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2.util.finder;
+
+import java.net.URL;
+import java.util.Enumeration;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Classes implementing this interface can find resources and load classes, usually delegating to a class
+ * loader 
+ */
+public interface ClassLoaderInterface {
+
+    //key used to add the current ClassLoaderInterface to ActionContext
+    public final String CLASS_LOADER_INTERFACE = "__current_class_loader_interface";
+
+    Class<?> loadClass(String name) throws ClassNotFoundException;
+
+    URL getResource(String name);
+
+    public Enumeration<URL> getResources(String name) throws IOException;
+
+    public InputStream getResourceAsStream(String name) throws IOException;
+
+    ClassLoaderInterface getParent();
+}

src/java/com/opensymphony/xwork2/util/finder/ClassLoaderInterfaceDelegate.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2.util.finder;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+
+/**
+ * Default implementation of ClassLoaderInterface, which delegates to an actual ClassLoader
+ */
+public class ClassLoaderInterfaceDelegate implements ClassLoaderInterface {
+    private ClassLoader classLoader;
+
+    public ClassLoaderInterfaceDelegate(ClassLoader classLoader) {
+        this.classLoader = classLoader;
+    }
+
+    public Class<?> loadClass(String name) throws ClassNotFoundException {
+        return classLoader.loadClass(name);
+    }
+
+    public URL getResource(String className) {
+        return classLoader.getResource(className);
+    }
+
+    public Enumeration<URL> getResources(String name) throws IOException {
+        return classLoader.getResources(name);
+    }
+
+    public InputStream getResourceAsStream(String name) {
+        return getResourceAsStream(name);
+    }
+
+    public ClassLoaderInterface getParent() {
+        return classLoader.getParent() != null ? new ClassLoaderInterfaceDelegate(classLoader.getParent()) : null;
+    }
+}

src/java/com/opensymphony/xwork2/util/finder/ResourceFinder.java

-/**
- * 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.
+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
  */
 package com.opensymphony.xwork2.util.finder;
 
 
     private final URL[] urls;
     private final String path;
-    private final ClassLoader classLoader;
+    private final ClassLoaderInterface classLoaderInterface;
     private final List<String> resourcesNotLoaded = new ArrayList<String>();
 
     public ResourceFinder(URL... urls) {
-        this(null, Thread.currentThread().getContextClassLoader(), urls);
+        this(null, new ClassLoaderInterfaceDelegate(Thread.currentThread().getContextClassLoader()), urls);
     }
 
     public ResourceFinder(String path) {
-        this(path, Thread.currentThread().getContextClassLoader(), null);
+        this(path, new ClassLoaderInterfaceDelegate(Thread.currentThread().getContextClassLoader()), null);
     }
 
     public ResourceFinder(String path, URL... urls) {
-        this(path, Thread.currentThread().getContextClassLoader(), urls);
+        this(path, new ClassLoaderInterfaceDelegate(Thread.currentThread().getContextClassLoader()), urls);
     }
 
-    public ResourceFinder(String path, ClassLoader classLoader) {
-        this(path, classLoader, null);
+    public ResourceFinder(String path, ClassLoaderInterface classLoaderInterface) {
+        this(path, classLoaderInterface, null);
     }
 
-    public ResourceFinder(String path, ClassLoader classLoader, URL... urls) {
+    public ResourceFinder(String path, ClassLoaderInterface classLoaderInterface, URL... urls) {
         if (path == null){
             path = "";
         } else if (path.length() > 0 && !path.endsWith("/")) {
         }
         this.path = path;
 
-        if (classLoader == null) {
-            classLoader = Thread.currentThread().getContextClassLoader();
-        }
-        this.classLoader = classLoader;
+        this.classLoaderInterface = classLoaderInterface == null ? new ClassLoaderInterfaceDelegate(Thread.currentThread().getContextClassLoader()) : classLoaderInterface ;
 
         for (int i = 0; urls != null && i < urls.length; i++) {
             URL url = urls[i];
      */
     public Class findClass(String uri) throws IOException, ClassNotFoundException {
         String className = findString(uri);
-        return (Class) classLoader.loadClass(className);
+        return (Class) classLoaderInterface.loadClass(className);
     }
 
     /**
         List<Class> classes = new ArrayList<Class>();
         List<String> strings = findAllStrings(uri);
         for (String className : strings) {
-            Class clazz = classLoader.loadClass(className);
+            Class clazz = classLoaderInterface.loadClass(className);
             classes.add(clazz);
         }
         return classes;
         List<String> strings = findAvailableStrings(uri);
         for (String className : strings) {
             try {
-                Class clazz = classLoader.loadClass(className);
+                Class clazz = classLoaderInterface.loadClass(className);
                 classes.add(clazz);
             } catch (Exception notAvailable) {
                 resourcesNotLoaded.add(className);
         for (Map.Entry<String, String> entry : map.entrySet()) {
             String string = entry.getKey();
             String className = entry.getValue();
-            Class clazz = classLoader.loadClass(className);
+            Class clazz = classLoaderInterface.loadClass(className);
             classes.put(string, clazz);
         }
         return classes;
             String string = entry.getKey();
             String className = entry.getValue();
             try {
-                Class clazz = classLoader.loadClass(className);
+                Class clazz = classLoaderInterface.loadClass(className);
                 classes.put(string, clazz);
             } catch (Exception notAvailable) {
                 resourcesNotLoaded.add(className);
      */
     public Class findImplementation(Class interfase) throws IOException, ClassNotFoundException {
         String className = findString(interfase.getName());
-        Class impl = classLoader.loadClass(className);
+        Class impl = classLoaderInterface.loadClass(className);
         if (!interfase.isAssignableFrom(impl)) {
             throw new ClassCastException("Class not of type: " + interfase.getName());
         }
         List<Class> implementations = new ArrayList<Class>();
         List<String> strings = findAllStrings(interfase.getName());
         for (String className : strings) {
-            Class impl = classLoader.loadClass(className);
+            Class impl = classLoaderInterface.loadClass(className);
             if (!interfase.isAssignableFrom(impl)) {
                 throw new ClassCastException("Class not of type: " + interfase.getName());
             }
         List<String> strings = findAvailableStrings(interfase.getName());
         for (String className : strings) {
             try {
-                Class impl = classLoader.loadClass(className);
+                Class impl = classLoaderInterface.loadClass(className);
                 if (interfase.isAssignableFrom(impl)) {
                     implementations.add(impl);
                 } else {
         for (Map.Entry<String, String> entry : map.entrySet()) {
             String string = entry.getKey();
             String className = entry.getValue();
-            Class impl = classLoader.loadClass(className);
+            Class impl = classLoaderInterface.loadClass(className);
             if (!interfase.isAssignableFrom(impl)) {
                 throw new ClassCastException("Class not of type: " + interfase.getName());
             }
             String string = entry.getKey();
             String className = entry.getValue();
             try {
-                Class impl = classLoader.loadClass(className);
+                Class impl = classLoaderInterface.loadClass(className);
                 if (interfase.isAssignableFrom(impl)) {
                     implementations.put(string, impl);
                 } else {
 
     private URL getResource(String fullUri) {
         if (urls == null){
-            return classLoader.getResource(fullUri);
+            return classLoaderInterface.getResource(fullUri);
         }
         return findResource(fullUri, urls);
     }
 
     private Enumeration<URL> getResources(String fulluri) throws IOException {
         if (urls == null) {
-            return classLoader.getResources(fulluri);
+            return classLoaderInterface.getResources(fulluri);
         }
         Vector<URL> resources = new Vector();
         for (URL url : urls) {

src/java/com/opensymphony/xwork2/util/finder/Test.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
 package com.opensymphony.xwork2.util.finder;
 
 /**

src/java/com/opensymphony/xwork2/util/finder/UrlSet.java

-/**
- * 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.
+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
  */
 package com.opensymphony.xwork2.util.finder;
 
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+import org.apache.commons.lang.StringUtils;
+
 import java.io.File;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.util.*;
-
-import org.apache.commons.lang.StringUtils;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Use with ClassFinder to filter the Urls to be scanned, example:
  * @version $Rev$ $Date$
  */
 public class UrlSet {
-
+    private static final Logger LOG = LoggerFactory.getLogger(UrlSet.class);
     private final Map<String,URL> urls;
 
-    public UrlSet(ClassLoader classLoader) throws IOException {
+    public UrlSet(ClassLoaderInterface classLoader) throws IOException {
         this(getUrls(classLoader));
     }
 
         return new UrlSet(urls);
     }
 
-    public UrlSet exclude(ClassLoader parent) throws IOException {
+    public UrlSet exclude(ClassLoaderInterface parent) throws IOException {
         return exclude(new UrlSet(parent));
     }
 
         return new ArrayList<URL>(urls.values());
     }
 
-    private static List<URL> getUrls(ClassLoader classLoader) throws IOException {
+    private static List<URL> getUrls(ClassLoaderInterface classLoader) throws IOException {
         List<URL> list = new ArrayList<URL>();
+
+        //find jars
         ArrayList<URL> urls = Collections.list(classLoader.getResources("META-INF"));
+
         for (URL url : urls) {
-            String externalForm = url.toExternalForm();
-            int i = externalForm.lastIndexOf("META-INF");
-            externalForm = externalForm.substring(0, i);
-            url = new URL(externalForm);
-            list.add(url);
+            if ("jar".equalsIgnoreCase(url.getProtocol())) {
+                String externalForm = url.toExternalForm();
+                //build a URL pointing to the jar, instead of the META-INF dir
+                url = new URL(StringUtils.substringBefore(externalForm, "META-INF"));
+                list.add(url);
+            } else if (LOG.isDebugEnabled())
+                LOG.debug("Ignoring URL [#0] because it is not a jar", url.toExternalForm());
+
         }
+
+        //usually the "classes" dir
         list.addAll(Collections.list(classLoader.getResources("")));
         return list;
     }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.