/*
* 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 Adrian Brock
* @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> 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 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 });
}
}