diff options
author | Shigeru Chiba <chibash@users.noreply.github.com> | 2017-11-15 00:06:52 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-15 00:06:52 +0900 |
commit | b7e59d4dc0222d34732c8efd87872b562501e14b (patch) | |
tree | f41f98b560cea64a496a3353fe4f369283c1a32a /src | |
parent | c4e194994f5d07cab64b54754fcee884d9287949 (diff) | |
parent | 53325f5637042322f1b810ad32c8ee3bad2915f4 (diff) | |
download | javassist-b7e59d4dc0222d34732c8efd87872b562501e14b.tar.gz javassist-b7e59d4dc0222d34732c8efd87872b562501e14b.zip |
Merge pull request #159 from nickl-/scoped-pool
Fixes to javassist.scopepool
Diffstat (limited to 'src')
-rw-r--r-- | src/main/javassist/scopedpool/ScopedClassPool.java | 26 | ||||
-rw-r--r-- | src/main/javassist/scopedpool/ScopedClassPoolRepository.java | 2 | ||||
-rw-r--r-- | src/main/javassist/scopedpool/ScopedClassPoolRepositoryImpl.java | 47 | ||||
-rw-r--r-- | src/main/javassist/scopedpool/SoftValueHashMap.java | 132 | ||||
-rw-r--r-- | src/test/scoped/ScopedRepositoryTestCase.java | 242 | ||||
-rw-r--r-- | src/test/scoped/TestAnnotation.java | 34 | ||||
-rw-r--r-- | src/test/scoped/UnscopedAnnotationDefaultUsage.java | 29 | ||||
-rw-r--r-- | src/test/scoped/UnscopedAnnotationUsage.java | 29 | ||||
-rw-r--r-- | src/test/scoped/jar1/FullyScopedAnnotationDefaultUsage.java | 29 | ||||
-rw-r--r-- | src/test/scoped/jar1/FullyScopedAnnotationUsage.java | 29 | ||||
-rw-r--r-- | src/test/scoped/jar1/ScopedAnnotationDefaultUsage.java | 31 | ||||
-rw-r--r-- | src/test/scoped/jar1/ScopedAnnotationUsage.java | 31 | ||||
-rw-r--r-- | src/test/scoped/jar1/ScopedTestAnnotation.java | 34 | ||||
-rw-r--r-- | src/test/scoped/jar1/TestClass1.java | 26 |
14 files changed, 650 insertions, 71 deletions
diff --git a/src/main/javassist/scopedpool/ScopedClassPool.java b/src/main/javassist/scopedpool/ScopedClassPool.java index bcda0ded..fb87709d 100644 --- a/src/main/javassist/scopedpool/ScopedClassPool.java +++ b/src/main/javassist/scopedpool/ScopedClassPool.java @@ -16,9 +16,9 @@ package javassist.scopedpool; +import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.security.ProtectionDomain; -import java.util.Iterator; import java.util.Map; import javassist.CannotCompileException; import javassist.ClassPool; @@ -37,11 +37,11 @@ import javassist.NotFoundException; public class ScopedClassPool extends ClassPool { protected ScopedClassPoolRepository repository; - protected WeakReference classLoader; + protected Reference<ClassLoader> classLoader; protected LoaderClassPath classPath; - protected SoftValueHashMap softcache = new SoftValueHashMap(); + protected Map<String,CtClass> softcache = new SoftValueHashMap<String,CtClass>(); boolean isBootstrapCl = true; @@ -59,10 +59,10 @@ public class ScopedClassPool extends ClassPool { * the original class pool * @param repository * the repository - *@deprecated */ protected ScopedClassPool(ClassLoader cl, ClassPool src, - ScopedClassPoolRepository repository) { + ScopedClassPoolRepository repository) + { this(cl, src, repository, false); } @@ -78,11 +78,12 @@ public class ScopedClassPool extends ClassPool { * @param isTemp * Whether this is a temporary pool used to resolve references */ - protected ScopedClassPool(ClassLoader cl, ClassPool src, ScopedClassPoolRepository repository, boolean isTemp) + protected ScopedClassPool(ClassLoader cl, ClassPool src, + ScopedClassPoolRepository repository, boolean isTemp) { super(src); this.repository = repository; - this.classLoader = new WeakReference(cl); + this.classLoader = new WeakReference<ClassLoader>(cl); if (cl != null) { classPath = new LoaderClassPath(cl); this.insertClassPath(classPath); @@ -110,7 +111,7 @@ public class ScopedClassPool extends ClassPool { } protected ClassLoader getClassLoader0() { - return (ClassLoader)classLoader.get(); + return classLoader.get(); } /** @@ -163,6 +164,7 @@ public class ScopedClassPool extends ClassPool { * the class name * @return the class */ + @Override protected CtClass getCached(String classname) { CtClass clazz = getCachedLocally(classname); if (clazz == null) { @@ -186,11 +188,9 @@ public class ScopedClassPool extends ClassPool { } if (!isLocal) { - Map registeredCLs = repository.getRegisteredCLs(); + Map<ClassLoader,ScopedClassPool> registeredCLs = repository.getRegisteredCLs(); synchronized (registeredCLs) { - Iterator it = registeredCLs.values().iterator(); - while (it.hasNext()) { - ScopedClassPool pool = (ScopedClassPool)it.next(); + for (ScopedClassPool pool:registeredCLs.values()) { if (pool.isUnloadedClassLoader()) { repository.unregisterClassLoader(pool .getClassLoader()); @@ -289,7 +289,7 @@ public class ScopedClassPool extends ClassPool { * @throws CannotCompileException * for any error */ - public Class toClass(CtClass ct, ClassLoader loader, ProtectionDomain domain) + public Class<?> toClass(CtClass ct, ClassLoader loader, ProtectionDomain domain) throws CannotCompileException { // We need to pass up the classloader stored in this pool, as the // default implementation uses the Thread context cl. diff --git a/src/main/javassist/scopedpool/ScopedClassPoolRepository.java b/src/main/javassist/scopedpool/ScopedClassPoolRepository.java index 497501be..33e47124 100644 --- a/src/main/javassist/scopedpool/ScopedClassPoolRepository.java +++ b/src/main/javassist/scopedpool/ScopedClassPoolRepository.java @@ -81,7 +81,7 @@ public interface ScopedClassPoolRepository { * * @return the registered classloaders. */ - Map getRegisteredCLs(); + Map<ClassLoader,ScopedClassPool> getRegisteredCLs(); /** * This method will check to see if a register classloader has been diff --git a/src/main/javassist/scopedpool/ScopedClassPoolRepositoryImpl.java b/src/main/javassist/scopedpool/ScopedClassPoolRepositoryImpl.java index a9a3c822..8c20d97c 100644 --- a/src/main/javassist/scopedpool/ScopedClassPoolRepositoryImpl.java +++ b/src/main/javassist/scopedpool/ScopedClassPoolRepositoryImpl.java @@ -18,7 +18,7 @@ package javassist.scopedpool; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.WeakHashMap; @@ -43,8 +43,8 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository boolean pruneWhenCached; /** The registered classloaders */ - protected Map registeredCLs = Collections - .synchronizedMap(new WeakHashMap()); + protected Map<ClassLoader,ScopedClassPool> registeredCLs = Collections + .synchronizedMap(new WeakHashMap<ClassLoader,ScopedClassPool>()); /** The default class pool */ protected ClassPool classpool; @@ -76,6 +76,7 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository * * @return the prune. */ + @Override public boolean isPrune() { return prune; } @@ -85,6 +86,7 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository * * @param prune a new value. */ + @Override public void setPrune(boolean prune) { this.prune = prune; } @@ -96,10 +98,12 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository * @param src the original classpool. * @return the classpool */ + @Override public ScopedClassPool createScopedClassPool(ClassLoader cl, ClassPool src) { return factory.create(cl, src, this); } + @Override public ClassPool findClassPool(ClassLoader cl) { if (cl == null) return registerClassLoader(ClassLoader.getSystemClassLoader()); @@ -113,6 +117,7 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository * @param ucl the classloader. * @return the classpool */ + @Override public ClassPool registerClassLoader(ClassLoader ucl) { synchronized (registeredCLs) { // FIXME: Probably want to take this method out later @@ -121,7 +126,7 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository // a // ClassPool.classpath if (registeredCLs.containsKey(ucl)) { - return (ClassPool)registeredCLs.get(ucl); + return registeredCLs.get(ucl); } ScopedClassPool pool = createScopedClassPool(ucl, classpool); registeredCLs.put(ucl, pool); @@ -132,7 +137,8 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository /** * Get the registered classloaders. */ - public Map getRegisteredCLs() { + @Override + public Map<ClassLoader,ScopedClassPool> getRegisteredCLs() { clearUnregisteredClassLoaders(); return registeredCLs; } @@ -141,34 +147,31 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository * This method will check to see if a register classloader has been * undeployed (as in JBoss) */ + @Override public void clearUnregisteredClassLoaders() { - ArrayList toUnregister = null; + List<ClassLoader> toUnregister = null; synchronized (registeredCLs) { - Iterator it = registeredCLs.values().iterator(); - while (it.hasNext()) { - ScopedClassPool pool = (ScopedClassPool)it.next(); - if (pool.isUnloadedClassLoader()) { - it.remove(); - ClassLoader cl = pool.getClassLoader(); + for (Map.Entry<ClassLoader,ScopedClassPool> reg:registeredCLs.entrySet()) { + if (reg.getValue().isUnloadedClassLoader()) { + ClassLoader cl = reg.getValue().getClassLoader(); if (cl != null) { - if (toUnregister == null) { - toUnregister = new ArrayList(); - } + if (toUnregister == null) + toUnregister = new ArrayList<ClassLoader>(); toUnregister.add(cl); } + registeredCLs.remove(reg.getKey()); } } - if (toUnregister != null) { - for (int i = 0; i < toUnregister.size(); i++) { - unregisterClassLoader((ClassLoader)toUnregister.get(i)); - } - } + if (toUnregister != null) + for (ClassLoader cl:toUnregister) + unregisterClassLoader(cl); } } + @Override public void unregisterClassLoader(ClassLoader cl) { synchronized (registeredCLs) { - ScopedClassPool pool = (ScopedClassPool)registeredCLs.remove(cl); + ScopedClassPool pool = registeredCLs.remove(cl); if (pool != null) pool.close(); } @@ -178,10 +181,12 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository // Noop - this is the end } + @Override public void setClassPoolFactory(ScopedClassPoolFactory factory) { this.factory = factory; } + @Override public ScopedClassPoolFactory getClassPoolFactory() { return factory; } diff --git a/src/main/javassist/scopedpool/SoftValueHashMap.java b/src/main/javassist/scopedpool/SoftValueHashMap.java index df6ae599..1154e62e 100644 --- a/src/main/javassist/scopedpool/SoftValueHashMap.java +++ b/src/main/javassist/scopedpool/SoftValueHashMap.java @@ -18,10 +18,14 @@ package javassist.scopedpool; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; -import java.util.AbstractMap; -import java.util.HashMap; +import java.util.AbstractMap.SimpleImmutableEntry; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; /** * This Map will remove entries when the value in the map has been cleaned from @@ -30,21 +34,21 @@ import java.util.Set; * @version <tt>$Revision: 1.4 $</tt> * @author <a href="mailto:bill@jboss.org">Bill Burke</a> */ -public class SoftValueHashMap extends AbstractMap implements Map { - private static class SoftValueRef extends SoftReference { - public Object key; +public class SoftValueHashMap<K,V> implements Map<K,V> { + private static class SoftValueRef<K,V> extends SoftReference<V> { + public K key; - private SoftValueRef(Object key, Object val, ReferenceQueue q) { + private SoftValueRef(K key, V val, ReferenceQueue<V> q) { super(val, q); this.key = key; } - private static SoftValueRef create(Object key, Object val, - ReferenceQueue q) { + private static <K,V> SoftValueRef<K,V> create( + K key, V val, ReferenceQueue<V> q) { if (val == null) return null; else - return new SoftValueRef(key, val, q); + return new SoftValueRef<K,V>(key, val, q); } } @@ -52,30 +56,37 @@ public class SoftValueHashMap extends AbstractMap implements Map { /** * Returns a set of the mappings contained in this hash table. */ - public Set entrySet() { + @Override + public Set<Map.Entry<K, V>> entrySet() { processQueue(); - return hash.entrySet(); + Set<Entry<K,V>> ret = new HashSet<Entry<K,V>>(); + for (Entry<K,SoftValueRef<K,V>> e:hash.entrySet()) + ret.add(new SimpleImmutableEntry<K,V> ( + e.getKey(), e.getValue().get())); + return ret; } /* Hash table mapping WeakKeys to values */ - private Map hash; + private Map<K,SoftValueRef<K,V>> hash; /* Reference queue for cleared WeakKeys */ - private ReferenceQueue queue = new ReferenceQueue(); + private ReferenceQueue<V> queue = new ReferenceQueue<V>(); /* * Remove all invalidated entries from the map, that is, remove all entries * whose values have been discarded. */ private void processQueue() { - SoftValueRef ref; - while ((ref = (SoftValueRef)queue.poll()) != null) { - if (ref == (SoftValueRef)hash.get(ref.key)) { - // only remove if it is the *exact* same WeakValueRef - // - hash.remove(ref.key); + Object ref; + if (!hash.isEmpty()) + while ((ref = queue.poll()) != null) + if (ref instanceof SoftValueRef) { + @SuppressWarnings("rawtypes") + SoftValueRef que =(SoftValueRef) ref; + if (ref == hash.get(que.key)) + // only remove if it is the *exact* same SoftValueRef + hash.remove(que.key); } - } } /* -- Constructors -- */ @@ -95,7 +106,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { * factor is nonpositive */ public SoftValueHashMap(int initialCapacity, float loadFactor) { - hash = new HashMap(initialCapacity, loadFactor); + hash = new ConcurrentHashMap<K,SoftValueRef<K,V>>(initialCapacity, loadFactor); } /** @@ -109,7 +120,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { * If the initial capacity is less than zero */ public SoftValueHashMap(int initialCapacity) { - hash = new HashMap(initialCapacity); + hash = new ConcurrentHashMap<K,SoftValueRef<K,V>>(initialCapacity); } /** @@ -117,7 +128,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { * initial capacity and the default load factor, which is <code>0.75</code>. */ public SoftValueHashMap() { - hash = new HashMap(); + hash = new ConcurrentHashMap<K,SoftValueRef<K,V>>(); } /** @@ -129,7 +140,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { * * @param t the map whose mappings are to be placed in this map. */ - public SoftValueHashMap(Map t) { + public SoftValueHashMap(Map<K,V> t) { this(Math.max(2 * t.size(), 11), 0.75f); putAll(t); } @@ -142,6 +153,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { * <code>Map</code> interface, the time required by this operation is * linear in the size of the map.</em> */ + @Override public int size() { processQueue(); return hash.size(); @@ -150,6 +162,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { /** * Returns <code>true</code> if this map contains no key-value mappings. */ + @Override public boolean isEmpty() { processQueue(); return hash.isEmpty(); @@ -162,6 +175,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { * @param key * The key whose presence in this map is to be tested. */ + @Override public boolean containsKey(Object key) { processQueue(); return hash.containsKey(key); @@ -177,12 +191,10 @@ public class SoftValueHashMap extends AbstractMap implements Map { * @param key * The key whose associated value, if any, is to be returned. */ - public Object get(Object key) { + @Override + public V get(Object key) { processQueue(); - SoftReference ref = (SoftReference)hash.get(key); - if (ref != null) - return ref.get(); - return null; + return valueOrNull(hash.get(key)); } /** @@ -200,12 +212,10 @@ public class SoftValueHashMap extends AbstractMap implements Map { * @return The previous value to which this key was mapped, or * <code>null</code> if if there was no mapping for the key */ - public Object put(Object key, Object value) { + @Override + public V put(K key, V value) { processQueue(); - Object rtn = hash.put(key, SoftValueRef.create(key, value, queue)); - if (rtn != null) - rtn = ((SoftReference)rtn).get(); - return rtn; + return valueOrNull(hash.put(key, SoftValueRef.create(key, value, queue))); } /** @@ -218,16 +228,66 @@ public class SoftValueHashMap extends AbstractMap implements Map { * @return The value to which this key was mapped, or <code>null</code> if * there was no mapping for the key. */ - public Object remove(Object key) { + @Override + public V remove(Object key) { processQueue(); - return hash.remove(key); + return valueOrNull(hash.remove(key)); } /** * Removes all mappings from this map. */ + @Override public void clear() { processQueue(); hash.clear(); } + + /* + * Check whether the supplied value exists. + * @param Object the value to compare. + * @return true if it was found or null. + */ + @Override + public boolean containsValue(Object arg0) { + processQueue(); + if (null == arg0) + return false; + + for (SoftValueRef<K,V> e:hash.values()) + if (null != e && arg0.equals(e.get())) + return true; + return false; + } + + /* {@inheritDoc} */ + @Override + public Set<K> keySet() { + processQueue(); + return hash.keySet(); + } + + /* {@inheritDoc} */ + @Override + public void putAll(Map<? extends K,? extends V> arg0) { + processQueue(); + for (K key:arg0.keySet()) + put(key, arg0.get(key)); + } + + /* {@inheritDoc} */ + @Override + public Collection<V> values() { + processQueue(); + List<V> ret = new ArrayList<V>(); + for (SoftValueRef<K,V> e:hash.values()) + ret.add(e.get()); + return ret; + } + + private V valueOrNull(SoftValueRef<K,V> rtn) { + if (null == rtn) + return null; + return rtn.get(); + } } diff --git a/src/test/scoped/ScopedRepositoryTestCase.java b/src/test/scoped/ScopedRepositoryTestCase.java new file mode 100644 index 00000000..9dca4f56 --- /dev/null +++ b/src/test/scoped/ScopedRepositoryTestCase.java @@ -0,0 +1,242 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later, + * or the Apache License Version 2.0. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ +package scoped; + +import java.io.File; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.Map; +import java.util.stream.LongStream; + +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtField; +import javassist.CtMethod; +import javassist.scopedpool.ScopedClassPool; +import javassist.scopedpool.ScopedClassPoolRepository; +import javassist.scopedpool.ScopedClassPoolRepositoryImpl; +import javassist.scopedpool.SoftValueHashMap; +import junit.framework.TestCase; + + +/** + * ScopedRepositoryTest. + * + * @author <a href="adrian@jboss.com">Adrian Brock</a> + * @version $Revision$ + */ +public class ScopedRepositoryTestCase extends TestCase +{ + private static final ScopedClassPoolRepository repository = ScopedClassPoolRepositoryImpl.getInstance(); + + public void testJDKClasses() throws Exception + { + ClassPool poolClass = repository.findClassPool(Class.class.getClassLoader()); + assertNotNull(poolClass); + ClassPool poolString = repository.findClassPool(String.class.getClassLoader()); + assertNotNull(poolString); + assertEquals(poolClass, poolString); + } + + public void testScopedClasses() throws Exception + { + ClassLoader cl = getURLClassLoader("test-classes14-jar1"); + ClassPool pool1 = repository.findClassPool(cl); + CtClass clazz = pool1.get("scoped.jar1.TestClass1"); + assertNotNull(clazz); + ClassPool poolClass = repository.findClassPool(Class.class.getClassLoader()); + assertNotNull(poolClass); + assertNotSame(pool1, poolClass); + } + + public void testUnscopedAnnotationUsage() throws Exception + { + CtClass clazz = getCtClass(UnscopedAnnotationUsage.class); + checkTestAnnotation(clazz, "notDefault"); + } + + public void testUnscopedAnnotationDefaultUsage() throws Exception + { + CtClass clazz = getCtClass(UnscopedAnnotationDefaultUsage.class); + checkTestAnnotation(clazz, "defaultValue"); + } + + public void testScopedAnnotationUsage() throws Exception + { + ClassLoader cl = getURLClassLoader("test-classes14-jar1"); + CtClass clazz = getCtClass("scoped.jar1.ScopedAnnotationUsage", cl); + checkTestAnnotation(clazz, "notDefault"); + } + + public void testScopedAnnotationDefaultUsage() throws Exception + { + ClassLoader cl = getURLClassLoader("test-classes14-jar1"); + CtClass clazz = getCtClass("scoped.jar1.ScopedAnnotationDefaultUsage", cl); + checkTestAnnotation(clazz, "defaultValue"); + } + + public void testFullyScopedAnnotationUsage() throws Exception + { + ClassLoader cl = getURLClassLoader("test-classes14-jar1"); + CtClass clazz = getCtClass("scoped.jar1.FullyScopedAnnotationUsage", cl); + checkScopedAnnotation(cl, clazz, "notDefault"); + } + + public void testFullyScopedAnnotationDefaultUsage() throws Exception + { + ClassLoader cl = getURLClassLoader("test-classes14-jar1"); + CtClass clazz = getCtClass("scoped.jar1.FullyScopedAnnotationDefaultUsage", cl); + checkScopedAnnotation(cl, clazz, "defaultValue"); + } + + public void testSoftValueHashMap() throws Exception { + Map<String,Class<?>> map = new SoftValueHashMap<>(); + Class<?> cls = this.getClass(); + assertTrue(map.put(cls.getName(), cls) == null); + assertTrue(map.put(cls.getName(), cls) == cls); + assertTrue(map.size() == 1); + assertTrue(map.get(cls.getName()) == cls); + assertTrue(map.values().iterator().next() == cls); + assertTrue(map.entrySet().iterator().next().getValue() == cls); + assertTrue(map.containsValue(cls)); + assertTrue(map.remove(cls.getName()) == cls); + assertTrue(map.size() == 0); + } + + public void testSoftCache() throws Exception { + // Overload the heap to test that the map auto cleans + Map<String,long[]> map = new SoftValueHashMap<>(); + // 12+8*30000000 = +- 252 MB + long[] data = LongStream.range(0, 30000000).toArray(); + int current = map.size(); + while (current <= map.size()) { + current = map.size(); + for (int ii = 0; ii < 5; ii++) { + map.put(current+"-"+ii, Arrays.copyOf(data, data.length)); + } + } + assertTrue(current > map.size()); + } + + protected CtClass getCtClass(Class<?> clazz) throws Exception + { + return getCtClass(clazz.getName(), clazz.getClassLoader()); + } + + protected CtClass getCtClass(String name, ClassLoader cl) throws Exception + { + ClassPool pool = repository.findClassPool(cl); + assertNotNull(pool); + CtClass clazz = pool.get(name); + assertNotNull(clazz); + return clazz; + } + + protected void checkTestAnnotation(CtClass ctClass, String value) throws Exception + { + checkTestAnnotation(ctClass.getAnnotations(), value); + checkTestAnnotation(getFieldAnnotations(ctClass), value); + checkTestAnnotation(getConstructorAnnotations(ctClass), value); + checkTestAnnotation(getConstructorParameterAnnotations(ctClass), value); + checkTestAnnotation(getMethodAnnotations(ctClass), value); + checkTestAnnotation(getMethodParameterAnnotations(ctClass), value); + } + + protected void checkTestAnnotation(Object[] annotations, String value) throws Exception + { + assertNotNull(annotations); + assertEquals(1, annotations.length); + assertNotNull(annotations[0]); + assertTrue(annotations[0] instanceof TestAnnotation); + TestAnnotation annotation = (TestAnnotation) annotations[0]; + assertEquals(value, annotation.something()); + } + + protected void checkScopedAnnotation(ClassLoader cl, CtClass ctClass, String value) throws Exception + { + Class<?> annotationClass = cl.loadClass("scoped.jar1.ScopedTestAnnotation"); + checkScopedAnnotation(annotationClass, ctClass.getAnnotations(), value); + checkScopedAnnotation(annotationClass, getFieldAnnotations(ctClass), value); + checkScopedAnnotation(annotationClass, getConstructorAnnotations(ctClass), value); + checkScopedAnnotation(annotationClass, getConstructorParameterAnnotations(ctClass), value); + checkScopedAnnotation(annotationClass, getMethodAnnotations(ctClass), value); + checkScopedAnnotation(annotationClass, getMethodParameterAnnotations(ctClass), value); + } + + protected void checkScopedAnnotation(Class<?> annotationClass, Object[] annotations, String value) throws Exception + { + assertNotNull(annotations); + assertEquals(1, annotations.length); + assertNotNull(annotations[0]); + assertTrue(annotationClass.isInstance(annotations[0])); + + Method method = annotationClass.getMethod("something", new Class<?>[0]); + assertEquals(value, method.invoke(annotations[0], (Object[]) null)); + } + + protected Object[] getFieldAnnotations(CtClass clazz) throws Exception + { + CtField field = clazz.getField("aField"); + assertNotNull(field); + return field.getAnnotations(); + } + + protected Object[] getMethodAnnotations(CtClass clazz) throws Exception + { + CtMethod method = clazz.getMethod("doSomething", "(I)V"); + assertNotNull(method); + return method.getAnnotations(); + } + + protected Object[] getMethodParameterAnnotations(CtClass clazz) throws Exception + { + CtMethod method = clazz.getMethod("doSomething", "(I)V"); + assertNotNull(method); + Object[] paramAnnotations = method.getParameterAnnotations(); + assertNotNull(paramAnnotations); + assertEquals(1, paramAnnotations.length); + return (Object[]) paramAnnotations[0]; + } + + protected Object[] getConstructorAnnotations(CtClass clazz) throws Exception + { + CtConstructor constructor = clazz.getConstructor("(I)V"); + assertNotNull(constructor); + return constructor.getAnnotations(); + } + + protected Object[] getConstructorParameterAnnotations(CtClass clazz) throws Exception + { + CtConstructor constructor = clazz.getConstructor("(I)V"); + assertNotNull(constructor); + Object[] paramAnnotations = constructor.getParameterAnnotations(); + assertNotNull(paramAnnotations); + assertEquals(1, paramAnnotations.length); + return (Object[]) paramAnnotations[0]; + } + + protected ClassLoader getURLClassLoader(String context) throws Exception + { + String output = "."; + File file = new File(output + File.separator + context); + URL url = file.toURI().toURL(); + return new URLClassLoader(new URL[] { url }); + } +} diff --git a/src/test/scoped/TestAnnotation.java b/src/test/scoped/TestAnnotation.java new file mode 100644 index 00000000..dd5c7b8c --- /dev/null +++ b/src/test/scoped/TestAnnotation.java @@ -0,0 +1,34 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later, + * or the Apache License Version 2.0. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ +package scoped; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * TestAnnotation. + * + * @author <a href="adrian@jboss.com">Adrian Brock</a> + * @version $Revision$ + */ +@Retention(value = RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR }) +public @interface TestAnnotation +{ + String something() default "defaultValue"; +} diff --git a/src/test/scoped/UnscopedAnnotationDefaultUsage.java b/src/test/scoped/UnscopedAnnotationDefaultUsage.java new file mode 100644 index 00000000..bcbecfe6 --- /dev/null +++ b/src/test/scoped/UnscopedAnnotationDefaultUsage.java @@ -0,0 +1,29 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later, + * or the Apache License Version 2.0. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ +package scoped; + +@TestAnnotation +public class UnscopedAnnotationDefaultUsage +{ + @TestAnnotation + public int aField; + + @TestAnnotation + public UnscopedAnnotationDefaultUsage(@TestAnnotation int param) {} + + @TestAnnotation + public void doSomething(@TestAnnotation int param) {} +} diff --git a/src/test/scoped/UnscopedAnnotationUsage.java b/src/test/scoped/UnscopedAnnotationUsage.java new file mode 100644 index 00000000..e63db330 --- /dev/null +++ b/src/test/scoped/UnscopedAnnotationUsage.java @@ -0,0 +1,29 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later, + * or the Apache License Version 2.0. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ +package scoped; + +@TestAnnotation(something="notDefault") +public class UnscopedAnnotationUsage +{ + @TestAnnotation(something="notDefault") + public int aField; + + @TestAnnotation(something="notDefault") + public UnscopedAnnotationUsage(@TestAnnotation(something="notDefault") int param) {} + + @TestAnnotation(something="notDefault") + public void doSomething(@TestAnnotation(something="notDefault") int param) {} +} diff --git a/src/test/scoped/jar1/FullyScopedAnnotationDefaultUsage.java b/src/test/scoped/jar1/FullyScopedAnnotationDefaultUsage.java new file mode 100644 index 00000000..663d18f8 --- /dev/null +++ b/src/test/scoped/jar1/FullyScopedAnnotationDefaultUsage.java @@ -0,0 +1,29 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later, + * or the Apache License Version 2.0. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ +package scoped.jar1; + +@ScopedTestAnnotation +public class FullyScopedAnnotationDefaultUsage +{ + @ScopedTestAnnotation + public int aField; + + @ScopedTestAnnotation + public FullyScopedAnnotationDefaultUsage(@ScopedTestAnnotation int value) {} + + @ScopedTestAnnotation + public void doSomething(@ScopedTestAnnotation int value) {} +} diff --git a/src/test/scoped/jar1/FullyScopedAnnotationUsage.java b/src/test/scoped/jar1/FullyScopedAnnotationUsage.java new file mode 100644 index 00000000..c44aeb75 --- /dev/null +++ b/src/test/scoped/jar1/FullyScopedAnnotationUsage.java @@ -0,0 +1,29 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later, + * or the Apache License Version 2.0. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ +package scoped.jar1; + +@ScopedTestAnnotation(something="notDefault") +public class FullyScopedAnnotationUsage +{ + @ScopedTestAnnotation(something="notDefault") + public int aField; + + @ScopedTestAnnotation(something="notDefault") + public FullyScopedAnnotationUsage(@ScopedTestAnnotation(something="notDefault") int param) {} + + @ScopedTestAnnotation(something="notDefault") + public void doSomething(@ScopedTestAnnotation(something="notDefault") int param) {} +} diff --git a/src/test/scoped/jar1/ScopedAnnotationDefaultUsage.java b/src/test/scoped/jar1/ScopedAnnotationDefaultUsage.java new file mode 100644 index 00000000..284b0868 --- /dev/null +++ b/src/test/scoped/jar1/ScopedAnnotationDefaultUsage.java @@ -0,0 +1,31 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later, + * or the Apache License Version 2.0. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ +package scoped.jar1; + +import scoped.TestAnnotation; + +@TestAnnotation +public class ScopedAnnotationDefaultUsage +{ + @TestAnnotation + public int aField; + + @TestAnnotation + public ScopedAnnotationDefaultUsage(@TestAnnotation int param) {} + + @TestAnnotation + public void doSomething(@TestAnnotation int param) {} +} diff --git a/src/test/scoped/jar1/ScopedAnnotationUsage.java b/src/test/scoped/jar1/ScopedAnnotationUsage.java new file mode 100644 index 00000000..23400f27 --- /dev/null +++ b/src/test/scoped/jar1/ScopedAnnotationUsage.java @@ -0,0 +1,31 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later, + * or the Apache License Version 2.0. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ +package scoped.jar1; + +import scoped.TestAnnotation; + +@TestAnnotation(something="notDefault") +public class ScopedAnnotationUsage +{ + @TestAnnotation(something="notDefault") + public int aField; + + @TestAnnotation(something="notDefault") + public ScopedAnnotationUsage(@TestAnnotation(something="notDefault") int param) {} + + @TestAnnotation(something="notDefault") + public void doSomething(@TestAnnotation(something="notDefault") int param) {} +} diff --git a/src/test/scoped/jar1/ScopedTestAnnotation.java b/src/test/scoped/jar1/ScopedTestAnnotation.java new file mode 100644 index 00000000..25a36a58 --- /dev/null +++ b/src/test/scoped/jar1/ScopedTestAnnotation.java @@ -0,0 +1,34 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later, + * or the Apache License Version 2.0. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ +package scoped.jar1; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * TestAnnotation. + * + * @author <a href="adrian@jboss.com">Adrian Brock</a> + * @version $Revision$ + */ +@Retention(value = RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR }) +public @interface ScopedTestAnnotation +{ + String something() default "defaultValue"; +} diff --git a/src/test/scoped/jar1/TestClass1.java b/src/test/scoped/jar1/TestClass1.java new file mode 100644 index 00000000..a538bf77 --- /dev/null +++ b/src/test/scoped/jar1/TestClass1.java @@ -0,0 +1,26 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later, + * or the Apache License Version 2.0. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ +package scoped.jar1; + +/** + * TestClass1. + * + * @author <a href="adrian@jboss.com">Adrian Brock</a> + * @version $Revision$ + */ +public class TestClass1 +{ +} |