package org.aspectj.weaver.ltw;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.util.LangUtil;
import org.aspectj.weaver.Dump.IVisitor;
import org.aspectj.weaver.ICrossReferenceHandler;
import org.aspectj.weaver.ReferenceType;
import org.aspectj.weaver.ReferenceTypeDelegate;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.bcel.BcelWorld;
import org.aspectj.weaver.loadtime.IWeavingContext;
import org.aspectj.weaver.reflect.AnnotationFinder;
import org.aspectj.weaver.reflect.IReflectionWorld;
import org.aspectj.weaver.reflect.ReflectionBasedReferenceTypeDelegateFactory;
import org.aspectj.weaver.reflect.ReflectionWorld;
public class LTWWorld extends BcelWorld implements IReflectionWorld {
private AnnotationFinder annotationFinder;
private IWeavingContext weavingContext;
private String classLoaderString;
private String classLoaderParentString;
protected final static Class concurrentMapClass;
private static final boolean ShareBootstrapTypes = false;
protected static MapbootstrapTypes;
static {
if (ShareBootstrapTypes) {
concurrentMapClass = makeConcurrentMapClass();
bootstrapTypes = makeConcurrentMap();
} else {
concurrentMapClass = null;
}
}
public LTWWorld(ClassLoader loader, IWeavingContext weavingContext, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
super(loader, handler, xrefHandler);
this.weavingContext = weavingContext;
try {
classLoaderString = loader.toString();
} catch (Throwable t) {
classLoaderString = loader.getClass().getName()+":"+Integer.toString(System.identityHashCode(loader));
}
classLoaderParentString = (loader.getParent() == null ? "<NullParent>" : loader.getParent().toString());
setBehaveInJava5Way(LangUtil.is15VMOrGreater());
annotationFinder = ReflectionWorld.makeAnnotationFinderIfAny(loader, this);
}
public ClassLoader getClassLoader() {
return weavingContext.getClassLoader();
}
@Override
protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) {
ReferenceTypeDelegate bootstrapLoaderDelegate = resolveIfBootstrapDelegate(ty);
if (bootstrapLoaderDelegate != null) {
return bootstrapLoaderDelegate;
}
return super.resolveDelegate(ty);
}
protected ReferenceTypeDelegate resolveIfBootstrapDelegate(ReferenceType ty) {
return null;
}
private ReferenceTypeDelegate resolveReflectionTypeDelegate(ReferenceType ty, ClassLoader resolutionLoader) {
ReferenceTypeDelegate res = ReflectionBasedReferenceTypeDelegateFactory.createDelegate(ty, this, resolutionLoader);
return res;
}
public void loadedClass(Class clazz) {
}
private static final long serialVersionUID = 1;
public AnnotationFinder getAnnotationFinder() {
return this.annotationFinder;
}
public ResolvedType resolve(Class aClass) {
return ReflectionWorld.resolve(this, aClass);
}
private static Map makeConcurrentMap() {
if (concurrentMapClass != null) {
try {
return (Map) concurrentMapClass.newInstance();
} catch (InstantiationException ie) {
} catch (IllegalAccessException iae) {
}
}
return Collections.synchronizedMap(new HashMap());
}
private static Class makeConcurrentMapClass() {
String betterChoices[] = { "java.util.concurrent.ConcurrentHashMap",
"edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap",
"EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap" };
for (int i = 0; i < betterChoices.length; i++) {
try {
return Class.forName(betterChoices[i]);
} catch (ClassNotFoundException cnfe) {
} catch (SecurityException se) {
}
}
return null;
}
@Override
public boolean isRunMinimalMemory() {
if (isRunMinimalMemorySet()) {
return super.isRunMinimalMemory();
}
return false;
}
private boolean typeCompletionInProgress = false;
private ListtypesForCompletion = new ArrayList();
@Override
protected void completeBinaryType(ResolvedType ret) {
if (isLocallyDefined(ret.getName())) {
if (typeCompletionInProgress) {
typesForCompletion.add(ret);
} else {
try {
typeCompletionInProgress = true;
completeHierarchyForType(ret);
} finally {
typeCompletionInProgress = false;
}
while (typesForCompletion.size() != 0) {
ResolvedType rt = (ResolvedType) typesForCompletion.get(0);
completeHierarchyForType(rt);
typesForCompletion.remove(0);
}
}
} else {
if (!ret.needsModifiableDelegate()) {
ret = completeNonLocalType(ret);
}
}
}
private void completeHierarchyForType(ResolvedType ret) {
getLint().typeNotExposedToWeaver.setSuppressed(true);
weaveInterTypeDeclarations(ret);
getLint().typeNotExposedToWeaver.setSuppressed(false);
}
protected boolean needsCompletion() {
return true;
}
@Override
public boolean isLocallyDefined(String classname) {
return weavingContext.isLocallyDefined(classname);
}
protected ResolvedType completeNonLocalType(ResolvedType ret) {
if (ret.isMissing()) {
return ret;
}
ResolvedType toResolve = ret;
if (ret.isParameterizedType() || ret.isGenericType()) {
toResolve = toResolve.getGenericType();
}
ReferenceTypeDelegate rtd = resolveReflectionTypeDelegate((ReferenceType) toResolve, getClassLoader());
((ReferenceType) ret).setDelegate(rtd);
return ret;
}
@Override
public void storeClass(JavaClass clazz) {
ensureRepositorySetup();
delegate.storeClass(clazz);
}
@Override
public void accept(IVisitor visitor) {
visitor.visitObject("Class loader:");
visitor.visitObject(classLoaderString);
visitor.visitObject("Class loader parent:");
visitor.visitObject(classLoaderParentString);
super.accept(visitor);
}
public boolean isLoadtimeWeaving() {
return true;
}
}