commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From c...@apache.org
Subject svn commit: r1344950 [2/3] - in /commons/sandbox/classscan/trunk: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/commons/ src/main/java/org/apache/commons/classscan/ src/main/java/org/apache/commo...
Date Fri, 01 Jun 2012 00:27:41 GMT
Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/Cache.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/Cache.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/Cache.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/Cache.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,74 @@
+/*
+ * Licensed 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.commons.classscan.bcel;
+
+import java.net.URLClassLoader;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.commons.classscan.MetaClassLoader;
+import org.apache.commons.classscan.MetaRegistry;
+import org.apache.commons.classscan.util.WeakConcurrentHashMap;
+
+/**
+ * An implementation of a MetaRegistry which uses BCEL to introspect class
+ * files. Usually, the client program should access
+ * {@link MetaRegistry#SINGLETON} to get a reference to a Cache.
+ */
+public class Cache implements MetaRegistry {
+
+    private final ConcurrentMap<ClassLoader, MetaClassLoader> maps = new WeakConcurrentHashMap<ClassLoader, MetaClassLoader>();
+
+    /**
+     * Get the MetaClassLoader for a ClassLoader. If possible, an existing
+     * MetaClassLoader is returned. Otherwise, the MetaClassLoader is created.
+     * 
+     * @param classLoader
+     *            The ClassLoader for which metadata is desired. If this
+     *            parameter is null, information about the Bootstrap classloader
+     *            is returned.
+     * @return The metadata about a ClassLoader
+     */
+    public MetaClassLoader getClassLoader(ClassLoader classLoader) {
+        if (classLoader == null) {
+            return getBootstrapClassLoader();
+        }
+        MetaClassLoader mcl = maps.get(classLoader);
+        if (mcl == null) {
+            mcl = createMetaClassLoader(classLoader);
+            MetaClassLoader prior = maps.putIfAbsent(classLoader, mcl);
+            if (prior != null) {
+                return prior;
+            }
+        }
+        return mcl;
+    }
+
+    static MetaClassLoader bootstrapClassLoader;
+
+    private static MetaClassLoader getBootstrapClassLoader() {
+        synchronized (Cache.class) {
+            if (bootstrapClassLoader == null) {
+                bootstrapClassLoader = new BootstrapClassLoader();
+            }
+        }
+        return bootstrapClassLoader;
+    }
+
+    private MetaClassLoader createMetaClassLoader(ClassLoader classLoader) {
+        if (classLoader instanceof URLClassLoader) {
+            return new MetaUrlClassLoader(this, (URLClassLoader) classLoader);
+        }
+        throw new IllegalArgumentException(classLoader.getClass().getCanonicalName() + " is not supported");
+    }
+}

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/Cache.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/ClassMetaType.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/ClassMetaType.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/ClassMetaType.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/ClassMetaType.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,36 @@
+/*
+ * Licensed 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.commons.classscan.bcel;
+
+import org.apache.commons.classscan.MetaClass;
+import org.apache.commons.classscan.MetaType;
+
+public class ClassMetaType implements MetaType {
+
+    private final MetaClass metaClass;
+
+    ClassMetaType(MetaClass metaClass) {
+        this.metaClass = metaClass;
+    }
+
+    @Override
+    public MetaClass getMetaClass() {
+        return metaClass;
+    }
+
+    @Override
+    public MetaType getArrayMetaType() {
+        return null;
+    }
+}

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/ClassMetaType.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/DeferredMetaClass.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/DeferredMetaClass.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/DeferredMetaClass.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/DeferredMetaClass.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,104 @@
+/*
+ * Licensed 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.commons.classscan.bcel;
+
+import java.util.MissingResourceException;
+import java.util.Set;
+
+import org.apache.commons.classscan.MetaAnnotation;
+import org.apache.commons.classscan.MetaClass;
+import org.apache.commons.classscan.MetaClassLocation;
+import org.apache.commons.classscan.MetaField;
+import org.apache.commons.classscan.MetaMethod;
+
+public class DeferredMetaClass implements MetaClass {
+
+    private MetaClass proxy;
+    private String canonicalName;
+    private MetaUrlClassLoader classLoader;
+
+    DeferredMetaClass(MetaUrlClassLoader classLoader, String canonicalName) {
+        this.classLoader = classLoader;
+        this.canonicalName = canonicalName;
+    }
+
+    private MetaClass getProxyMetaClass() {
+        synchronized (this) {
+            if (proxy == null) {
+                proxy = classLoader.findMetaClass(canonicalName);
+                if (proxy == null) {
+                    throw new MissingResourceException("Unable to resolve " + canonicalName, canonicalName, canonicalName);
+                }
+                canonicalName = null;
+                classLoader = null;
+            }
+            return proxy;
+        }
+    }
+
+    @Override
+    public MetaClassLocation getClassLocation() {
+        return getProxyMetaClass().getClassLocation();
+    }
+
+    @Override
+    public String getName() {
+        return getProxyMetaClass().getName();
+    }
+
+    @Override
+    public MetaClass getParent() {
+        return getProxyMetaClass().getParent();
+    }
+
+    @Override
+    public Set<? extends MetaClass> getInterfaces() {
+        return getProxyMetaClass().getInterfaces();
+    }
+
+    @Override
+    public Set<? extends MetaAnnotation> getAnnotations() {
+        return getProxyMetaClass().getAnnotations();
+    }
+
+    @Override
+    public MetaAnnotation getAnnotation(String annotationName) {
+        return getProxyMetaClass().getAnnotation(annotationName);
+    }
+
+    @Override
+    public Set<? extends MetaMethod> getMethods() {
+        return getProxyMetaClass().getMethods();
+    }
+
+    @Override
+    public Set<? extends MetaField> getFields() {
+        return getProxyMetaClass().getFields();
+    }
+
+    @Override
+    public boolean isAssignableFrom(MetaClass implementor) {
+        return getProxyMetaClass().isAssignableFrom(implementor);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        return getProxyMetaClass().equals(other);
+    }
+
+    @Override
+    public int hashCode() {
+        return getProxyMetaClass().hashCode();
+    }
+}

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/DeferredMetaClass.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/FileClassLocation.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/FileClassLocation.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/FileClassLocation.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/FileClassLocation.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,131 @@
+/*
+ * Licensed 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.commons.classscan.bcel;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FilenameFilter;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FileClassLocation extends UriClassLocation {
+
+    private static final Logger logger = LoggerFactory.getLogger(FileClassLocation.class);
+
+    public FileClassLocation(MetaUrlClassLoader loader, File root, URI location) {
+        super(loader, location);
+        root.listFiles(new PathedFileFilter());
+        sealLocation();
+    }
+
+    static private Pattern IDENTIFIER_PACKAGE = Pattern.compile(IDENTIFIER_REGEX);
+
+    /**
+     * Check if supplied name is a valid java package name portion or class
+     * identifier.
+     * 
+     * @param identifier
+     *            The name of a package file
+     * @return true if the identifier is a valid part of a package or class name
+     */
+    static boolean isValidIdentifier(String identifier) {
+        Matcher ipm = IDENTIFIER_PACKAGE.matcher(identifier);
+        return ipm.matches();
+    }
+
+    static private Pattern filePattern = Pattern.compile(FILE_REGEX);
+
+    /**
+     * Check if supplied file name is a valid class file name. The name must be
+     * a valid Class name followed by ".class"
+     * 
+     * @param fileName
+     *            The name of a file (without path)
+     * @return The class name without the trailing ".class", or null if the
+     *         supplied filename is invalid
+     */
+    static String getClassNameFromFileName(String fileName) {
+        Matcher fpm = filePattern.matcher(fileName);
+        if (fpm.matches()) {
+            return fpm.group(1);
+        }
+        else {
+            return null;
+        }
+    }
+
+    private class PathedFileFilter implements FileFilter {
+        private final StringBuilder pathPrefix = new StringBuilder();
+
+        @Override
+        public boolean accept(File path) {
+            if (path.isDirectory()) {
+                acceptPath(path);
+            }
+            else {
+                acceptFile(path);
+            }
+            return false;
+        }
+
+        private void acceptPath(File path) {
+            String folderName = path.getName();
+            if (isValidIdentifier(folderName)) {
+                int prefixLength = pathPrefix.length();
+                pathPrefix.append(folderName).append('.');
+                path.listFiles(this);
+                pathPrefix.setLength(prefixLength);
+            }
+            else if (pathPrefix.length() == 0 && folderName.equals(META_INF)) {
+                acceptMetaInf(path);
+            }
+        }
+
+        private void acceptFile(File path) {
+            String fileName = getClassNameFromFileName(path.getName());
+            if (fileName != null) {
+                int prefixLength = pathPrefix.length();
+                pathPrefix.append(fileName);
+                addClass(pathPrefix.toString(), path);
+                pathPrefix.setLength(prefixLength);
+            }
+        }
+    }
+
+    private void addClass(String fullPath, File path) {
+        try {
+            InputStream is = new FileInputStream(path);
+            addClass(fullPath, is);
+        }
+        catch (Exception ex) {
+            logger.debug("Failed to add class " + fullPath, ex);
+        }
+    }
+
+    void acceptMetaInf(File path) {
+        path.list(new FilenameFilter() {
+            @Override
+            public boolean accept(File dir, String name) {
+                addMetaFile(name);
+                return false;
+            }
+        });
+    }
+}

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/FileClassLocation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/JarClassLocation.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/JarClassLocation.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/JarClassLocation.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/JarClassLocation.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,128 @@
+/*
+ * Licensed 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.commons.classscan.bcel;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Enumeration;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JarClassLocation extends UriClassLocation {
+
+    private static final Logger logger = LoggerFactory.getLogger(JarClassLocation.class);
+    private static Pattern PATH_SPLITTER = Pattern.compile("\\s+");
+
+    public JarClassLocation(MetaUrlClassLoader loader, JarFile jarFile, URI location) {
+        super(loader, location);
+        addClassesFromJarFile(jarFile);
+        sealLocation();
+        addAdditionalJars(location, jarFile);
+    }
+
+    private static final String PATH_REGEX = "((" + IDENTIFIER_REGEX + "/)*)" + FILE_REGEX;
+    static private Pattern pathPattern = Pattern.compile(PATH_REGEX);
+
+    /**
+     * Check if supplied path name is a valid pathed file name. The path must
+     * contain valid package names, the file name must be a valid Class name,
+     * and must be followed by ".class"
+     * 
+     * @param path
+     *            A file name with path
+     * @return The class name without the trailing ".class", with the dotted
+     *         package prefix, or null if the supplied filename is invalid
+     */
+    static String getCannonicalClassNameFromPathName(String path) {
+        Matcher m = pathPattern.matcher(path);
+        if (m.matches()) {
+            String packagePrefix = m.group(1).replace('/', '.');
+            String className = m.group(3);
+            return packagePrefix + className;
+        }
+        else {
+            return null;
+        }
+    }
+
+    private static final String METAFILE_NAME_REGEX = META_INF + "/([^/]+)";
+    static private Pattern metafileNamePattern = Pattern.compile(METAFILE_NAME_REGEX);
+
+    private String getMetafileNameFromPathName(String path) {
+        Matcher m = metafileNamePattern.matcher(path);
+        if (m.matches()) {
+            return m.group(1);
+        }
+        else {
+            return null;
+        }
+    }
+
+    private void addClassesFromJarFile(JarFile jarFile) {
+        for (Enumeration<JarEntry> jarEntries = jarFile.entries(); jarEntries.hasMoreElements();) {
+            JarEntry jarEntry = jarEntries.nextElement();
+            String pathName = getCannonicalClassNameFromPathName(jarEntry.getName());
+            if (pathName != null) {
+                addClass(pathName, jarFile, jarEntry);
+                continue;
+            }
+            String metaFileName = getMetafileNameFromPathName(jarEntry.getName());
+            if (metaFileName != null) {
+                addMetaFile(metaFileName);
+            }
+        }
+    }
+
+    private void addClass(String fullName, JarFile jarFile, JarEntry jarEntry) {
+        try {
+            InputStream is = jarFile.getInputStream(jarEntry);
+            addClass(fullName, is);
+        }
+        catch (Exception ex) {
+            logger.warn("Failed to add class " + fullName, ex);
+        }
+    }
+
+    private void addAdditionalJars(URI location, JarFile jarFile) {
+        try {
+            Manifest manifest = jarFile.getManifest();
+            if (manifest != null) {
+                addAdditionalJars(location, manifest);
+            }
+        }
+        catch (IOException ex) {
+            logger.warn("failure reading manifest from " + location, ex);
+        }
+    }
+
+    private void addAdditionalJars(URI location, Manifest manifest) {
+        Attributes attributes = manifest.getMainAttributes();
+        String classPath = attributes.getValue(Attributes.Name.CLASS_PATH);
+        if (classPath == null) {
+            return;
+        }
+        for (String pathElement : PATH_SPLITTER.split(classPath)) {
+            URI newLocation = location.resolve(pathElement);
+            loader.addLocation(newLocation);
+        }
+    }
+}
\ No newline at end of file

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/JarClassLocation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/MetaUrlClassLoader.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/MetaUrlClassLoader.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/MetaUrlClassLoader.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/MetaUrlClassLoader.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,338 @@
+/*
+ * Licensed 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.commons.classscan.bcel;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.JarURLConnection;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.Set;
+import java.util.jar.JarFile;
+
+import org.apache.commons.classscan.MetaClass;
+import org.apache.commons.classscan.MetaClassLoader;
+import org.apache.commons.classscan.MetaClassLocation;
+import org.apache.commons.classscan.MetaRegistry;
+import org.apache.commons.classscan.MetaType;
+import org.apache.commons.classscan.util.SortedReadOnlySet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MetaUrlClassLoader implements MetaClassLoader {
+
+    private static final Logger logger = LoggerFactory.getLogger(MetaUrlClassLoader.class);
+
+    private final MetaUrlClassLoader parent;
+
+    protected Map<String, MetaClass> workClasses = new HashMap<String, MetaClass>();
+    protected SortedReadOnlySet<MetaClass> sealedClasses;
+    private Map<String, MetaClass> delegates = new HashMap<String, MetaClass>();
+
+    private Map<String, UriClassLocation> workLocations = new HashMap<String, UriClassLocation>();
+    private SortedReadOnlySet<UriClassLocation> sealedLocations;
+    
+    // for BootstrapClassLoader
+    MetaUrlClassLoader(MetaUrlClassLoader parent) {
+        this.parent = parent;
+    }
+
+    MetaUrlClassLoader(MetaRegistry registry, URLClassLoader urlClassLoader) {
+        this((MetaUrlClassLoader) registry.getClassLoader(urlClassLoader.getParent()));
+        addLocations(urlClassLoader);
+        sealClassLoader();
+    }
+
+    private void addLocations(URLClassLoader urlClassLoader) {
+        for (URL url : urlClassLoader.getURLs()) {
+            try {
+                URI uri = url.toURI();
+                addLocation(uri);
+            }
+            catch (URISyntaxException e) {
+                logger.warn("failure translating " + url + " to uri", e);
+            }
+        }
+    }
+
+    /**
+     * Make the class map readOnly, prevent any further adding of classes
+     */
+    void sealClassLoader() {
+        sealedClasses = new SortedReadOnlySet<MetaClass>(MetaClass.class, workClasses.values());
+        workClasses = null;
+        delegates = null;
+
+        sealedLocations = new SortedReadOnlySet<UriClassLocation>(UriClassLocation.class, workLocations.values());
+        workLocations = null;
+    }
+
+    /**
+     * Add a location
+     * 
+     * @param location
+     *            The URI of a jar or folder
+     */
+    protected void addLocation(URI location) {
+        String locationName = location.toString();
+        if (workLocations.containsKey(locationName)) {
+            return;
+        }
+
+        UriClassLocation mcl = createClassLocation(location);
+        if (mcl != null) {
+            workLocations.put(locationName, mcl);
+            for (MetaClass mc : mcl.getMetaClasses()) {
+                workClasses.put(mc.getName(), mc);
+            }
+        }
+    }
+
+    private UriClassLocation createClassLocation(URI location) {
+        if (location.getScheme().equals("jar")) {
+            JarFile jf = getJarFile(location);
+            if (jf != null) {
+                return new JarClassLocation(this, jf, location);
+            }
+            return null;
+        }
+        else if (location.getScheme().equals("file")) {
+            File file = new File(location);
+            if (file.isDirectory()) {
+                return new FileClassLocation(this, file, location);
+            }
+            try {
+                JarFile jf = new JarFile(file);
+                return new JarClassLocation(this, jf, location);
+            }
+            catch (IOException io) {
+                logger.debug(file + " is not a jar", io);
+            }
+            return null;
+        }
+        else {
+            logger.warn("protocol {} not supported ", location.getScheme());
+            return null;
+        }
+    }
+
+    static private JarFile getJarFile(URI location) {
+        try {
+            JarURLConnection conn = (JarURLConnection) location.toURL().openConnection();
+            return conn.getJarFile();
+        }
+        catch (IOException ex) {
+            logger.warn("Failed to open " + location, ex);
+            return null;
+        }
+    }
+
+    @Override
+    public MetaClassLoader getParent() {
+        return parent;
+    }
+
+    @Override
+    public Set<? extends MetaClassLocation> getClassLocations() {
+        return sealedLocations;
+    }
+
+    @Override
+    public Collection<MetaClassLocation> getClassLocationsWithMetaFile(String metaInfFilename) {
+        List<MetaClassLocation> matchedLocations = new ArrayList<MetaClassLocation>(sealedLocations.size());
+        for (UriClassLocation location : sealedLocations) {
+            if (location.containsMetafile(metaInfFilename)) {
+                matchedLocations.add(location);
+            }
+        }
+        return matchedLocations;
+    }
+
+    @Override
+    public MetaClassLocation getClassLocation(String location) {
+        return sealedLocations.getValue(location);
+    }
+
+    @Override
+    public Set<? extends MetaClass> getMetaClasses() {
+        return sealedClasses;
+    }
+
+    @Override
+    public MetaClass getMetaClass(String className) {
+        return sealedClasses.getValue(className);
+    }
+
+    @Override
+    public MetaClass findMetaClass(String className) {
+        MetaClass mc = parent.findMetaClass(className);
+        if (mc != null) {
+            return mc;
+        }
+        return getMetaClass(className);
+    }
+
+    /**
+     * How to handle delegates
+     */
+    static enum DelegateOption {
+        /**
+         * Allow return of a delegate, but do not create one
+         */
+        AllowDelegate,
+        /**
+         * Create a delegate if explicate MetaClass not found
+         */
+        CreateDelegate
+    }
+
+    /**
+     * Get metadata about a particular Class. The returned instance may be a
+     * deferred delegate which will resolve the MetaClass once the delegate
+     * instance is invoked.
+     * 
+     * @param className
+     *            The name of the Class
+     * @param createDelegate
+     *            If true, return a deferred delegate if MetaClass not found.
+     * @param allowDelegate
+     *            If true, may return a deferred delegate.
+     * @return The metadata about the Class; or null, if the class was not
+     *         available to the associated ClassLoader
+     */
+    MetaClass getMetaClass(String className, DelegateOption delegateBehavior) {
+        // check parent for MetaClass
+        if (parent != null) {
+            MetaClass mc = parent.getMetaClass(className, DelegateOption.AllowDelegate);
+            if (mc != null) {
+                return mc;
+            }
+        }
+
+        // check for explicit MetaClass
+        if (sealedClasses != null) {
+            MetaClass mc = sealedClasses.getValue(className);
+            if (mc == null) {
+                return mc;
+            }
+            return mc;
+        }
+
+        MetaClass mc = workClasses.get(className);
+        if (mc != null) {
+            return mc;
+        }
+
+        // check for existing delegate
+        mc = delegates.get(className);
+        if (mc != null) {
+            return mc;
+        }
+
+        // if allowed, create a delegate
+        if (delegateBehavior == DelegateOption.CreateDelegate) {
+            MetaClass deferred = new DeferredMetaClass(this, className);
+            delegates.put(className, deferred);
+            return deferred;
+        }
+        return null;
+    }
+
+    /**
+     * Get metadata representing a type from its byte code signature
+     * 
+     * @param fieldDescriptor
+     *            The field descriptor as defined in section 4.3.2 of The Java
+     *            Virtual Machine Specification
+     * @return The type metadata
+     */
+    /*
+     * FieldType: BaseType ObjectType ArrayType
+     * 
+     * BaseType: // see BootstrapClassLoader.getPrimitiveTypeForDescriptor
+     * 
+     * ObjectType: L <classname> ;
+     * 
+     * ArrayType: [ ComponentType
+     */
+    MetaType getTypeForDescriptor(String fieldDescriptor) {
+        char typeCode = fieldDescriptor.charAt(0);
+        switch (typeCode) {
+        case 'L':
+            return getTypeForClassName(fieldDescriptor);
+        case '[':
+            return getArrayType(fieldDescriptor.substring(1));
+        default:
+            return getPrimitiveTypeForDescriptor(typeCode);
+        }
+    }
+
+    MetaType getPrimitiveTypeForDescriptor(char typeCode) {
+        // delegate to parent so that BootstrapClassLoader will hold the
+        // primitive types
+        return parent.getPrimitiveTypeForDescriptor(typeCode);
+    }
+
+    private ArrayMetaType getArrayType(String fieldDescriptor) {
+        MetaType arrayType = getTypeForDescriptor(fieldDescriptor);
+        return new ArrayMetaType(arrayType);
+    }
+
+    private MetaType getTypeForClassName(String internalClassName) {
+        String canonicalName = internalToCanonicalName(internalClassName);
+        return new ClassMetaType(getMetaClass(canonicalName, DelegateOption.CreateDelegate));
+    }
+
+    @Override
+    public Collection<? extends MetaClass> findAllImplementors(String interfaceToFind) {
+        MetaClass mc = findMetaClass(interfaceToFind);
+
+        Collection<MetaClass> implementations = new ArrayList<MetaClass>();
+        MetaClassLoader classLoader = this;
+        do {
+            for (MetaClass potentialImplementation : classLoader.getMetaClasses()) {
+                try {
+                    if (!potentialImplementation.equals(mc) && mc.isAssignableFrom(potentialImplementation)) {
+                        implementations.add(potentialImplementation);
+                    }
+                }
+                catch (MissingResourceException mre) {
+                    continue;
+                }
+            }
+            classLoader = classLoader.getParent();
+        }
+        while (classLoader != null);
+        return implementations;
+    }
+
+    /**
+     * Get the canonical name from the internal name
+     * 
+     * @param internalName
+     *            The internal name in the form Ljava/lang/Object;
+     * @return The canonical name in the form java.lang.Object
+     */
+    static String internalToCanonicalName(String internalName) {
+        return internalName.substring(1, internalName.length() - 1).replace('/', '.');
+    }
+}

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/MetaUrlClassLoader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/PrimitiveClass.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/PrimitiveClass.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/PrimitiveClass.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/PrimitiveClass.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,91 @@
+/*
+ * Licensed 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.commons.classscan.bcel;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.commons.classscan.MetaAnnotation;
+import org.apache.commons.classscan.MetaClass;
+import org.apache.commons.classscan.MetaClassLocation;
+import org.apache.commons.classscan.MetaField;
+import org.apache.commons.classscan.MetaMethod;
+
+public class PrimitiveClass implements MetaClass {
+
+    private final String primitiveName;
+
+    public PrimitiveClass(String primitiveName) {
+        this.primitiveName = primitiveName;
+    }
+
+    @Override
+    public MetaClassLocation getClassLocation() {
+        return null;
+    }
+
+    @Override
+    public String getName() {
+        return primitiveName;
+    }
+
+    @Override
+    public MetaClass getParent() {
+        return null;
+    }
+
+    @Override
+    public Set<MetaClass> getInterfaces() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Set<? extends MetaAnnotation> getAnnotations() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public MetaAnnotation getAnnotation(String annotationName) {
+        return null;
+    }
+
+    @Override
+    public Set<MetaMethod> getMethods() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Set<MetaField> getFields() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public boolean isAssignableFrom(MetaClass assignor) {
+        return equals(assignor);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof PrimitiveClass)) {
+            return false;
+        }
+        PrimitiveClass other = (PrimitiveClass) obj;
+        return primitiveName.equals(other.primitiveName);
+    }
+
+    @Override
+    public int hashCode() {
+        return primitiveName.hashCode();
+    }
+}

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/PrimitiveClass.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/UriClassLocation.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/UriClassLocation.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/UriClassLocation.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/UriClassLocation.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,115 @@
+/*
+ * Licensed 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.commons.classscan.bcel;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.bcel.classfile.ClassFormatException;
+import org.apache.bcel.classfile.ClassParser;
+import org.apache.commons.classscan.MetaClass;
+import org.apache.commons.classscan.MetaClassLoader;
+import org.apache.commons.classscan.MetaClassLocation;
+import org.apache.commons.classscan.util.SortedReadOnlySet;
+
+/**
+ * Base class for {link MetaClassLocation}s that support {link URI}s
+ */
+public abstract class UriClassLocation implements MetaClassLocation {
+
+    protected final MetaUrlClassLoader loader;
+    protected final String location;
+    protected Set<String> metaFiles = new HashSet<String>();
+
+    private Map<String, MetaClass> workClasses = new HashMap<String, MetaClass>();
+    private SortedReadOnlySet<MetaClass> sealedClasses;
+
+    /**
+     * Constructor for URI based ClassLocation. Derived constructors should fill
+     * classes by calling addClass
+     * 
+     * @param loader
+     *            The {@link MetaClassLoader} that tracks the {@link MetaClass}
+     *            es.
+     * @param location
+     *            The {@link URI} of the associated Classes.
+     */
+    public UriClassLocation(MetaUrlClassLoader loader, URI location) {
+        this.loader = loader;
+        this.location = location.toString();
+    }
+
+    @Override
+    public Set<? extends MetaClass> getMetaClasses() {
+        return sealedClasses;
+    }
+
+    @Override
+    public MetaClass getMetaClass(String className) {
+        return sealedClasses.getValue(className);
+    }
+
+    @Override
+    public String getName() {
+        return location;
+    }
+
+    protected void addClass(String className, InputStream is) throws ClassFormatException, IOException {
+        MetaClass mc = new BcelClass(this, loader, new ClassParser(is, className));
+        if (!className.equals(mc.getName())) {
+            throw new IllegalArgumentException("Expecting classname " + className + " but found " + mc.getName());
+        }
+        workClasses.put(className, mc);
+    }
+
+    /**
+     * Make the class map readOnly, prevent any further adding of classes
+     */
+    void sealLocation() {
+        sealedClasses = new SortedReadOnlySet<MetaClass>(MetaClass.class, workClasses.values());
+        workClasses = null;
+    }
+
+    protected void addMetaFile(String metaFileName) {
+        metaFiles.add(metaFileName);
+    }
+
+    boolean containsMetafile(String metaInfFilename) {
+        return metaFiles.contains(metaInfFilename);
+    }
+
+    @Override
+    public int hashCode() {
+        return location.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof UriClassLocation)) {
+            return false;
+        }
+        UriClassLocation other = (UriClassLocation) obj;
+        return location.equals(other.location);
+    }
+
+    // following constants are used by JarClassLocation and FileClassLocation
+    protected static final String IDENTIFIER_REGEX = "\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*";
+    protected static final String FILE_REGEX = "(" + IDENTIFIER_REGEX + ")\\.class";
+    protected static final String META_INF = "META-INF";
+}

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/UriClassLocation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/package-info.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/package-info.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/package-info.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/package-info.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,20 @@
+/*
+ * Licensed 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.
+ */
+/**
+ * <p>This package is an implementation of the {@link org.apache.commons.classscan} interfaces.
+ * The implementation uses the BCEL commons library to introspect class files.</p>
+ * <p><b>The non-public methods in these classes are subject to change in any release.</b></p>
+ */
+package org.apache.commons.classscan.bcel;
+

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/bcel/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/package-info.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/package-info.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/package-info.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/package-info.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,31 @@
+/*
+ * Licensed 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.
+ */
+/**
+ * <p><b>** Start Here **</b> The metadata package provides information about available classes without loading them.
+ *  The standard Java runtime hides many details about classes, particularly the location of classes which can potentially be loaded, and the details of unloaded classes.
+ *  An application may need to discover class information without loading the class in the following situations:</p>
+ *  <ul>
+ *  <li>When discovering the implementers of a particular interface</li>
+ *  <li>Determining which classes have a specific annotation (or set to a particular annotation value)</li>
+ *  <li>Determine which fields or methods are available on a class</li>
+ *  <li>Any of the above, limited by the location of the class (eg. only classes annotated with @Entity from a jar that has a META-INF/persistence.xml file</li>
+ *  </ul>
+ *  <p>An application using this package must first obtain a {@link org.apache.commons.classscan.MetaClassLoader MetaClassLoader} instance from 
+ *  the {@link org.apache.commons.classscan.MetaRegistry MetaRegistry}</p>
+ *  <code>
+    MetaClassLoader classLoader = MetaRegistry.SINGLETON.getClassLoader(getClass().getClassLoader());
+</code>
+ */
+package org.apache.commons.classscan;
+

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/ArrayTransformer.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/ArrayTransformer.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/ArrayTransformer.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/ArrayTransformer.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,58 @@
+/*
+ * Licensed 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.commons.classscan.util;
+
+import java.lang.reflect.Array;
+
+/**
+ * Transform the incoming array and hold destination array in a read only set.
+ * 
+ * @param <S>
+ *            The source array type
+ * @param <D>
+ *            The destination array type
+ */
+public abstract class ArrayTransformer<S, D> {
+
+    final S[] source;
+
+    /**
+     * Transform all elements of the source array
+     */
+    public ArrayTransformer(S[] source) {
+        this.source = source;
+    }
+
+    /**
+     * Transform the source array into an D[] containing elements of type D
+     */
+    public D[] transform(Class<D> destClass) {
+        @SuppressWarnings("unchecked")
+        D[] dest = (D[]) Array.newInstance(destClass, source.length);
+        for (int i = 0; i < dest.length; ++i) {
+            dest[i] = transformElement(source[i]);
+        }
+        return dest;
+    }
+
+    /**
+     * Subclasses must override this method to define the transformation of a
+     * single element of the array
+     * 
+     * @param src
+     *            The source element
+     * @return The destination element
+     */
+    abstract protected D transformElement(S src);
+}
\ No newline at end of file

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/ArrayTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/CallStack.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/CallStack.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/CallStack.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/CallStack.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,74 @@
+/*
+ * Licensed 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.commons.classscan.util;
+
+public abstract class CallStack {
+    
+    interface GetCallerStrategy {
+        Class<?> getCallerClass(int callStackDepth);        
+    }
+    
+    private static GetCallerStrategy strategy;
+    
+    static class SunReflection implements GetCallerStrategy {
+        SunReflection() {
+            // cause load of sun.reflect.Reflection class
+            sun.reflect.Reflection.getCallerClass(0);
+        }
+
+        @Override
+        public Class<?> getCallerClass(int callStackDepth) {
+            return sun.reflect.Reflection.getCallerClass(callStackDepth);
+        }
+    }
+    
+    static class SecurityManagerMethod extends SecurityManager implements GetCallerStrategy {
+        @Override
+        public Class<?> getCallerClass(int callStackDepth) {
+            return getClassContext()[callStackDepth];
+        }
+    }
+    
+    static {
+        try {
+            strategy= new SunReflection();
+        }
+        catch(Throwable t) {
+            strategy= new SecurityManagerMethod();
+        }
+    }
+
+    /**
+     * Return the Class of the caller.
+     * @param callStackDepth The number of stack frames to skip.  
+     * A value of 0 will return the calling Class of this method.  
+     * A value of 1 will return the calling Class of the caller of this method. 
+     * @return The Class at callStackDepth down the call stack
+     */
+    public static Class<?> getCallerClass(int callStackDepth) {
+        return strategy.getCallerClass(callStackDepth+3);
+    }
+
+    /**
+     * Return the ClassLoader of the caller.
+     * @param callStackDepth The number of stack frames to skip.  
+     * A value of 0 will return the ClassLoader of the calling Class of this method.  
+     * A value of 1 will return the ClassLoader of the calling Class of the caller of this method. 
+     * @return The ClassLoader of the Class at callStackDepth down the call stack
+     */
+    public static ClassLoader getClassLoader(int callStackDepth) {
+        Class<?> rc= strategy.getCallerClass(callStackDepth+3);
+        return rc.getClassLoader();
+    }
+}

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/CallStack.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/HashWeakReference.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/HashWeakReference.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/HashWeakReference.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/HashWeakReference.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,53 @@
+/*
+ * Licensed 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.commons.classscan.util;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+public class HashWeakReference<T> extends WeakReference<T> {
+    private final int hashCode;
+
+    public HashWeakReference(T referent) {
+        super(referent);
+        hashCode = System.identityHashCode(referent);
+    }
+
+    public HashWeakReference(T referent, ReferenceQueue<? super T> queue) {
+        super(referent, queue);
+        hashCode = System.identityHashCode(referent);
+    }
+
+    @Override
+    public int hashCode() {
+        return hashCode;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof HashWeakReference) {
+            T ref = get();
+            if (ref != null) {
+                @SuppressWarnings("unchecked")
+                HashWeakReference<T> other = (HashWeakReference<T>) obj;
+                T otherRef = other.get();
+                if (otherRef != null) {
+                    return ref == otherRef;
+                }
+            }
+        }
+        return false;
+    }
+
+}

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/HashWeakReference.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/ReadOnlySet.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/ReadOnlySet.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/ReadOnlySet.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/ReadOnlySet.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,172 @@
+/*
+ * Licensed 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.commons.classscan.util;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * Set of immutable instances.
+ * 
+ * @param <V>
+ *            The contained type
+ */
+public class ReadOnlySet<V> implements Set<V> {
+    
+    private static final Object[] EMPTY_ARRAY = new Object[0];
+
+    protected V[] values;
+
+    public ReadOnlySet(V[] values) {
+        if(values==null || values.length==0) {
+            this.values = emptyArray();
+        }
+        else {
+            this.values = values;
+        }
+    }
+
+    <D> D[] emptyArray() {
+        @SuppressWarnings("unchecked")
+        D[] emptyArray = (D[]) EMPTY_ARRAY;
+        return emptyArray;
+    };
+
+    /**
+     * Subclasses may use this constructor to delay initialization of values.
+     * The derived class must call setValues before general use.
+     */
+    protected ReadOnlySet() {
+    }
+
+    /**
+     * @param values
+     *            The array to view
+     */
+    protected void setValues(V[] values) {
+        this.values = values;
+    }
+
+    @Override
+    public boolean contains(Object o) {
+        for (V t : values) {
+            if (t.equals(o)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> collection) {
+        for (Object single : collection) {
+            if (!contains(single)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return values.length == 0;
+    }
+
+    @Override
+    public Iterator<V> iterator() {
+        return new Iterator<V>() {
+            int i;
+
+            @Override
+            public boolean hasNext() {
+                return i < values.length;
+            }
+
+            @Override
+            public V next() {
+                if (i == values.length) {
+                    throw new NoSuchElementException("Reading past end of iterator");
+                }
+                return values[i++];
+            }
+
+            @Override
+            public void remove() {
+                throw new UnsupportedOperationException("Read only iterator");
+            }
+        };
+    }
+
+    @Override
+    public int size() {
+        return values.length;
+    }
+
+    @Override
+    public Object[] toArray() {
+        return values.clone();
+    }
+
+    @Override
+    public <T> T[] toArray(T[] a) {
+        int numberToNull = a.length - values.length;
+        if (numberToNull >= 0) {
+            System.arraycopy(values, 0, a, 0, values.length);
+            if (numberToNull > 0) {
+                Arrays.fill(a, values.length, a.length, null);
+            }
+            return a;
+        }
+
+        @SuppressWarnings("unchecked")
+        T[] rv = (T[]) Array.newInstance(a.getClass().getComponentType(), values.length);
+        System.arraycopy(values, 0, rv, 0, values.length);
+        return rv;
+    }
+
+    @Override
+    final public boolean add(V e) {
+        throw new UnsupportedOperationException("Set is readonly");
+    }
+
+    @Override
+    final public boolean addAll(Collection<? extends V> c) {
+        throw new UnsupportedOperationException("Set is readonly");
+    }
+
+    @Override
+    final public void clear() {
+        throw new UnsupportedOperationException("Set is readonly");
+    }
+
+    @Override
+    final public boolean remove(Object e) {
+        throw new UnsupportedOperationException("Set is readonly");
+    }
+
+    @Override
+    final public boolean removeAll(Collection<?> c) {
+        throw new UnsupportedOperationException("Set is readonly");
+    }
+
+    @Override
+    final public boolean retainAll(Collection<?> c) {
+        throw new UnsupportedOperationException("Set is readonly");
+    }
+
+}

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/ReadOnlySet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/SortedReadOnlySet.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/SortedReadOnlySet.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/SortedReadOnlySet.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/SortedReadOnlySet.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,76 @@
+/*
+ * Licensed 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.commons.classscan.util;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+
+import org.apache.commons.classscan.HasName;
+
+public class SortedReadOnlySet<D extends HasName> extends ReadOnlySet<D> {
+
+    private final static Comparator<HasName> REVERSE_COMPARE = new Comparator<HasName>() {
+        @Override
+        public int compare(HasName l, HasName r) {
+            String left = l.getName();
+            String right = r.getName();
+            
+            // "quick" compare
+            int diff = left.length() - right.length();
+            if (diff != 0) {
+                return diff;
+            }
+            // compare from end of strings - the names have long equivalent prefixes
+            for (int i = left.length(); --i > 0;) {
+                int d = left.charAt(i) - right.charAt(i);
+                if (d != 0) {
+                    return d;
+                }
+            }
+            return 0;
+        }
+    };
+
+    public SortedReadOnlySet(D[] values) {
+        super(values);
+        if(values!=null && values.length>0) {
+            Arrays.sort(values, REVERSE_COMPARE);
+        }
+    }
+
+    public SortedReadOnlySet(Class<D> clss, Collection<? extends D> workValues) {
+        this(collectionToArray(clss, workValues));
+     }
+
+    private static <D extends HasName> D[] collectionToArray(Class<D> collectionType, Collection<? extends D> workValues) {
+        if(workValues.isEmpty()) {
+            return null;
+        }
+        @SuppressWarnings("unchecked")
+        D[] newInstance = (D[]) Array.newInstance(collectionType, workValues.size());
+        return workValues.toArray(newInstance);
+    }
+
+    public D getValue(final String name) {
+        int idx= Arrays.binarySearch(values, new HasName() {
+            @Override
+            public String getName() {
+                return name;
+            }
+        }, REVERSE_COMPARE);
+        return idx<0 ? null : values[idx];
+    }
+}

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/SortedReadOnlySet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/WeakConcurrentHashMap.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/WeakConcurrentHashMap.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/WeakConcurrentHashMap.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/WeakConcurrentHashMap.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,135 @@
+/*
+ * Licensed 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.commons.classscan.util;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public final class WeakConcurrentHashMap<K, V> implements ConcurrentMap<K, V> {
+
+    private final ConcurrentMap<HashWeakReference<K>, V> innerMap = new ConcurrentHashMap<HashWeakReference<K>, V>();
+    private final ReferenceQueue<K> queue = new ReferenceQueue<K>();
+    private final Thread reaper = new ReaperThread();
+
+    public WeakConcurrentHashMap() {
+        reaper.setDaemon(true);
+        reaper.start();
+    }
+
+    private class ReaperThread extends Thread {
+        ReaperThread() {
+            super("WeakConcurrentHashMap-" + System.identityHashCode(WeakConcurrentHashMap.this) + "-reaper");
+        }
+
+        @Override
+        public void run() {
+            for (;;) {
+                try {
+                    Reference<? extends K> ref = queue.remove();
+                    HashWeakReference<? extends K> key = (HashWeakReference<? extends K>) ref;
+                    innerMap.remove(key);
+                }
+                catch (InterruptedException ignore) {
+                }
+            }
+        }
+    }
+
+    @Override
+    public V get(Object key) {
+        HashWeakReference<Object> innerKey = new HashWeakReference<Object>(key);
+        return innerMap.get(innerKey);
+    }
+
+    @Override
+    public V putIfAbsent(K key, V value) {
+        HashWeakReference<K> innerKey = new HashWeakReference<K>(key, queue);
+        return innerMap.putIfAbsent(innerKey, value);
+    }
+
+    @Override
+    public void clear() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean containsKey(Object key) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean containsValue(Object value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<Map.Entry<K, V>> entrySet() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<K> keySet() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public V put(K key, V value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putAll(Map<? extends K, ? extends V> m) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public V remove(Object key) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int size() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Collection<V> values() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean remove(Object key, Object value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public V replace(K key, V value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean replace(K key, V oldValue, V newValue) {
+        throw new UnsupportedOperationException();
+    }
+}

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/WeakConcurrentHashMap.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/package-info.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/package-info.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/package-info.java (added)
+++ commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/package-info.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,18 @@
+/*
+ * Licensed 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.
+ */
+/**
+ * <p>The util package consists of utility collection implementations to support the {@link org.apache.commons.classscan.bcel} package.</p>
+ * <p><b>These classes are subject to change in any release.</b></p>
+ */
+package org.apache.commons.classscan.util;
\ No newline at end of file

Propchange: commons/sandbox/classscan/trunk/src/main/java/org/apache/commons/classscan/util/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/site/site.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/site/site.xml?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/site/site.xml (added)
+++ commons/sandbox/classscan/trunk/src/site/site.xml Fri Jun  1 00:27:39 2012
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ 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.
+-->
+<project name="Lang">
+    <bannerRight>
+        <name>Commons ClassScan</name>
+        <src>/images/logo.png</src>
+        <href>/index.html</href>
+    </bannerRight>
+
+    <body>
+        <menu name="Lang">
+            <item name="Overview"        href="/index.html"/>
+            <item name="Users guide"     href="/userguide.html"/>
+        </menu>
+
+        <menu name="Development">
+            <item name="Building"             href="/building.html"/>
+            <item name="Mailing Lists"        href="/mail-lists.html"/>
+            <item name="Javadoc (SVN latest)" href="apidocs/index.html"/>
+        </menu>
+
+    </body>
+
+</project>

Propchange: commons/sandbox/classscan/trunk/src/site/site.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/site/xdoc/building.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/site/xdoc/building.xml?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/site/xdoc/building.xml (added)
+++ commons/sandbox/classscan/trunk/src/site/xdoc/building.xml Fri Jun  1 00:27:39 2012
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!--
+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.
+-->
+<document>
+ <properties>
+  <title>Building</title>
+  <author email="dev@commons.apache.org">Commons Documentation Team</author>
+ </properties>
+<body>
+<!-- ================================================== -->
+<section name="Overview">
+<p>
+  Commons Lang uses <a href="http://maven.apache.org">Maven</a> as a build system.
+</p>
+</section>
+<!-- ================================================== -->
+<section name="Maven Goals">
+  <p>
+    To build a jar file, change into the root directory of ClasspathInfo and run "mvn package".
+    The result will be in the "target" subdirectory.
+  </p>
+  <p>
+    To build the full website, run "mvn site".
+    The result will be in "target/site".
+  </p>
+  <p>
+    Further details can be found in the
+    <a href="http://commons.apache.org/building.html">commons build instructions</a>.
+  </p>
+</section>
+</body>
+</document>

Propchange: commons/sandbox/classscan/trunk/src/site/xdoc/building.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/site/xdoc/index.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/site/xdoc/index.xml?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/site/xdoc/index.xml (added)
+++ commons/sandbox/classscan/trunk/src/site/xdoc/index.xml Fri Jun  1 00:27:39 2012
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<!--
+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.
+-->
+<document>
+ <properties>
+  <title>Commons ClasspathInfo</title>
+  <author email="dev@commons.apache.org">Commons Documentation Team</author>
+ </properties>
+<body>
+<!-- ================================================== -->
+<section name="Commons ClasspathInfo">
+
+<p>
+The standard Java runtime hides many details about classes, particularly the location of classes which can potentially be loaded, and the details of unloaded classes. 
+</p>
+
+<p>
+ClasspathInfo can provide information about all of the classes available to the runtime, whether or not the class has been loaded.
+<ul>An application may want to discover:
+<li>all of the implementers of a particular interface</li>
+<li>all of the classes with a specific annotation (or even a particular annotation value)</li>
+<li>a particular field or all of the fields of a class</li>
+<li>a particular method or all of the fields of a class</li>
+<li>Any of the above, limited by the location of the class (eg. only classes annotated with @Entity from a jar that has a META-INF/persistence.xml file</li>
+</ul>
+</p>
+</section>
+<!-- ================================================== -->
+<section name="Documentation">
+<p>
+A getting started <a href="userguide.html">user guide</a> is available
+together with various <a href="project-reports.html">project reports</a>.
+</p>
+</section>
+<!-- ================================================== -->
+<section name="Release Information">
+</section>
+<!-- ================================================== -->
+<section name="Support">
+<p>
+The <a href="mail-lists.html">commons mailing lists</a> act as the main support forum.
+The user list is suitable for most library usage queries.
+The dev list is intended for the development discussion.
+Please remember that the lists are shared between all commons components,
+so prefix your email by [meiyo].
+</p>
+<!-- p>
+Bug reports and enhancements are also welcomed via the <a href="issue-tracking.html">JIRA</a> issue tracker.
+Please read the instructions carefully.
+</p -->
+</section>
+<!-- ================================================== -->
+</body>
+</document>

Propchange: commons/sandbox/classscan/trunk/src/site/xdoc/index.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/site/xdoc/userguide.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/site/xdoc/userguide.xml?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/site/xdoc/userguide.xml (added)
+++ commons/sandbox/classscan/trunk/src/site/xdoc/userguide.xml Fri Jun  1 00:27:39 2012
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<!--
+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.
+-->
+
+<document>
+
+ <properties>
+  <title>Commons ClasspathInfo - User guide</title>
+  <author email="dev@commons.apache.org">Commons Documentation Team</author>
+ </properties>
+
+ <body>
+
+
+  <section name="Description">
+   <p>This library provides methods to search for classes without using reflection, in fact, without even loading the classes.  This is particularly important when the class has
+   static initializers that cause behavior that cannot be undone.  Additionally, framework libraries don't always have apriori knowledge of all classes which must be managed.</p>
+  </section>
+
+   <section name="Find All Implementors of an Interface">
+<p>You can use the following code snippet to find all implementors of an interface.</p>
+   <source><![CDATA[
+        MetaClassLoader classLoader = MetaRegistry.SINGLETON.getClassLoader(getClass().getClassLoader());
+        Collection<? extends MetaClass> implementations = classLoader.findAllImplementors(FullInterface.class.getCanonicalName());
+]]></source>
+   </section>
+
+   <section name="Find All Classes in a jar with a Annotation">
+<p>You can use the following code snippets to find all classes with a particular annotation in a jar with a marker META-INF file.</p>
+   <source><![CDATA[    
+    public void findAnnotatedClassesFromJar(MetaClassLoader classLoader) {
+        for(MetaClassLocation location : classLoader.getClassLocationsWithMetaFile("persistence.xml")) {
+            findAnnotatedClassesFromLocation(location);
+        }
+    }
+
+    private void findAnnotatedClassesFromLocation(MetaClassLocation location) {
+        for(MetaClass mc : location.getMetaClasses()) {
+            MetaAnnotation ma = mc.getAnnotation("javax.persistence.Entity");
+            if(ma!=null) {
+                workOnClass(mc);
+            }
+        }
+    }
+]]></source>
+   </section>
+   
+   
+</body>
+</document>

Propchange: commons/sandbox/classscan/trunk/src/site/xdoc/userguide.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/test/java/org/apache/commons/classscan/bcel/BcelClassTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/test/java/org/apache/commons/classscan/bcel/BcelClassTest.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/test/java/org/apache/commons/classscan/bcel/BcelClassTest.java (added)
+++ commons/sandbox/classscan/trunk/src/test/java/org/apache/commons/classscan/bcel/BcelClassTest.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,56 @@
+/*
+ * Licensed 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.commons.classscan.bcel;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import org.apache.commons.classscan.MetaClass;
+import org.apache.commons.classscan.MetaClassLoader;
+import org.apache.commons.classscan.MetaRegistry;
+import org.junit.Before;
+import org.junit.Test;
+
+public class BcelClassTest {
+
+    MetaClassLoader classLoader;
+    MetaClass thisClass;
+    
+    @Before
+    public void loadLocation() throws URISyntaxException {
+        classLoader = MetaRegistry.SINGLETON.getClassLoader(getClass().getClassLoader());
+        thisClass = classLoader.getMetaClass(getClass().getCanonicalName());
+    }
+
+    @Test
+    public void testGetClassLocation() throws MalformedURLException {
+        String testClassLocation = thisClass.getClassLocation().getName();
+        assertEquals(getClass().getProtectionDomain().getCodeSource().getLocation(), new URL(testClassLocation));
+    }
+
+    @Test
+    public void testGetParent() {
+        MetaClass pmc = thisClass.getParent();
+        assertEquals(Object.class.getCanonicalName(), pmc.getName());
+    }
+
+    @Test
+    public void testGetInterfaces() {
+        assertFalse(thisClass.getInterfaces().iterator().hasNext());
+    }
+}

Propchange: commons/sandbox/classscan/trunk/src/test/java/org/apache/commons/classscan/bcel/BcelClassTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/classscan/trunk/src/test/java/org/apache/commons/classscan/bcel/MetaUrlClassLoaderTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/trunk/src/test/java/org/apache/commons/classscan/bcel/MetaUrlClassLoaderTest.java?rev=1344950&view=auto
==============================================================================
--- commons/sandbox/classscan/trunk/src/test/java/org/apache/commons/classscan/bcel/MetaUrlClassLoaderTest.java (added)
+++ commons/sandbox/classscan/trunk/src/test/java/org/apache/commons/classscan/bcel/MetaUrlClassLoaderTest.java Fri Jun  1 00:27:39 2012
@@ -0,0 +1,106 @@
+/*
+ * Licensed 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.commons.classscan.bcel;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.net.URISyntaxException;
+import java.util.Collection;
+
+import org.apache.commons.classscan.MetaClass;
+import org.apache.commons.classscan.MetaClassLoader;
+import org.apache.commons.classscan.MetaClassLocation;
+import org.apache.commons.classscan.MetaRegistry;
+import org.apache.commons.classscan.test.classes.FullInterface;
+import org.apache.commons.classscan.test.classes.FullyDecorated;
+import org.apache.commons.classscan.test.classes.ValidateFullyDecorated;
+import org.junit.Before;
+import org.junit.Test;
+
+public class MetaUrlClassLoaderTest {
+
+    private static final String OBJECT_CANONICAL_NAME = Object.class.getCanonicalName();
+    private static final String FULLY_DECORATED_NAME = FullyDecorated.class.getCanonicalName();
+
+    MetaClassLoader classLoader;
+    MetaClass fdClass;
+    MetaClass objClass;
+
+    @Before
+    public void loadLocation() throws URISyntaxException {
+        classLoader = MetaRegistry.SINGLETON.getClassLoader(getClass().getClassLoader());
+        fdClass = classLoader.findMetaClass(FULLY_DECORATED_NAME);
+        objClass = classLoader.findMetaClass(OBJECT_CANONICAL_NAME);
+    }
+
+    @Test
+    public void testGetMetaClass() {
+        new ValidateFullyDecorated(classLoader.getMetaClass(FULLY_DECORATED_NAME));        
+        assertNull(classLoader.getMetaClass(OBJECT_CANONICAL_NAME));
+    }
+
+    @Test
+    public void testFindMetaClass() {
+        assertEquals(FULLY_DECORATED_NAME, fdClass.getName());
+        assertEquals(OBJECT_CANONICAL_NAME, objClass.getName());
+    }
+
+    @Test
+    public void testGetMetaClasses() {
+        Collection<? extends MetaClass> classes = classLoader.getMetaClasses();
+        assertTrue(classes.contains(fdClass));
+        assertFalse(classes.contains(objClass));
+    }
+
+    @Test
+    public void testGetClassLocations() throws URISyntaxException {
+        Collection<? extends MetaClassLocation> locations = classLoader.getClassLocations();
+        MetaClassLocation location = classLoader.getClassLocation(getClass().getProtectionDomain().getCodeSource().getLocation().toString());
+        assertTrue(locations.contains(location));
+    }
+    
+    @Test
+    public void testGetClassLocationsWithMetaFile() throws URISyntaxException {
+        Collection<? extends MetaClassLocation> locations = classLoader.getClassLocationsWithMetaFile(FullInterface.class.getCanonicalName());
+        MetaClassLocation location = fdClass.getClassLocation();
+        assertTrue(locations.contains(location));
+    }
+
+    @Test
+    public void testGetParent() {
+        MetaClassLoader cl = MetaRegistry.SINGLETON.getClassLoader(getClass().getClassLoader());
+        for (int i = 0; i < 4; ++i) {
+            MetaClassLoader pcl = cl.getParent();
+            if (pcl == null) {
+                // cl is now bootstrap class loader
+                assertNotNull(cl.getMetaClass(Integer.class.getCanonicalName()));
+                return;
+            }
+            cl = pcl;
+        }
+        fail("Too many nested ClassLoaders");
+    }
+
+    @Test
+    public void findAllImplementations() throws URISyntaxException {
+        Collection<? extends MetaClass> implementations= classLoader.findAllImplementors(FullInterface.class.getCanonicalName());
+        assertTrue(implementations.contains(fdClass));
+        assertFalse(implementations.contains(objClass));
+    }
+}

Propchange: commons/sandbox/classscan/trunk/src/test/java/org/apache/commons/classscan/bcel/MetaUrlClassLoaderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message