import org.aspectj.apache.bcel.classfile.JavaClass;
/**
- * The repository maintains information about which classes have
- * been loaded.
- *
- * It loads its data from the ClassLoader implementation
- * passed into its constructor.
- *
+ * The repository maintains information about which classes have been loaded.
+ *
+ * It loads its data from the ClassLoader implementation passed into its constructor.
+ *
* @see org.aspectj.apache.bcel.Repository
- *
- * @version $Id: NonCachingClassLoaderRepository.java,v 1.4 2008/08/26 15:02:51 aclement Exp $
+ *
+ * @version $Id: NonCachingClassLoaderRepository.java,v 1.5 2009/09/04 18:42:08 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
* @author David Dixon-Peugh
*
*/
-public class NonCachingClassLoaderRepository
- implements Repository
-{
- private static java.lang.ClassLoader bootClassLoader = null;
-
- private ClassLoaderReference loaderRef;
- private Map loadedClasses =
- new SoftHashMap(); // CLASSNAME X JAVACLASS
-
+public class NonCachingClassLoaderRepository implements Repository {
+ private static java.lang.ClassLoader bootClassLoader = null;
+
+ private final ClassLoaderReference loaderRef;
+ private final Map loadedClasses = new SoftHashMap(); // CLASSNAME X JAVACLASS
+
public static class SoftHashMap extends AbstractMap {
- private Map map;
- private ReferenceQueue rq = new ReferenceQueue();
-
- public SoftHashMap(Map map) { this.map = map; }
- public SoftHashMap() { this(new HashMap()); }
- public SoftHashMap(Map map, boolean b) { this(map); }
-
- class SpecialValue extends SoftReference {
- private final Object key;
- SpecialValue(Object k,Object v) {
- super(v,rq);
- this.key = k;
- }
- }
-
- private void processQueue() {
+ private Map map;
+ private ReferenceQueue rq = new ReferenceQueue();
+
+ public SoftHashMap(Map map) {
+ this.map = map;
+ }
+
+ public SoftHashMap() {
+ this(new HashMap());
+ }
+
+ public SoftHashMap(Map map, boolean b) {
+ this(map);
+ }
+
+ class SpecialValue extends SoftReference {
+ private final Object key;
+
+ SpecialValue(Object k, Object v) {
+ super(v, rq);
+ this.key = k;
+ }
+ }
+
+ private void processQueue() {
SpecialValue sv = null;
- while ((sv = (SpecialValue)rq.poll())!=null) {
+ while ((sv = (SpecialValue) rq.poll()) != null) {
map.remove(sv.key);
}
- }
-
- public Object get(Object key) {
- SpecialValue value = (SpecialValue)map.get(key);
- if (value==null) return null;
- if (value.get()==null) {
+ }
+
+ public Object get(Object key) {
+ SpecialValue value = (SpecialValue) map.get(key);
+ if (value == null)
+ return null;
+ if (value.get() == null) {
// it got GC'd
map.remove(value.key);
return null;
} else {
return value.get();
}
- }
+ }
- public Object put(Object k, Object v) {
+ public Object put(Object k, Object v) {
processQueue();
- return map.put(k, new SpecialValue(k,v));
- }
+ return map.put(k, new SpecialValue(k, v));
+ }
- public Set entrySet() {
+ public Set entrySet() {
return map.entrySet();
- }
-
- public void clear() {
+ }
+
+ public void clear() {
processQueue();
Set keys = map.keySet();
for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
Object name = iterator.next();
map.remove(name);
}
- }
-
- public int size() {
+ }
+
+ public int size() {
processQueue();
return map.size();
- }
-
- public Object remove(Object k) {
+ }
+
+ public Object remove(Object k) {
processQueue();
- SpecialValue value = (SpecialValue)map.remove(k);
- if (value==null) return null;
- if (value.get()!=null) {
+ SpecialValue value = (SpecialValue) map.remove(k);
+ if (value == null)
+ return null;
+ if (value.get() != null) {
return value.get();
}
return null;
- }
- }
-
- public NonCachingClassLoaderRepository(java.lang.ClassLoader loader) {
- this.loaderRef = new DefaultClassLoaderReference((loader != null) ? loader : getBootClassLoader());
- }
-
- public NonCachingClassLoaderRepository(ClassLoaderReference loaderRef) {
- this.loaderRef = loaderRef;
- }
-
- private static synchronized java.lang.ClassLoader getBootClassLoader() {
- if (bootClassLoader == null) {
- bootClassLoader = new URLClassLoader(new URL[0]);
- }
- return bootClassLoader;
- }
-
- /**
- * Store a new JavaClass into this Repository.
- */
- public void storeClass( JavaClass clazz ) {
- loadedClasses.put( clazz.getClassName(),
- clazz );
- clazz.setRepository( this );
- }
-
- /**
- * Remove class from repository
- */
- public void removeClass(JavaClass clazz) {
- loadedClasses.remove(clazz.getClassName());
- }
-
- /**
- * Find an already defined JavaClass.
- */
- public JavaClass findClass( String className ) {
- if ( loadedClasses.containsKey( className )) {
- return (JavaClass) loadedClasses.get( className );
- } else {
- return null;
- }
- }
-
- /**
- * Lookup a JavaClass object from the Class Name provided.
- */
- public JavaClass loadClass( String className )
- throws ClassNotFoundException
- {
- String classFile = className.replace('.', '/');
-
- JavaClass RC = findClass( className );
- if (RC != null) { return RC; }
-
- try {
- InputStream is =
- loaderRef.getClassLoader().getResourceAsStream(classFile + ".class");
-
- if(is == null) {
- throw new ClassNotFoundException(className + " not found.");
- }
-
- ClassParser parser = new ClassParser( is, className );
- RC = parser.parse();
-
- storeClass( RC );
-
- return RC;
- } catch (IOException e) {
- throw new ClassNotFoundException( e.toString() );
- }
- }
-
- public JavaClass loadClass(Class clazz) throws ClassNotFoundException {
- return loadClass(clazz.getName());
- }
-
- /** Clear all entries from cache.
- */
- public void clear() {
- loadedClasses.clear();
- }
-}
+ }
+ }
+
+ public NonCachingClassLoaderRepository(java.lang.ClassLoader loader) {
+ this.loaderRef = new DefaultClassLoaderReference((loader != null) ? loader : getBootClassLoader());
+ }
+
+ public NonCachingClassLoaderRepository(ClassLoaderReference loaderRef) {
+ this.loaderRef = loaderRef;
+ }
+
+ private static synchronized java.lang.ClassLoader getBootClassLoader() {
+ if (bootClassLoader == null) {
+ bootClassLoader = new URLClassLoader(new URL[0]);
+ }
+ return bootClassLoader;
+ }
+
+ /**
+ * Store a new JavaClass into this Repository.
+ */
+ public void storeClass(JavaClass clazz) {
+ synchronized (loadedClasses) {
+ loadedClasses.put(clazz.getClassName(), clazz);
+ }
+ clazz.setRepository(this);
+ }
+
+ /**
+ * Remove class from repository
+ */
+ public void removeClass(JavaClass clazz) {
+ synchronized (loadedClasses) {
+ loadedClasses.remove(clazz.getClassName());
+ }
+ }
+
+ /**
+ * Find an already defined JavaClass.
+ */
+ public JavaClass findClass(String className) {
+ synchronized (loadedClasses) {
+ if (loadedClasses.containsKey(className)) {
+ return (JavaClass) loadedClasses.get(className);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Clear all entries from cache.
+ */
+ public void clear() {
+ synchronized (loadedClasses) {
+ loadedClasses.clear();
+ }
+ }
+ /**
+ * Lookup a JavaClass object from the Class Name provided.
+ */
+ public JavaClass loadClass(String className) throws ClassNotFoundException {
+
+ JavaClass javaClass = findClass(className);
+ if (javaClass != null) {
+ return javaClass;
+ }
+
+ javaClass = loadJavaClass(className);
+ storeClass(javaClass);
+
+ return javaClass;
+ }
+
+ public JavaClass loadClass(Class clazz) throws ClassNotFoundException {
+ return loadClass(clazz.getName());
+ }
+
+ private JavaClass loadJavaClass(String className) throws ClassNotFoundException {
+ String classFile = className.replace('.', '/');
+ try {
+ InputStream is = loaderRef.getClassLoader().getResourceAsStream(classFile + ".class");
+
+ if (is == null) {
+ throw new ClassNotFoundException(className + " not found.");
+ }
+
+ ClassParser parser = new ClassParser(is, className);
+ return parser.parse();
+ } catch (IOException e) {
+ throw new ClassNotFoundException(e.toString());
+ }
+ }
+
+}
import junit.framework.Test;
import junit.framework.TestSuite;
-import org.aspectj.apache.bcel.classfile.tests.AnnotationAccessFlagTest;
-import org.aspectj.apache.bcel.classfile.tests.AnnotationDefaultAttributeTest;
-import org.aspectj.apache.bcel.classfile.tests.ElementValueGenTest;
-import org.aspectj.apache.bcel.classfile.tests.EnclosingMethodAttributeTest;
-import org.aspectj.apache.bcel.classfile.tests.EnumAccessFlagTest;
-import org.aspectj.apache.bcel.classfile.tests.FieldAnnotationsTest;
-import org.aspectj.apache.bcel.classfile.tests.GeneratingAnnotatedClassesTest;
-import org.aspectj.apache.bcel.classfile.tests.LocalVariableTypeTableTest;
-import org.aspectj.apache.bcel.classfile.tests.MethodAnnotationsTest;
-import org.aspectj.apache.bcel.classfile.tests.RuntimeVisibleAnnotationAttributeTest;
-import org.aspectj.apache.bcel.classfile.tests.RuntimeVisibleParameterAnnotationAttributeTest;
-import org.aspectj.apache.bcel.classfile.tests.VarargsTest;
-
public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite("Tests for BCEL");
- //$JUnit-BEGIN$
+ // $JUnit-BEGIN$
suite.addTestSuite(Fundamentals.class);
suite.addTestSuite(RuntimeVisibleParameterAnnotationAttributeTest.class);
suite.addTestSuite(AnnotationDefaultAttributeTest.class);
suite.addTestSuite(MethodAnnotationsTest.class);
suite.addTestSuite(RuntimeVisibleAnnotationAttributeTest.class);
suite.addTestSuite(ClassloaderRepositoryTest.class);
+ suite.addTestSuite(NonCachingClassLoaderRepositoryTest.class);
suite.addTestSuite(EnumAccessFlagTest.class);
suite.addTestSuite(LocalVariableTypeTableTest.class);
suite.addTestSuite(VarargsTest.class);
suite.addTestSuite(GenericSignatureParsingTest.class);
suite.addTestSuite(GenericsErasureTesting.class);
suite.addTestSuite(AnonymousClassTest.class);
- //$JUnit-END$
+ // $JUnit-END$
return suite;
}
}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache BCEL" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache BCEL", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.aspectj.apache.bcel.classfile.tests;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.aspectj.apache.bcel.classfile.JavaClass;
+import org.aspectj.apache.bcel.util.NonCachingClassLoaderRepository;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class NonCachingClassLoaderRepositoryTest extends TestCase {
+
+ private final NonCachingClassLoaderRepository nonCachingClassLoaderRepository = new NonCachingClassLoaderRepository(
+ NonCachingClassLoaderRepositoryTest.class.getClassLoader());
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ abstract class DoneChecker implements Runnable {
+ private volatile boolean success = false;
+ private volatile boolean done = false;
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public boolean isDone() {
+ return done;
+ }
+
+ protected void setDone(boolean successFully) {
+ success = successFully;
+ done = true;
+ }
+
+ public abstract void run();
+ }
+
+ class Loader extends DoneChecker implements Runnable {
+ public void run() {
+ try {
+ JavaClass javaClass = nonCachingClassLoaderRepository.loadClass(NonCachingClassLoaderRepositoryTest.class
+ .getCanonicalName());
+ nonCachingClassLoaderRepository.clear();
+ setDone(true);
+ } catch (Throwable e) {
+ e.printStackTrace(System.out);
+ setDone(false);
+ }
+ }
+ }
+
+ class Clearer extends DoneChecker implements Runnable {
+ public void run() {
+ try {
+ nonCachingClassLoaderRepository.clear();
+ setDone(true);
+ } catch (Throwable e) {
+ e.printStackTrace(System.out);
+ setDone(false);
+ }
+ }
+ }
+
+ public void testConcurrency() throws ClassNotFoundException, InterruptedException {
+ List loaders = new ArrayList();
+ int i1 = 1000;
+ for (int i = 0; i < i1; i++) {
+ DoneChecker loader = new Loader();
+ loaders.add(loader);
+ new Thread(loader).start();
+ DoneChecker clearer = new Clearer();
+ loaders.add(clearer);
+ new Thread(clearer).start();
+ }
+
+ for (int i = 0; i < i1 * 2; i++) {
+ DoneChecker loader = (DoneChecker) loaders.get(i);
+ while (!loader.isDone()) {
+ Thread.sleep(10);
+ }
+ assertTrue("Loader " + i + " is supposed to run successfully", loader.isSuccess());
+ }
+
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+}