Przeglądaj źródła

fixed eclipse warnings

tags/V1_6_2
aclement 15 lat temu
rodzic
commit
4e4299ef56

+ 258
- 250
loadtime/src/org/aspectj/weaver/loadtime/Aj.java Wyświetl plik

@@ -26,269 +26,277 @@ import org.aspectj.weaver.tools.TraceFactory;
import org.aspectj.weaver.tools.WeavingAdaptor;

/**
* Adapter between the generic class pre processor interface and the AspectJ weaver
* Load time weaving consistency relies on Bcel.setRepository
*
* Adapter between the generic class pre processor interface and the AspectJ weaver Load time weaving consistency relies on
* Bcel.setRepository
*
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public class Aj implements ClassPreProcessor {

private IWeavingContext weavingContext;

/**
* References are added to this queue when their associated classloader is removed, and once on here that indicates
* that we should tidy up the adaptor map and remove the adaptor (weaver) from the map we are maintaining from
* adaptorkey > adaptor (weaver)
*/
private static ReferenceQueue adaptorQueue = new ReferenceQueue();
/**
* References are added to this queue when their associated classloader is removed, and once on here that indicates that we
* should tidy up the adaptor map and remove the adaptor (weaver) from the map we are maintaining from adaptorkey > adaptor
* (weaver)
*/
private static ReferenceQueue adaptorQueue = new ReferenceQueue();

private static Trace trace = TraceFactory.getTraceFactory().getTrace(Aj.class);
public Aj(){
public Aj() {
this(null);
}
public Aj(IWeavingContext context){
if (trace.isTraceEnabled()) trace.enter("<init>",this,new Object[] {context, getClass().getClassLoader()});
public Aj(IWeavingContext context) {
if (trace.isTraceEnabled())
trace.enter("<init>", this, new Object[] { context, getClass().getClassLoader() });
this.weavingContext = context;
if (trace.isTraceEnabled()) trace.exit("<init>");
if (trace.isTraceEnabled())
trace.exit("<init>");
}

/**
* Initialization
*/
public void initialize() {

}

/**
* Weave
*
* @param className
* @param bytes
* @param loader
* @return weaved bytes
*/
public byte[] preProcess(String className, byte[] bytes, ClassLoader loader) {

// TODO AV needs to doc that
if (loader == null || className == null) {
// skip boot loader or null classes (hibernate)
return bytes;
}

if (trace.isTraceEnabled())
trace.enter("preProcess", this, new Object[] { className, bytes, loader });
if (trace.isTraceEnabled())
trace.event("preProcess", this, new Object[] { loader.getParent(), Thread.currentThread().getContextClassLoader() });

try {
synchronized (loader) {
WeavingAdaptor weavingAdaptor = WeaverContainer.getWeaver(loader, weavingContext);
if (weavingAdaptor == null) {
if (trace.isTraceEnabled())
trace.exit("preProcess");
return bytes;
}
byte[] newBytes = weavingAdaptor.weaveClass(className, bytes, false);
Dump.dumpOnExit(weavingAdaptor.getMessageHolder(), true);
if (trace.isTraceEnabled())
trace.exit("preProcess", newBytes);
return newBytes;
}

/* Don't like to do this but JVMTI swallows all exceptions */
} catch (Throwable th) {
trace.error(className, th);
Dump.dumpWithException(th);
// FIXME AV wondering if we should have the option to fail (throw runtime exception) here
// would make sense at least in test f.e. see TestHelper.handleMessage()
if (trace.isTraceEnabled())
trace.exit("preProcess", th);
return bytes;
} finally {
CompilationAndWeavingContext.resetForThread();
}
}

/**
* An AdaptorKey is a WeakReference wrapping a classloader reference that will enqueue to a specified queue when the classloader
* is GC'd. Since the AdaptorKey is used as a key into a hashmap we need to give it a non-varying hashcode/equals
* implementation, and we need that hashcode not to vary even when the internal referent has been GC'd. The hashcode is
* calculated on creation of the AdaptorKey based on the loader instance that it is wrapping. This means even when the referent
* is gone we can still use the AdaptorKey and it will 'point' to the same place as it always did.
*/
private static class AdaptorKey extends WeakReference {

private int hashcode = -1;

public AdaptorKey(ClassLoader loader) {
super(loader, adaptorQueue);
hashcode = loader.hashCode() * 37;
}

public ClassLoader getClassLoader() {
ClassLoader instance = (ClassLoader) get();
// Assert instance!=null - shouldn't be asked for after a GC of the referent has occurred !
return instance;
}

public boolean equals(Object obj) {
if (!(obj instanceof AdaptorKey))
return false;
AdaptorKey other = (AdaptorKey) obj;
return other.hashcode == hashcode;
}

public int hashCode() {
return hashcode;
}

}

/**
* The reference queue is only processed when a request is made for a weaver adaptor. This means there can be one or two stale
* weavers left around. If the user knows they have finished all their weaving, they might wish to call removeStaleAdaptors
* which will process anything left on the reference queue containing adaptorKeys for garbage collected classloaders.
*
* @param displayProgress produce System.err info on the tidying up process
* @return number of stale weavers removed
*/
public static int removeStaleAdaptors(boolean displayProgress) {
int removed = 0;
synchronized (WeaverContainer.weavingAdaptors) {
if (displayProgress) {
System.err.println("Weaver adaptors before queue processing:");
Map m = WeaverContainer.weavingAdaptors;
Set keys = m.keySet();
for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
Object object = iterator.next();
System.err.println(object + " = " + WeaverContainer.weavingAdaptors.get(object));
}
}
Object o = adaptorQueue.poll();
while (o != null) {
if (displayProgress)
System.err.println("Processing referencequeue entry " + o);
AdaptorKey wo = (AdaptorKey) o;
boolean didit = WeaverContainer.weavingAdaptors.remove(wo) != null;
if (didit) {
removed++;
} else {
throw new RuntimeException("Eh?? key=" + wo);
}
if (displayProgress)
System.err.println("Removed? " + didit);
o = adaptorQueue.poll();
}
if (displayProgress) {
System.err.println("Weaver adaptors after queue processing:");
Map m = WeaverContainer.weavingAdaptors;
Set keys = m.keySet();
for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
Object object = iterator.next();
System.err.println(object + " = " + WeaverContainer.weavingAdaptors.get(object));
}
}
}
return removed;
}

/**
* @return the number of entries still in the weavingAdaptors map
*/
public static int getActiveAdaptorCount() {
return WeaverContainer.weavingAdaptors.size();
}

/**
* Process the reference queue that contains stale AdaptorKeys - the keys are put on the queue when their classloader referent
* is garbage collected and so the associated adaptor (weaver) should be removed from the map
*/
public static void checkQ() {
synchronized (adaptorQueue) {
Object o = adaptorQueue.poll();
while (o != null) {
AdaptorKey wo = (AdaptorKey) o;
// boolean removed =
WeaverContainer.weavingAdaptors.remove(wo);
// DBG System.err.println("Evicting key " + wo + " = " + didit);
o = adaptorQueue.poll();
}
}
}

/**
* Cache of weaver There is one weaver per classloader
*/
static class WeaverContainer {

final static Map weavingAdaptors = Collections.synchronizedMap(new HashMap());

static WeavingAdaptor getWeaver(ClassLoader loader, IWeavingContext weavingContext) {
ExplicitlyInitializedClassLoaderWeavingAdaptor adaptor = null;
AdaptorKey adaptorKey = new AdaptorKey(loader);

synchronized (weavingAdaptors) {
checkQ();
adaptor = (ExplicitlyInitializedClassLoaderWeavingAdaptor) weavingAdaptors.get(adaptorKey);
if (adaptor == null) {
String loaderClassName = loader.getClass().getName();
if (loaderClassName.equals("sun.reflect.DelegatingClassLoader")) {
// we don't weave reflection generated types at all!
return null;
} else {
// create it and put it back in the weavingAdaptors map but avoid any kind of instantiation
// within the synchronized block
ClassLoaderWeavingAdaptor weavingAdaptor = new ClassLoaderWeavingAdaptor();
adaptor = new ExplicitlyInitializedClassLoaderWeavingAdaptor(weavingAdaptor);
weavingAdaptors.put(adaptorKey, adaptor);
}
}
}
// perform the initialization
return adaptor.getWeavingAdaptor(loader, weavingContext);

}
}

/**
* Initialization
*/
public void initialize() {
;
}

/**
* Weave
*
* @param className
* @param bytes
* @param loader
* @return weaved bytes
*/
public byte[] preProcess(String className, byte[] bytes, ClassLoader loader) {
//TODO AV needs to doc that
if (loader == null || className == null) {
// skip boot loader or null classes (hibernate)
return bytes;
}

if (trace.isTraceEnabled()) trace.enter("preProcess",this,new Object[] {className, bytes, loader});
if (trace.isTraceEnabled()) trace.event("preProcess",this,new Object[] {loader.getParent(), Thread.currentThread().getContextClassLoader()});

try {
synchronized (loader) {
WeavingAdaptor weavingAdaptor = WeaverContainer.getWeaver(loader, weavingContext);
if (weavingAdaptor == null) {
if (trace.isTraceEnabled()) trace.exit("preProcess");
return bytes;
}
byte[] newBytes = weavingAdaptor.weaveClass(className, bytes,false);
Dump.dumpOnExit(weavingAdaptor.getMessageHolder(), true);
if (trace.isTraceEnabled()) trace.exit("preProcess",newBytes);
return newBytes;
static class ExplicitlyInitializedClassLoaderWeavingAdaptor {
private final ClassLoaderWeavingAdaptor weavingAdaptor;
private boolean isInitialized;

public ExplicitlyInitializedClassLoaderWeavingAdaptor(ClassLoaderWeavingAdaptor weavingAdaptor) {
this.weavingAdaptor = weavingAdaptor;
this.isInitialized = false;
}

private void initialize(ClassLoader loader, IWeavingContext weavingContext) {
if (!isInitialized) {
isInitialized = true;
weavingAdaptor.initialize(loader, weavingContext);
}
/* Don't like to do this but JVMTI swallows all exceptions */
} catch (Throwable th) {
trace.error(className,th);
Dump.dumpWithException(th);
//FIXME AV wondering if we should have the option to fail (throw runtime exception) here
// would make sense at least in test f.e. see TestHelper.handleMessage()
if (trace.isTraceEnabled()) trace.exit("preProcess",th);
return bytes;
} finally {
CompilationAndWeavingContext.resetForThread();
}
}

/**
* An AdaptorKey is a WeakReference wrapping a classloader reference that will enqueue to a specified queue when the
* classloader is GC'd. Since the AdaptorKey is used as a key into a hashmap we need to give it a non-varying
* hashcode/equals implementation, and we need that hashcode not to vary even when the internal referent has been
* GC'd. The hashcode is calculated on creation of the AdaptorKey based on the loader instance that it is wrapping.
* This means even when the referent is gone we can still use the AdaptorKey and it will 'point' to the same place
* as it always did.
*/
private static class AdaptorKey extends WeakReference {

private int hashcode = -1;

public AdaptorKey(ClassLoader loader) {
super(loader, adaptorQueue);
hashcode = loader.hashCode() * 37;
}

public ClassLoader getClassLoader() {
ClassLoader instance = (ClassLoader) get();
// Assert instance!=null - shouldn't be asked for after a GC of the referent has occurred !
return instance;
}

public boolean equals(Object obj) {
if (!(obj instanceof AdaptorKey)) return false;
AdaptorKey other = (AdaptorKey) obj;
return other.hashcode == hashcode;
}
public int hashCode() {
return hashcode;
}

}

/**
* The reference queue is only processed when a request is made for a weaver adaptor. This means there can be one or
* two stale weavers left around. If the user knows they have finished all their weaving, they might wish to call
* removeStaleAdaptors which will process anything left on the reference queue containing adaptorKeys for garbage
* collected classloaders.
*
* @param displayProgress produce System.err info on the tidying up process
* @return number of stale weavers removed
*/
public static int removeStaleAdaptors(boolean displayProgress) {
int removed = 0;
synchronized (WeaverContainer.weavingAdaptors) {
if (displayProgress) {
System.err.println("Weaver adaptors before queue processing:");
Map m = WeaverContainer.weavingAdaptors;
Set keys = m.keySet();
for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
Object object = iterator.next();
System.err.println(object + " = " + WeaverContainer.weavingAdaptors.get(object));
}
}
Object o = adaptorQueue.poll();
while (o != null) {
if (displayProgress) System.err.println("Processing referencequeue entry " + o);
AdaptorKey wo = (AdaptorKey) o;
boolean didit = WeaverContainer.weavingAdaptors.remove(wo) != null;
if (didit) {
removed++;
} else {
throw new RuntimeException("Eh?? key="+wo);
}
if (displayProgress) System.err.println("Removed? "+didit);
o = adaptorQueue.poll();
}
if (displayProgress) {
System.err.println("Weaver adaptors after queue processing:");
Map m = WeaverContainer.weavingAdaptors;
Set keys = m.keySet();
for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
Object object = iterator.next();
System.err.println(object + " = " + WeaverContainer.weavingAdaptors.get(object));
}
}
}
return removed;
}
/**
* @return the number of entries still in the weavingAdaptors map
*/
public static int getActiveAdaptorCount() {
return WeaverContainer.weavingAdaptors.size();
}

/**
* Process the reference queue that contains stale AdaptorKeys - the keys are put on the queue when their
* classloader referent is garbage collected and so the associated adaptor (weaver) should be removed from the map
*/
public static void checkQ() {
synchronized (adaptorQueue) {
Object o = adaptorQueue.poll();
while (o != null) {
AdaptorKey wo = (AdaptorKey) o;
boolean removed = WeaverContainer.weavingAdaptors.remove(wo) != null;
// DBG System.err.println("Evicting key " + wo + " = " + didit);
o = adaptorQueue.poll();
}
}
}

/**
* Cache of weaver
* There is one weaver per classloader
*/
static class WeaverContainer {

final static Map weavingAdaptors = Collections.synchronizedMap(new HashMap());

static WeavingAdaptor getWeaver(ClassLoader loader, IWeavingContext weavingContext) {
ExplicitlyInitializedClassLoaderWeavingAdaptor adaptor = null;
AdaptorKey adaptorKey = new AdaptorKey(loader);

synchronized (weavingAdaptors) {
checkQ();
adaptor = (ExplicitlyInitializedClassLoaderWeavingAdaptor) weavingAdaptors.get(adaptorKey);
if (adaptor == null) {
String loaderClassName = loader.getClass().getName();
if (loaderClassName.equals("sun.reflect.DelegatingClassLoader")) {
// we don't weave reflection generated types at all!
return null;
} else {
// create it and put it back in the weavingAdaptors map but avoid any kind of instantiation
// within the synchronized block
ClassLoaderWeavingAdaptor weavingAdaptor = new ClassLoaderWeavingAdaptor();
adaptor = new ExplicitlyInitializedClassLoaderWeavingAdaptor(weavingAdaptor);
weavingAdaptors.put(adaptorKey, adaptor);
}
}
}
// perform the initialization
return adaptor.getWeavingAdaptor(loader, weavingContext);

}
}

static class ExplicitlyInitializedClassLoaderWeavingAdaptor {
private final ClassLoaderWeavingAdaptor weavingAdaptor;
private boolean isInitialized;

public ExplicitlyInitializedClassLoaderWeavingAdaptor(ClassLoaderWeavingAdaptor weavingAdaptor) {
this.weavingAdaptor = weavingAdaptor;
this.isInitialized = false;
}

private void initialize(ClassLoader loader, IWeavingContext weavingContext) {
if (!isInitialized) {
isInitialized = true;
weavingAdaptor.initialize(loader, weavingContext);
}
}

public ClassLoaderWeavingAdaptor getWeavingAdaptor(ClassLoader loader, IWeavingContext weavingContext) {
initialize(loader, weavingContext);
return weavingAdaptor;
}
}

/**
* Returns a namespace based on the contest of the aspects available
*/
public String getNamespace (ClassLoader loader) {
ClassLoaderWeavingAdaptor weavingAdaptor = (ClassLoaderWeavingAdaptor)WeaverContainer.getWeaver(loader, weavingContext);
return weavingAdaptor.getNamespace();
}
/**
* Check to see if any classes have been generated for a particular classes loader.
* Calls ClassLoaderWeavingAdaptor.generatedClassesExist()
* @param loader the class cloder
* @return true if classes have been generated.
*/
public boolean generatedClassesExist(ClassLoader loader){
return ((ClassLoaderWeavingAdaptor)WeaverContainer.getWeaver(loader, weavingContext)).generatedClassesExistFor(null);
}
public void flushGeneratedClasses(ClassLoader loader){
((ClassLoaderWeavingAdaptor)WeaverContainer.getWeaver(loader, weavingContext)).flushGeneratedClasses();
}
}

public ClassLoaderWeavingAdaptor getWeavingAdaptor(ClassLoader loader, IWeavingContext weavingContext) {
initialize(loader, weavingContext);
return weavingAdaptor;
}
}

/**
* Returns a namespace based on the contest of the aspects available
*/
public String getNamespace(ClassLoader loader) {
ClassLoaderWeavingAdaptor weavingAdaptor = (ClassLoaderWeavingAdaptor) WeaverContainer.getWeaver(loader, weavingContext);
return weavingAdaptor.getNamespace();
}

/**
* Check to see if any classes have been generated for a particular classes loader. Calls
* ClassLoaderWeavingAdaptor.generatedClassesExist()
*
* @param loader the class cloder
* @return true if classes have been generated.
*/
public boolean generatedClassesExist(ClassLoader loader) {
return ((ClassLoaderWeavingAdaptor) WeaverContainer.getWeaver(loader, weavingContext)).generatedClassesExistFor(null);
}

public void flushGeneratedClasses(ClassLoader loader) {
((ClassLoaderWeavingAdaptor) WeaverContainer.getWeaver(loader, weavingContext)).flushGeneratedClasses();
}

}

+ 711
- 691
loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java
Plik diff jest za duży
Wyświetl plik


+ 304
- 340
loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java Wyświetl plik

@@ -11,6 +11,15 @@
*******************************************************************************/
package org.aspectj.weaver.loadtime;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
@@ -37,365 +46,320 @@ import org.aspectj.weaver.loadtime.definition.Definition;
import org.aspectj.weaver.patterns.PerClause;
import org.aspectj.weaver.patterns.PerSingleton;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
* Generates bytecode for concrete-aspect
* <p/>
* The concrete aspect is @AspectJ code generated. As it is build during aop.xml definitions registration
* we perform the type munging for perclause ie aspectOf artifact directly, instead of waiting for it
* to go thru the weaver (that we are in the middle of configuring).
*
* Generates bytecode for concrete-aspect <p/> The concrete aspect is @AspectJ code generated. As it is build during aop.xml
* definitions registration we perform the type munging for perclause ie aspectOf artifact directly, instead of waiting for it to go
* thru the weaver (that we are in the middle of configuring).
*
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public class ConcreteAspectCodeGen {

private final static String[] EMPTY_STRINGS = new String[0];
private final static Type[] EMPTY_TYPES = new Type[0];
/**
* Concrete aspect definition we build for
*/
private final Definition.ConcreteAspect m_concreteAspect;
/**
* World for which we build for
*/
private final World m_world;
/**
* Set to true when all is checks are verified
*/
private boolean m_isValid = false;
/**
* The parent aspect, not concretized
*/
private ResolvedType m_parent;
/**
* Aspect perClause, used for direct munging of aspectOf artifacts
*/
private PerClause m_perClause;
/**
* Create a new compiler for a concrete aspect
*
* @param concreteAspect
* @param world
*/
ConcreteAspectCodeGen(Definition.ConcreteAspect concreteAspect, World world) {
m_concreteAspect = concreteAspect;
m_world = world;
}
/**
* Checks that concrete aspect is valid
*
* @return true if ok, false otherwise
*/
public boolean validate() {
if (!(m_world instanceof BcelWorld)) {
reportError("Internal error: world must be of type BcelWorld");
return false;
}
// name must be undefined so far
// TODO only convert the name to signature once, probably earlier than this
ResolvedType current = m_world.lookupBySignature(UnresolvedType.forName(m_concreteAspect.name).getSignature());
if (current!=null && !current.isMissing()) {
reportError("Attempt to concretize but chosen aspect name already defined: " + stringify());
return false;
}
// it can happen that extends is null, for precedence only declaration
if (m_concreteAspect.extend == null && m_concreteAspect.precedence != null) {
if (m_concreteAspect.pointcuts.isEmpty()) {
m_isValid = true;
m_perClause = new PerSingleton();
m_parent = null;
return true;// no need to checks more in that special case
} else {
reportError("Attempt to use nested pointcuts without extends clause: "+stringify());
return false;
}
}
m_parent = m_world.resolve(m_concreteAspect.extend, true);
// handle inner classes
if (m_parent.isMissing()) {
// fallback on inner class lookup mechanism
String fixedName = m_concreteAspect.extend;
int hasDot = fixedName.lastIndexOf('.');
while (hasDot > 0) {
char[] fixedNameChars = fixedName.toCharArray();
fixedNameChars[hasDot] = '$';
fixedName = new String(fixedNameChars);
hasDot = fixedName.lastIndexOf('.');
m_parent = m_world.resolve(UnresolvedType.forName(fixedName), true);
if (!m_parent.isMissing()) {
break;
}
}
}
if (m_parent.isMissing()) {
reportError("Cannot find m_parent aspect for: " + stringify());
return false;
}
// extends must be abstract
if (!m_parent.isAbstract()) {
reportError("Attempt to concretize a non-abstract aspect: " + stringify());
return false;
}
// m_parent must be aspect
if (!m_parent.isAspect()) {
reportError("Attempt to concretize a non aspect: " + stringify());
return false;
}
// must have all abstractions defined
List elligibleAbstractions = new ArrayList();
Collection abstractMethods = getOutstandingAbstractMethods(m_parent);
for (Iterator iter = abstractMethods.iterator(); iter.hasNext();) {
private final static String[] EMPTY_STRINGS = new String[0];
private final static Type[] EMPTY_TYPES = new Type[0];
/**
* Concrete aspect definition we build for
*/
private final Definition.ConcreteAspect m_concreteAspect;
/**
* World for which we build for
*/
private final World m_world;
/**
* Set to true when all is checks are verified
*/
private boolean m_isValid = false;
/**
* The parent aspect, not concretized
*/
private ResolvedType m_parent;
/**
* Aspect perClause, used for direct munging of aspectOf artifacts
*/
private PerClause m_perClause;
/**
* Create a new compiler for a concrete aspect
*
* @param concreteAspect
* @param world
*/
ConcreteAspectCodeGen(Definition.ConcreteAspect concreteAspect, World world) {
m_concreteAspect = concreteAspect;
m_world = world;
}
/**
* Checks that concrete aspect is valid
*
* @return true if ok, false otherwise
*/
public boolean validate() {
if (!(m_world instanceof BcelWorld)) {
reportError("Internal error: world must be of type BcelWorld");
return false;
}
// name must be undefined so far
// TODO only convert the name to signature once, probably earlier than this
ResolvedType current = m_world.lookupBySignature(UnresolvedType.forName(m_concreteAspect.name).getSignature());
if (current != null && !current.isMissing()) {
reportError("Attempt to concretize but chosen aspect name already defined: " + stringify());
return false;
}
// it can happen that extends is null, for precedence only declaration
if (m_concreteAspect.extend == null && m_concreteAspect.precedence != null) {
if (m_concreteAspect.pointcuts.isEmpty()) {
m_isValid = true;
m_perClause = new PerSingleton();
m_parent = null;
return true;// no need to checks more in that special case
} else {
reportError("Attempt to use nested pointcuts without extends clause: " + stringify());
return false;
}
}
m_parent = m_world.resolve(m_concreteAspect.extend, true);
// handle inner classes
if (m_parent.isMissing()) {
// fallback on inner class lookup mechanism
String fixedName = m_concreteAspect.extend;
int hasDot = fixedName.lastIndexOf('.');
while (hasDot > 0) {
char[] fixedNameChars = fixedName.toCharArray();
fixedNameChars[hasDot] = '$';
fixedName = new String(fixedNameChars);
hasDot = fixedName.lastIndexOf('.');
m_parent = m_world.resolve(UnresolvedType.forName(fixedName), true);
if (!m_parent.isMissing()) {
break;
}
}
}
if (m_parent.isMissing()) {
reportError("Cannot find m_parent aspect for: " + stringify());
return false;
}
// extends must be abstract
if (!m_parent.isAbstract()) {
reportError("Attempt to concretize a non-abstract aspect: " + stringify());
return false;
}
// m_parent must be aspect
if (!m_parent.isAspect()) {
reportError("Attempt to concretize a non aspect: " + stringify());
return false;
}
// must have all abstractions defined
List elligibleAbstractions = new ArrayList();
Collection abstractMethods = getOutstandingAbstractMethods(m_parent);
for (Iterator iter = abstractMethods.iterator(); iter.hasNext();) {
ResolvedMember method = (ResolvedMember) iter.next();
if ("()V".equals(method.getSignature())) {
String n = method.getName();
if (n.startsWith("ajc$pointcut")) { // Allow for the abstract pointcut being from a code style aspect compiled with -1.5 (see test for 128744)
n = n.substring(14);
n = n.substring(0,n.indexOf("$"));
elligibleAbstractions.add(n);
} else if (hasPointcutAnnotation(method)) {
elligibleAbstractions.add(method.getName());
} else {
// error, an outstanding abstract method that can't be concretized in XML
reportError("Abstract method '" + method.toString() + "' cannot be concretized in XML: " + stringify());
return false;
}
} else {
if (method.getName().startsWith("ajc$pointcut") || hasPointcutAnnotation(method)) {
// it may be a pointcut but it doesn't meet the requirements for XML concretization
reportError("Abstract method '" + method.toString() + "' cannot be concretized as a pointcut (illegal signature, must have no arguments, must return void): " + stringify());
return false;
} else {
// error, an outstanding abstract method that can't be concretized in XML
reportError("Abstract method '" + method.toString() + "' cannot be concretized in XML: " + stringify());
return false;
}
}
String n = method.getName();
if (n.startsWith("ajc$pointcut")) { // Allow for the abstract pointcut being from a code style aspect compiled with
// -1.5 (see test for 128744)
n = n.substring(14);
n = n.substring(0, n.indexOf("$"));
elligibleAbstractions.add(n);
} else if (hasPointcutAnnotation(method)) {
elligibleAbstractions.add(method.getName());
} else {
// error, an outstanding abstract method that can't be concretized in XML
reportError("Abstract method '" + method.toString() + "' cannot be concretized in XML: " + stringify());
return false;
}
} else {
if (method.getName().startsWith("ajc$pointcut") || hasPointcutAnnotation(method)) {
// it may be a pointcut but it doesn't meet the requirements for XML concretization
reportError("Abstract method '"
+ method.toString()
+ "' cannot be concretized as a pointcut (illegal signature, must have no arguments, must return void): "
+ stringify());
return false;
} else {
// error, an outstanding abstract method that can't be concretized in XML
reportError("Abstract method '" + method.toString() + "' cannot be concretized in XML: " + stringify());
return false;
}
}
}
List pointcutNames = new ArrayList();
for (Iterator it = m_concreteAspect.pointcuts.iterator(); it.hasNext();) {
Definition.Pointcut abstractPc = (Definition.Pointcut) it.next();
pointcutNames.add(abstractPc.name);
}
List pointcutNames = new ArrayList();
for (Iterator it = m_concreteAspect.pointcuts.iterator(); it.hasNext();) {
Definition.Pointcut abstractPc = (Definition.Pointcut) it.next();
pointcutNames.add(abstractPc.name);
}
for (Iterator it = elligibleAbstractions.iterator(); it.hasNext();) {
String elligiblePc = (String) it.next();
if (!pointcutNames.contains(elligiblePc)) {
reportError("Abstract pointcut '" + elligiblePc + "' not configured: " + stringify());
return false;
}
}

m_perClause = m_parent.getPerClause();
m_isValid = true;
return m_isValid;
}

private Collection getOutstandingAbstractMethods(ResolvedType type) {
Map collector = new HashMap();
// let's get to the top of the hierarchy and then walk down ... recording abstract methods then removing
// them if they get defined further down the hierarchy
getOutstandingAbstractMethodsHelper(type,collector);
for (Iterator it = elligibleAbstractions.iterator(); it.hasNext();) {
String elligiblePc = (String) it.next();
if (!pointcutNames.contains(elligiblePc)) {
reportError("Abstract pointcut '" + elligiblePc + "' not configured: " + stringify());
return false;
}
}

m_perClause = m_parent.getPerClause();
m_isValid = true;
return m_isValid;
}

private Collection getOutstandingAbstractMethods(ResolvedType type) {
Map collector = new HashMap();
// let's get to the top of the hierarchy and then walk down ... recording abstract methods then removing
// them if they get defined further down the hierarchy
getOutstandingAbstractMethodsHelper(type, collector);
return collector.values();
}
// We are trying to determine abstract methods left over at the bottom of a hierarchy that have not been
// concretized.
private void getOutstandingAbstractMethodsHelper(ResolvedType type,Map collector) {
if (type==null) return;
// Get to the top
if (type!=null && !type.equals(ResolvedType.OBJECT)) {
if (type.getSuperclass()!=null)
getOutstandingAbstractMethodsHelper(type.getSuperclass(),collector);
}
ResolvedMember[] rms = type.getDeclaredMethods();
if (rms!=null) {
for (int i = 0; i < rms.length; i++) {

// We are trying to determine abstract methods left over at the bottom of a hierarchy that have not been
// concretized.
private void getOutstandingAbstractMethodsHelper(ResolvedType type, Map collector) {
if (type == null)
return;
// Get to the top
if (!type.equals(ResolvedType.OBJECT)) {
if (type.getSuperclass() != null)
getOutstandingAbstractMethodsHelper(type.getSuperclass(), collector);
}
ResolvedMember[] rms = type.getDeclaredMethods();
if (rms != null) {
for (int i = 0; i < rms.length; i++) {
ResolvedMember member = rms[i];
String key = member.getName()+member.getSignature();
String key = member.getName() + member.getSignature();
if (member.isAbstract()) {
collector.put(key,member);
collector.put(key, member);
} else {
collector.remove(key);
}
}
}
}
}
}
}

/**
* Rebuild the XML snip that defines this concrete aspect, for log error purpose
*
* @return string repr.
*/
private String stringify() {
StringBuffer sb = new StringBuffer("<concrete-aspect name='");
sb.append(m_concreteAspect.name);
sb.append("' extends='");
sb.append(m_concreteAspect.extend);
sb.append("'/> in aop.xml");
return sb.toString();
}
private boolean hasPointcutAnnotation(ResolvedMember member) {
AnnotationX[] as = member.getAnnotations();
if (as==null || as.length==0) return false;
for (int i = 0; i < as.length; i++) {
* Rebuild the XML snip that defines this concrete aspect, for log error purpose
*
* @return string repr.
*/
private String stringify() {
StringBuffer sb = new StringBuffer("<concrete-aspect name='");
sb.append(m_concreteAspect.name);
sb.append("' extends='");
sb.append(m_concreteAspect.extend);
sb.append("'/> in aop.xml");
return sb.toString();
}

private boolean hasPointcutAnnotation(ResolvedMember member) {
AnnotationX[] as = member.getAnnotations();
if (as == null || as.length == 0)
return false;
for (int i = 0; i < as.length; i++) {
if (as[i].getTypeSignature().equals("Lorg/aspectj/lang/annotation/Pointcut;")) {
return true;
}
}
return false;
}

public String getClassName () {
return m_concreteAspect.name;
}
/**
* Build the bytecode for the concrete aspect
*
* @return concrete aspect bytecode
*/
public byte[] getBytes() {
if (!m_isValid) {
throw new RuntimeException("Must validate first");
}

//TODO AV - abstract away from BCEL...
// @Aspect //inherit clause from m_parent
// @DeclarePrecedence("....") // if any
// public class xxxName [extends xxxExtends] {
// [@Pointcut(xxxExpression-n)
// public void xxxName-n() {}]
// }

// @Aspect public class ...
LazyClassGen cg = new LazyClassGen(
m_concreteAspect.name.replace('.', '/'),
(m_parent==null)?"java/lang/Object":m_parent.getName().replace('.', '/'),
null,//TODO AV - we could point to the aop.xml that defines it and use JSR-45
Modifier.PUBLIC + Constants.ACC_SUPER,
EMPTY_STRINGS,
m_world
);
AnnotationGen ag = new AnnotationGen(
new ObjectType("org/aspectj/lang/annotation/Aspect"),
Collections.EMPTY_LIST,
true,
cg.getConstantPool()
);
cg.addAnnotation(ag);
if (m_concreteAspect.precedence != null) {
SimpleElementValueGen svg = new SimpleElementValueGen(
ElementValueGen.STRING,
cg.getConstantPool(),
m_concreteAspect.precedence
);
List elems = new ArrayList();
elems.add(new ElementNameValuePairGen("value", svg, cg.getConstantPool()));
AnnotationGen agprec = new AnnotationGen(
new ObjectType("org/aspectj/lang/annotation/DeclarePrecedence"),
elems,
true,
cg.getConstantPool()
);
cg.addAnnotation(agprec);
}

// default constructor
LazyMethodGen init = new LazyMethodGen(
Modifier.PUBLIC,
Type.VOID,
"<init>",
EMPTY_TYPES,
EMPTY_STRINGS,
cg
);
InstructionList cbody = init.getBody();
cbody.append(InstructionConstants.ALOAD_0);
cbody.append(cg.getFactory().createInvoke(
(m_parent==null)?"java/lang/Object":m_parent.getName().replace('.', '/'),
"<init>",
Type.VOID,
EMPTY_TYPES,
Constants.INVOKESPECIAL
));
cbody.append(InstructionConstants.RETURN);
cg.addMethodGen(init);

for (Iterator it = m_concreteAspect.pointcuts.iterator(); it.hasNext();) {
Definition.Pointcut abstractPc = (Definition.Pointcut) it.next();

LazyMethodGen mg = new LazyMethodGen(
Modifier.PUBLIC,//TODO AV - respect visibility instead of opening up?
Type.VOID,
abstractPc.name,
EMPTY_TYPES,
EMPTY_STRINGS,
cg
);
SimpleElementValueGen svg = new SimpleElementValueGen(
ElementValueGen.STRING,
cg.getConstantPool(),
abstractPc.expression
);
List elems = new ArrayList();
elems.add(new ElementNameValuePairGen("value", svg, cg.getConstantPool()));
AnnotationGen mag = new AnnotationGen(
new ObjectType("org/aspectj/lang/annotation/Pointcut"),
elems,
true,
cg.getConstantPool()
);
AnnotationX max = new AnnotationX(mag, m_world);
mg.addAnnotation(max);

InstructionList body = mg.getBody();
body.append(InstructionConstants.RETURN);

cg.addMethodGen(mg);
}

// handle the perClause
ReferenceType rt = new ReferenceType(ResolvedType.forName(m_concreteAspect.name).getSignature(),m_world);
BcelPerClauseAspectAdder perClauseMunger = new BcelPerClauseAspectAdder(rt,m_perClause.getKind());
perClauseMunger.forceMunge(cg, false);

//TODO AV - unsafe cast
// register the fresh new class into the world repository as it does not exist on the classpath anywhere
JavaClass jc = cg.getJavaClass((BcelWorld) m_world);
((BcelWorld) m_world).addSourceObjectType(jc);

return jc.getBytes();
}

/**
* Error reporting
*
* @param message
*/
private void reportError(String message) {
m_world.getMessageHandler().handleMessage(new Message(message, IMessage.ERROR, null, null));
}
return false;
}

public String getClassName() {
return m_concreteAspect.name;
}

/**
* Build the bytecode for the concrete aspect
*
* @return concrete aspect bytecode
*/
public byte[] getBytes() {
if (!m_isValid) {
throw new RuntimeException("Must validate first");
}

// TODO AV - abstract away from BCEL...
// @Aspect //inherit clause from m_parent
// @DeclarePrecedence("....") // if any
// public class xxxName [extends xxxExtends] {
// [@Pointcut(xxxExpression-n)
// public void xxxName-n() {}]
// }

// @Aspect public class ...
LazyClassGen cg = new LazyClassGen(m_concreteAspect.name.replace('.', '/'), (m_parent == null) ? "java/lang/Object"
: m_parent.getName().replace('.', '/'), null,// TODO AV - we could point to the aop.xml that defines it and use
// JSR-45
Modifier.PUBLIC + Constants.ACC_SUPER, EMPTY_STRINGS, m_world);
AnnotationGen ag = new AnnotationGen(new ObjectType("org/aspectj/lang/annotation/Aspect"), Collections.EMPTY_LIST, true, cg
.getConstantPool());
cg.addAnnotation(ag);
if (m_concreteAspect.precedence != null) {
SimpleElementValueGen svg = new SimpleElementValueGen(ElementValueGen.STRING, cg.getConstantPool(),
m_concreteAspect.precedence);
List elems = new ArrayList();
elems.add(new ElementNameValuePairGen("value", svg, cg.getConstantPool()));
AnnotationGen agprec = new AnnotationGen(new ObjectType("org/aspectj/lang/annotation/DeclarePrecedence"), elems, true,
cg.getConstantPool());
cg.addAnnotation(agprec);
}

// default constructor
LazyMethodGen init = new LazyMethodGen(Modifier.PUBLIC, Type.VOID, "<init>", EMPTY_TYPES, EMPTY_STRINGS, cg);
InstructionList cbody = init.getBody();
cbody.append(InstructionConstants.ALOAD_0);
cbody.append(cg.getFactory().createInvoke((m_parent == null) ? "java/lang/Object" : m_parent.getName().replace('.', '/'),
"<init>", Type.VOID, EMPTY_TYPES, Constants.INVOKESPECIAL));
cbody.append(InstructionConstants.RETURN);
cg.addMethodGen(init);

for (Iterator it = m_concreteAspect.pointcuts.iterator(); it.hasNext();) {
Definition.Pointcut abstractPc = (Definition.Pointcut) it.next();

LazyMethodGen mg = new LazyMethodGen(Modifier.PUBLIC,// TODO AV - respect visibility instead of opening up?
Type.VOID, abstractPc.name, EMPTY_TYPES, EMPTY_STRINGS, cg);
SimpleElementValueGen svg = new SimpleElementValueGen(ElementValueGen.STRING, cg.getConstantPool(),
abstractPc.expression);
List elems = new ArrayList();
elems.add(new ElementNameValuePairGen("value", svg, cg.getConstantPool()));
AnnotationGen mag = new AnnotationGen(new ObjectType("org/aspectj/lang/annotation/Pointcut"), elems, true, cg
.getConstantPool());
AnnotationX max = new AnnotationX(mag, m_world);
mg.addAnnotation(max);

InstructionList body = mg.getBody();
body.append(InstructionConstants.RETURN);

cg.addMethodGen(mg);
}

// handle the perClause
ReferenceType rt = new ReferenceType(ResolvedType.forName(m_concreteAspect.name).getSignature(), m_world);
BcelPerClauseAspectAdder perClauseMunger = new BcelPerClauseAspectAdder(rt, m_perClause.getKind());
perClauseMunger.forceMunge(cg, false);

// TODO AV - unsafe cast
// register the fresh new class into the world repository as it does not exist on the classpath anywhere
JavaClass jc = cg.getJavaClass((BcelWorld) m_world);
((BcelWorld) m_world).addSourceObjectType(jc);

return jc.getBytes();
}

/**
* Error reporting
*
* @param message
*/
private void reportError(String message) {
m_world.getMessageHandler().handleMessage(new Message(message, IMessage.ERROR, null, null));
}
}

+ 135
- 148
loadtime/src/org/aspectj/weaver/loadtime/Options.java Wyświetl plik

@@ -11,171 +11,158 @@
*******************************************************************************/
package org.aspectj.weaver.loadtime;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.bridge.Message;
import org.aspectj.util.LangUtil;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
* A class that hanldes LTW options.
* Note: AV - I choosed to not reuse AjCompilerOptions and alike since those implies too many dependancies on
* jdt and ajdt modules.
*
* A class that hanldes LTW options. Note: AV - I choosed to not reuse AjCompilerOptions and alike since those implies too many
* dependancies on jdt and ajdt modules.
*
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public class Options {

private final static String OPTION_15 = "-1.5";
private final static String OPTION_lazyTjp = "-XlazyTjp";
private final static String OPTION_noWarn = "-nowarn";
private final static String OPTION_noWarnNone = "-warn:none";
private final static String OPTION_proceedOnError = "-proceedOnError";
private final static String OPTION_verbose = "-verbose";
private final static String OPTION_debug = "-debug";
private final static String OPTION_reweavable = "-Xreweavable";//notReweavable is default for LTW
private final static String OPTION_noinline = "-Xnoinline";
private final static String OPTION_addSerialVersionUID = "-XaddSerialVersionUID";
private final static String OPTION_hasMember = "-XhasMember";
private final static String OPTION_pinpoint = "-Xdev:pinpoint";
private final static String OPTION_showWeaveInfo = "-showWeaveInfo";
private final static String OPTIONVALUED_messageHandler = "-XmessageHandlerClass:";
private static final String OPTIONVALUED_Xlintfile = "-Xlintfile:";
private static final String OPTIONVALUED_Xlint = "-Xlint:";
private static final String OPTIONVALUED_joinpoints = "-Xjoinpoints:";
private static final String OPTIONVALUED_Xset = "-Xset:";
private final static String OPTION_15 = "-1.5";
private final static String OPTION_lazyTjp = "-XlazyTjp";
private final static String OPTION_noWarn = "-nowarn";
private final static String OPTION_noWarnNone = "-warn:none";
private final static String OPTION_proceedOnError = "-proceedOnError";
private final static String OPTION_verbose = "-verbose";
private final static String OPTION_debug = "-debug";
private final static String OPTION_reweavable = "-Xreweavable";// notReweavable is default for LTW
private final static String OPTION_noinline = "-Xnoinline";
private final static String OPTION_addSerialVersionUID = "-XaddSerialVersionUID";
private final static String OPTION_hasMember = "-XhasMember";
private final static String OPTION_pinpoint = "-Xdev:pinpoint";
private final static String OPTION_showWeaveInfo = "-showWeaveInfo";
private final static String OPTIONVALUED_messageHandler = "-XmessageHandlerClass:";
private static final String OPTIONVALUED_Xlintfile = "-Xlintfile:";
private static final String OPTIONVALUED_Xlint = "-Xlint:";
private static final String OPTIONVALUED_joinpoints = "-Xjoinpoints:";
private static final String OPTIONVALUED_Xset = "-Xset:";

public static WeaverOption parse(String options, ClassLoader laoder, IMessageHandler imh) {
WeaverOption weaverOption = new WeaverOption(imh);
public static WeaverOption parse(String options, ClassLoader laoder, IMessageHandler imh) {
WeaverOption weaverOption = new WeaverOption(imh);

if (LangUtil.isEmpty(options)) {
return weaverOption;
}
// the first option wins
List flags = LangUtil.anySplit(options, " ");
Collections.reverse(flags);
if (LangUtil.isEmpty(options)) {
return weaverOption;
}
// the first option wins
List flags = LangUtil.anySplit(options, " ");
Collections.reverse(flags);

// do a first round on the message handler since it will report the options themselves
for (Iterator iterator = flags.iterator(); iterator.hasNext();) {
String arg = (String) iterator.next();
if (arg.startsWith(OPTIONVALUED_messageHandler)) {
if (arg.length() > OPTIONVALUED_messageHandler.length()) {
String handlerClass = arg.substring(OPTIONVALUED_messageHandler.length()).trim();
try {
Class handler = Class.forName(handlerClass, false, laoder);
weaverOption.messageHandler = ((IMessageHandler) handler.newInstance());
} catch (Throwable t) {
weaverOption.messageHandler.handleMessage(
new Message(
"Cannot instantiate message handler " + handlerClass,
IMessage.ERROR,
t,
null
)
);
}
}
}
}
// do a first round on the message handler since it will report the options themselves
for (Iterator iterator = flags.iterator(); iterator.hasNext();) {
String arg = (String) iterator.next();
if (arg.startsWith(OPTIONVALUED_messageHandler)) {
if (arg.length() > OPTIONVALUED_messageHandler.length()) {
String handlerClass = arg.substring(OPTIONVALUED_messageHandler.length()).trim();
try {
Class handler = Class.forName(handlerClass, false, laoder);
weaverOption.messageHandler = ((IMessageHandler) handler.newInstance());
} catch (Throwable t) {
weaverOption.messageHandler.handleMessage(new Message("Cannot instantiate message handler " + handlerClass,
IMessage.ERROR, t, null));
}
}
}
}

// configure the other options
for (Iterator iterator = flags.iterator(); iterator.hasNext();) {
String arg = (String) iterator.next();
if (arg.equals(OPTION_15)) {
weaverOption.java5 = true;
} else if (arg.equalsIgnoreCase(OPTION_lazyTjp)) {
weaverOption.lazyTjp = true;
} else if (arg.equalsIgnoreCase(OPTION_noinline)) {
weaverOption.noInline = true;
} else if (arg.equalsIgnoreCase(OPTION_addSerialVersionUID)) {
weaverOption.addSerialVersionUID=true;
} else if (arg.equalsIgnoreCase(OPTION_noWarn) || arg.equalsIgnoreCase(OPTION_noWarnNone)) {
weaverOption.noWarn = true;
} else if (arg.equalsIgnoreCase(OPTION_proceedOnError)) {
weaverOption.proceedOnError = true;
} else if (arg.equalsIgnoreCase(OPTION_reweavable)) {
weaverOption.notReWeavable = false;
} else if (arg.equalsIgnoreCase(OPTION_showWeaveInfo)) {
weaverOption.showWeaveInfo = true;
} else if (arg.equalsIgnoreCase(OPTION_hasMember)) {
weaverOption.hasMember = true;
} else if (arg.startsWith(OPTIONVALUED_joinpoints)) {
if (arg.length()>OPTIONVALUED_joinpoints.length())
weaverOption.optionalJoinpoints = arg.substring(OPTIONVALUED_joinpoints.length()).trim();
} else if (arg.equalsIgnoreCase(OPTION_verbose)) {
weaverOption.verbose = true;
} else if (arg.equalsIgnoreCase(OPTION_debug)) {
weaverOption.debug = true;
} else if (arg.equalsIgnoreCase(OPTION_pinpoint)) {
weaverOption.pinpoint = true;
} else if (arg.startsWith(OPTIONVALUED_messageHandler)) {
;// handled in first round
} else if (arg.startsWith(OPTIONVALUED_Xlintfile)) {
if (arg.length() > OPTIONVALUED_Xlintfile.length()) {
weaverOption.lintFile = arg.substring(OPTIONVALUED_Xlintfile.length()).trim();
}
} else if (arg.startsWith(OPTIONVALUED_Xlint)) {
if (arg.length() > OPTIONVALUED_Xlint.length()) {
weaverOption.lint = arg.substring(OPTIONVALUED_Xlint.length()).trim();
}
} else if (arg.startsWith(OPTIONVALUED_Xset)) {
if (arg.length() > OPTIONVALUED_Xlint.length()) {
weaverOption.xSet = arg.substring(OPTIONVALUED_Xset.length()).trim();
}
} else {
weaverOption.messageHandler.handleMessage(
new Message(
"Cannot configure weaver with option '" + arg + "': unknown option",
IMessage.WARNING,
null,
null
)
);
}
}
// configure the other options
for (Iterator iterator = flags.iterator(); iterator.hasNext();) {
String arg = (String) iterator.next();
if (arg.equals(OPTION_15)) {
weaverOption.java5 = true;
} else if (arg.equalsIgnoreCase(OPTION_lazyTjp)) {
weaverOption.lazyTjp = true;
} else if (arg.equalsIgnoreCase(OPTION_noinline)) {
weaverOption.noInline = true;
} else if (arg.equalsIgnoreCase(OPTION_addSerialVersionUID)) {
weaverOption.addSerialVersionUID = true;
} else if (arg.equalsIgnoreCase(OPTION_noWarn) || arg.equalsIgnoreCase(OPTION_noWarnNone)) {
weaverOption.noWarn = true;
} else if (arg.equalsIgnoreCase(OPTION_proceedOnError)) {
weaverOption.proceedOnError = true;
} else if (arg.equalsIgnoreCase(OPTION_reweavable)) {
weaverOption.notReWeavable = false;
} else if (arg.equalsIgnoreCase(OPTION_showWeaveInfo)) {
weaverOption.showWeaveInfo = true;
} else if (arg.equalsIgnoreCase(OPTION_hasMember)) {
weaverOption.hasMember = true;
} else if (arg.startsWith(OPTIONVALUED_joinpoints)) {
if (arg.length() > OPTIONVALUED_joinpoints.length())
weaverOption.optionalJoinpoints = arg.substring(OPTIONVALUED_joinpoints.length()).trim();
} else if (arg.equalsIgnoreCase(OPTION_verbose)) {
weaverOption.verbose = true;
} else if (arg.equalsIgnoreCase(OPTION_debug)) {
weaverOption.debug = true;
} else if (arg.equalsIgnoreCase(OPTION_pinpoint)) {
weaverOption.pinpoint = true;
} else if (arg.startsWith(OPTIONVALUED_messageHandler)) {
// handled in first round
} else if (arg.startsWith(OPTIONVALUED_Xlintfile)) {
if (arg.length() > OPTIONVALUED_Xlintfile.length()) {
weaverOption.lintFile = arg.substring(OPTIONVALUED_Xlintfile.length()).trim();
}
} else if (arg.startsWith(OPTIONVALUED_Xlint)) {
if (arg.length() > OPTIONVALUED_Xlint.length()) {
weaverOption.lint = arg.substring(OPTIONVALUED_Xlint.length()).trim();
}
} else if (arg.startsWith(OPTIONVALUED_Xset)) {
if (arg.length() > OPTIONVALUED_Xlint.length()) {
weaverOption.xSet = arg.substring(OPTIONVALUED_Xset.length()).trim();
}
} else {
weaverOption.messageHandler.handleMessage(new Message("Cannot configure weaver with option '" + arg
+ "': unknown option", IMessage.WARNING, null, null));
}
}

// refine message handler configuration
if (weaverOption.noWarn) {
weaverOption.messageHandler.ignore(IMessage.WARNING);
}
if (weaverOption.verbose) {
weaverOption.messageHandler.dontIgnore(IMessage.INFO);
}
if (weaverOption.debug) {
weaverOption.messageHandler.dontIgnore(IMessage.DEBUG);
}
if (weaverOption.showWeaveInfo) {
weaverOption.messageHandler.dontIgnore(IMessage.WEAVEINFO);
}
// refine message handler configuration
if (weaverOption.noWarn) {
weaverOption.messageHandler.ignore(IMessage.WARNING);
}
if (weaverOption.verbose) {
weaverOption.messageHandler.dontIgnore(IMessage.INFO);
}
if (weaverOption.debug) {
weaverOption.messageHandler.dontIgnore(IMessage.DEBUG);
}
if (weaverOption.showWeaveInfo) {
weaverOption.messageHandler.dontIgnore(IMessage.WEAVEINFO);
}

return weaverOption;
}
return weaverOption;
}

public static class WeaverOption {
public static class WeaverOption {
boolean java5;
boolean lazyTjp;
boolean hasMember;
String optionalJoinpoints;
boolean noWarn;
boolean proceedOnError;
boolean verbose;
boolean debug;
boolean notReWeavable = true;//default to notReweavable for LTW (faster)
boolean noInline;
boolean addSerialVersionUID;
boolean showWeaveInfo;
boolean pinpoint;
IMessageHandler messageHandler;
String lint;
String lintFile;
String xSet;
boolean lazyTjp;
boolean hasMember;
String optionalJoinpoints;
boolean noWarn;
boolean proceedOnError;
boolean verbose;
boolean debug;
boolean notReWeavable = true;// default to notReweavable for LTW (faster)
boolean noInline;
boolean addSerialVersionUID;
boolean showWeaveInfo;
boolean pinpoint;
IMessageHandler messageHandler;
String lint;
String lintFile;
String xSet;

public WeaverOption(IMessageHandler imh) {
// messageHandler = new DefaultMessageHandler();//default
this.messageHandler = imh;
}
}
public WeaverOption(IMessageHandler imh) {
// messageHandler = new DefaultMessageHandler();//default
this.messageHandler = imh;
}
}
}

+ 190
- 201
loadtime/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java Wyświetl plik

@@ -28,93 +28,92 @@ import org.xml.sax.helpers.XMLReaderFactory;

/**
* FIXME AV - doc, concrete aspect
*
*
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public class DocumentParser extends DefaultHandler {

/**
* The current DTD public id. The matching dtd will be searched as a resource.
*/
private final static String DTD_PUBLIC_ID = "-//AspectJ//DTD 1.5.0//EN";
/**
* The current DTD public id. The matching dtd will be searched as a resource.
*/
private final static String DTD_PUBLIC_ID = "-//AspectJ//DTD 1.5.0//EN";

/**
* The DTD alias, for better user experience.
*/
private final static String DTD_PUBLIC_ID_ALIAS = "-//AspectJ//DTD//EN";

/**
* The DTD alias, for better user experience.
*/
private final static String DTD_PUBLIC_ID_ALIAS = "-//AspectJ//DTD//EN";
/**
* A handler to the DTD stream so that we are only using one file descriptor
*/
private final static InputStream DTD_STREAM = DocumentParser.class.getResourceAsStream("/aspectj_1_5_0.dtd");

/**
* A handler to the DTD stream so that we are only using one file descriptor
*/
private final static InputStream DTD_STREAM = DocumentParser.class.getResourceAsStream("/aspectj_1_5_0.dtd");
private final static String ASPECTJ_ELEMENT = "aspectj";
private final static String WEAVER_ELEMENT = "weaver";
private final static String DUMP_ELEMENT = "dump";
private final static String DUMP_BEFOREANDAFTER_ATTRIBUTE = "beforeandafter";
private final static String INCLUDE_ELEMENT = "include";
private final static String EXCLUDE_ELEMENT = "exclude";
private final static String OPTIONS_ATTRIBUTE = "options";
private final static String ASPECTS_ELEMENT = "aspects";
private final static String ASPECT_ELEMENT = "aspect";
private final static String CONCRETE_ASPECT_ELEMENT = "concrete-aspect";
private final static String NAME_ATTRIBUTE = "name";
private final static String EXTEND_ATTRIBUTE = "extends";
private final static String PRECEDENCE_ATTRIBUTE = "precedence";
private final static String POINTCUT_ELEMENT = "pointcut";
private final static String WITHIN_ATTRIBUTE = "within";
private final static String EXPRESSION_ATTRIBUTE = "expression";

private final static String ASPECTJ_ELEMENT = "aspectj";
private final static String WEAVER_ELEMENT = "weaver";
private final static String DUMP_ELEMENT = "dump";
private final static String DUMP_BEFOREANDAFTER_ATTRIBUTE = "beforeandafter";
private final static String INCLUDE_ELEMENT = "include";
private final static String EXCLUDE_ELEMENT = "exclude";
private final static String OPTIONS_ATTRIBUTE = "options";
private final static String ASPECTS_ELEMENT = "aspects";
private final static String ASPECT_ELEMENT = "aspect";
private final static String CONCRETE_ASPECT_ELEMENT = "concrete-aspect";
private final static String NAME_ATTRIBUTE = "name";
private final static String EXTEND_ATTRIBUTE = "extends";
private final static String PRECEDENCE_ATTRIBUTE = "precedence";
private final static String POINTCUT_ELEMENT = "pointcut";
private final static String WITHIN_ATTRIBUTE = "within";
private final static String EXPRESSION_ATTRIBUTE = "expression";
private final Definition m_definition;

private final Definition m_definition;
private boolean m_inAspectJ;
private boolean m_inWeaver;
private boolean m_inAspects;

private boolean m_inAspectJ;
private boolean m_inWeaver;
private boolean m_inAspects;
private Definition.ConcreteAspect m_lastConcreteAspect;

private Definition.ConcreteAspect m_lastConcreteAspect;
private DocumentParser() {
m_definition = new Definition();
}

private DocumentParser() {
m_definition = new Definition();
}
public static Definition parse(final URL url) throws Exception {
InputStream in = null;
try {
DocumentParser parser = new DocumentParser();
public static Definition parse(final URL url) throws Exception {
InputStream in = null;
try {
DocumentParser parser = new DocumentParser();

XMLReader xmlReader = getXMLReader();
xmlReader.setContentHandler(parser);
xmlReader.setErrorHandler(parser);
XMLReader xmlReader = getXMLReader();
xmlReader.setContentHandler(parser);
xmlReader.setErrorHandler(parser);

try {
xmlReader.setFeature("http://xml.org/sax/features/validation", false);
} catch (SAXException e) {
;//fine, the parser don't do validation
}
try {
xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
} catch (SAXException e) {
;//fine, the parser don't do validation
}
try {
xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
} catch (SAXException e) {
;//fine, the parser don't do validation
}
try {
xmlReader.setFeature("http://xml.org/sax/features/validation", false);
} catch (SAXException e) {
// fine, the parser don't do validation
}
try {
xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
} catch (SAXException e) {
// fine, the parser don't do validation
}
try {
xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
} catch (SAXException e) {
// fine, the parser don't do validation
}

xmlReader.setEntityResolver(parser);
in = url.openStream();
xmlReader.parse(new InputSource(in));
return parser.m_definition;
} finally {
try {
in.close();
} catch (Throwable t) {

xmlReader.setEntityResolver(parser);
in = url.openStream();
xmlReader.parse(new InputSource(in));
return parser.m_definition;
} finally {
try {
in.close();
} catch (Throwable t) {
;
}
}
}
}
}
}

private static XMLReader getXMLReader() throws SAXException, ParserConfigurationException {
XMLReader xmlReader = null;
@@ -123,7 +122,7 @@ public class DocumentParser extends DefaultHandler {
try {
xmlReader = XMLReaderFactory.createXMLReader();
}
/* .. and ignore "System property ... not set" and then try this instead */
catch (SAXException ex) {
xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
@@ -131,145 +130,135 @@ public class DocumentParser extends DefaultHandler {
return xmlReader;
}

public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
if (publicId.equals(DTD_PUBLIC_ID) || publicId.equals(DTD_PUBLIC_ID_ALIAS)) {
InputStream in = DTD_STREAM;
if (in == null) {
System.err.println(
"AspectJ - WARN - could not read DTD "
+ publicId
);
return null;
} else {
return new InputSource(in);
}
} else {
System.err.println(
"AspectJ - WARN - unknown DTD "
+ publicId
+ " - consider using "
+ DTD_PUBLIC_ID
);
return null;
}
}
public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
if (publicId.equals(DTD_PUBLIC_ID) || publicId.equals(DTD_PUBLIC_ID_ALIAS)) {
InputStream in = DTD_STREAM;
if (in == null) {
System.err.println("AspectJ - WARN - could not read DTD " + publicId);
return null;
} else {
return new InputSource(in);
}
} else {
System.err.println("AspectJ - WARN - unknown DTD " + publicId + " - consider using " + DTD_PUBLIC_ID);
return null;
}
}

public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (ASPECT_ELEMENT.equals(qName)) {
String name = attributes.getValue(NAME_ATTRIBUTE);
if (!isNull(name)) {
m_definition.getAspectClassNames().add(name);
}
} else if (WEAVER_ELEMENT.equals(qName)) {
String options = attributes.getValue(OPTIONS_ATTRIBUTE);
if (!isNull(options)) {
m_definition.appendWeaverOptions(options);
}
m_inWeaver = true;
} else if (CONCRETE_ASPECT_ELEMENT.equals(qName)) {
String name = attributes.getValue(NAME_ATTRIBUTE);
String extend = attributes.getValue(EXTEND_ATTRIBUTE);
String precedence = attributes.getValue(PRECEDENCE_ATTRIBUTE);
if (!isNull(name)) {
if (isNull(precedence) && !isNull(extend)) {//if no precedence, then extends must be there
m_lastConcreteAspect = new Definition.ConcreteAspect(name, extend);
} else if (!isNull(precedence)) {
// wether a pure precedence def, or an extendsANDprecedence def.
m_lastConcreteAspect = new Definition.ConcreteAspect(name, extend, precedence);
}
m_definition.getConcreteAspects().add(m_lastConcreteAspect);
}
} else if (POINTCUT_ELEMENT.equals(qName) && m_lastConcreteAspect != null) {
String name = attributes.getValue(NAME_ATTRIBUTE);
String expression = attributes.getValue(EXPRESSION_ATTRIBUTE);
if (!isNull(name) && !isNull(expression)) {
m_lastConcreteAspect.pointcuts.add(new Definition.Pointcut(name, replaceXmlAnd(expression)));
}
} else if (ASPECTJ_ELEMENT.equals(qName)) {
if (m_inAspectJ) {
throw new SAXException("Found nested <aspectj> element");
}
m_inAspectJ = true;
} else if (ASPECTS_ELEMENT.equals(qName)) {
m_inAspects = true;
} else if (INCLUDE_ELEMENT.equals(qName) && m_inWeaver) {
String typePattern = getWithinAttribute(attributes);
if (!isNull(typePattern)) {
m_definition.getIncludePatterns().add(typePattern);
}
} else if (EXCLUDE_ELEMENT.equals(qName) && m_inWeaver) {
String typePattern = getWithinAttribute(attributes);
if (!isNull(typePattern)) {
m_definition.getExcludePatterns().add(typePattern);
}
} else if (DUMP_ELEMENT.equals(qName) && m_inWeaver) {
String typePattern = getWithinAttribute(attributes);
if (!isNull(typePattern)) {
m_definition.getDumpPatterns().add(typePattern);
}
String beforeAndAfter = attributes.getValue(DUMP_BEFOREANDAFTER_ATTRIBUTE);
if (isTrue(beforeAndAfter)) {
m_definition.setDumpBefore(true);
}
} else if (EXCLUDE_ELEMENT.equals(qName) && m_inAspects) {
String typePattern = getWithinAttribute(attributes);
if (!isNull(typePattern)) {
m_definition.getAspectExcludePatterns().add(typePattern);
}
} else if (INCLUDE_ELEMENT.equals(qName) && m_inAspects) {
String typePattern = getWithinAttribute(attributes);
if (!isNull(typePattern)) {
m_definition.getAspectIncludePatterns().add(typePattern);
}
} else {
throw new SAXException("Unknown element while parsing <aspectj> element: " + qName);
}
super.startElement(uri, localName, qName, attributes);
}
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (ASPECT_ELEMENT.equals(qName)) {
String name = attributes.getValue(NAME_ATTRIBUTE);
if (!isNull(name)) {
m_definition.getAspectClassNames().add(name);
}
} else if (WEAVER_ELEMENT.equals(qName)) {
String options = attributes.getValue(OPTIONS_ATTRIBUTE);
if (!isNull(options)) {
m_definition.appendWeaverOptions(options);
}
m_inWeaver = true;
} else if (CONCRETE_ASPECT_ELEMENT.equals(qName)) {
String name = attributes.getValue(NAME_ATTRIBUTE);
String extend = attributes.getValue(EXTEND_ATTRIBUTE);
String precedence = attributes.getValue(PRECEDENCE_ATTRIBUTE);
if (!isNull(name)) {
if (isNull(precedence) && !isNull(extend)) {// if no precedence, then extends must be there
m_lastConcreteAspect = new Definition.ConcreteAspect(name, extend);
} else if (!isNull(precedence)) {
// wether a pure precedence def, or an extendsANDprecedence def.
m_lastConcreteAspect = new Definition.ConcreteAspect(name, extend, precedence);
}
m_definition.getConcreteAspects().add(m_lastConcreteAspect);
}
} else if (POINTCUT_ELEMENT.equals(qName) && m_lastConcreteAspect != null) {
String name = attributes.getValue(NAME_ATTRIBUTE);
String expression = attributes.getValue(EXPRESSION_ATTRIBUTE);
if (!isNull(name) && !isNull(expression)) {
m_lastConcreteAspect.pointcuts.add(new Definition.Pointcut(name, replaceXmlAnd(expression)));
}
} else if (ASPECTJ_ELEMENT.equals(qName)) {
if (m_inAspectJ) {
throw new SAXException("Found nested <aspectj> element");
}
m_inAspectJ = true;
} else if (ASPECTS_ELEMENT.equals(qName)) {
m_inAspects = true;
} else if (INCLUDE_ELEMENT.equals(qName) && m_inWeaver) {
String typePattern = getWithinAttribute(attributes);
if (!isNull(typePattern)) {
m_definition.getIncludePatterns().add(typePattern);
}
} else if (EXCLUDE_ELEMENT.equals(qName) && m_inWeaver) {
String typePattern = getWithinAttribute(attributes);
if (!isNull(typePattern)) {
m_definition.getExcludePatterns().add(typePattern);
}
} else if (DUMP_ELEMENT.equals(qName) && m_inWeaver) {
String typePattern = getWithinAttribute(attributes);
if (!isNull(typePattern)) {
m_definition.getDumpPatterns().add(typePattern);
}
String beforeAndAfter = attributes.getValue(DUMP_BEFOREANDAFTER_ATTRIBUTE);
if (isTrue(beforeAndAfter)) {
m_definition.setDumpBefore(true);
}
} else if (EXCLUDE_ELEMENT.equals(qName) && m_inAspects) {
String typePattern = getWithinAttribute(attributes);
if (!isNull(typePattern)) {
m_definition.getAspectExcludePatterns().add(typePattern);
}
} else if (INCLUDE_ELEMENT.equals(qName) && m_inAspects) {
String typePattern = getWithinAttribute(attributes);
if (!isNull(typePattern)) {
m_definition.getAspectIncludePatterns().add(typePattern);
}
} else {
throw new SAXException("Unknown element while parsing <aspectj> element: " + qName);
}
super.startElement(uri, localName, qName, attributes);
}

private String getWithinAttribute(Attributes attributes) {
return replaceXmlAnd(attributes.getValue(WITHIN_ATTRIBUTE));
}

public void endElement(String uri, String localName, String qName) throws SAXException {
if (CONCRETE_ASPECT_ELEMENT.equals(qName)) {
m_lastConcreteAspect = null;
} else if (ASPECTJ_ELEMENT.equals(qName)) {
m_inAspectJ = false;
} else if (WEAVER_ELEMENT.equals(qName)) {
m_inWeaver = false;
} else if (ASPECTS_ELEMENT.equals(qName)) {
m_inAspects = false;
}
super.endElement(uri, localName, qName);
}

//TODO AV - define what we want for XML parser error - for now stderr
public void warning(SAXParseException e) throws SAXException {
super.warning(e);
}

public void error(SAXParseException e) throws SAXException {
super.error(e);
}
public void endElement(String uri, String localName, String qName) throws SAXException {
if (CONCRETE_ASPECT_ELEMENT.equals(qName)) {
m_lastConcreteAspect = null;
} else if (ASPECTJ_ELEMENT.equals(qName)) {
m_inAspectJ = false;
} else if (WEAVER_ELEMENT.equals(qName)) {
m_inWeaver = false;
} else if (ASPECTS_ELEMENT.equals(qName)) {
m_inAspects = false;
}
super.endElement(uri, localName, qName);
}

public void fatalError(SAXParseException e) throws SAXException {
super.fatalError(e);
}
// TODO AV - define what we want for XML parser error - for now stderr
public void warning(SAXParseException e) throws SAXException {
super.warning(e);
}

public void error(SAXParseException e) throws SAXException {
super.error(e);
}

private static String replaceXmlAnd(String expression) {
//TODO AV do we need to handle "..)AND" or "AND(.." ?
return LangUtil.replace(expression, " AND ", " && ");
}
public void fatalError(SAXParseException e) throws SAXException {
super.fatalError(e);
}

private boolean isNull(String s) {
return (s == null || s.length() <= 0);
}
private static String replaceXmlAnd(String expression) {
// TODO AV do we need to handle "..)AND" or "AND(.." ?
return LangUtil.replace(expression, " AND ", " && ");
}

private boolean isTrue(String s) {
return (s != null && s.equals("true"));
}
private boolean isNull(String s) {
return (s == null || s.length() <= 0);
}

private boolean isTrue(String s) {
return (s != null && s.equals("true"));
}

}

+ 7
- 5
loadtime/testsrc/org/aspectj/weaver/loadtime/AjTest.java Wyświetl plik

@@ -18,13 +18,15 @@ import junit.framework.TestCase;
public class AjTest extends TestCase {

public void testAj() {
Aj aj = new Aj();
// Aj aj =
new Aj();
}

public void testAjIWeavingContext() {
ClassLoader loader = new URLClassLoader(new URL[] {}, null);
IWeavingContext weavingContext = new DefaultWeavingContext(loader);
Aj aj = new Aj(weavingContext);
// Aj aj =
new Aj(weavingContext);
}

public void testInitialize() {
@@ -42,14 +44,14 @@ public class AjTest extends TestCase {
ClassLoader loader = new URLClassLoader(new URL[] {}, null);
Aj aj = new Aj();
String namespace = aj.getNamespace(loader);
assertEquals("Namespace should be empty","",namespace);
assertEquals("Namespace should be empty", "", namespace);
}

public void testGeneratedClassesExist() {
ClassLoader loader = new URLClassLoader(new URL[] {}, null);
Aj aj = new Aj();
boolean exist = aj.generatedClassesExist(loader);
assertFalse("There should be no generated classes",exist);
assertFalse("There should be no generated classes", exist);
}

public void testFlushGeneratedClasses() {
@@ -57,7 +59,7 @@ public class AjTest extends TestCase {
Aj aj = new Aj();
aj.flushGeneratedClasses(loader);
boolean exist = aj.generatedClassesExist(loader);
assertFalse("There should be no generated classes",exist);
assertFalse("There should be no generated classes", exist);
}

}

+ 93
- 86
loadtime/testsrc/org/aspectj/weaver/loadtime/JRockitAgentTest.java Wyświetl plik

@@ -24,11 +24,11 @@ import java.util.List;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;

import junit.framework.TestCase;

import com.bea.jvm.ClassPreProcessor;
import com.bea.jvm.JVMFactory;

import junit.framework.TestCase;

public class JRockitAgentTest extends TestCase {

protected void setUp() throws Exception {
@@ -42,16 +42,16 @@ public class JRockitAgentTest extends TestCase {
public void testJRockitAgent() {
ClassPreProcessor preProcessor = new JRockitAgent();
ClassPreProcessor expectedPreProcessor = JVMFactory.getJVM().getClassLibrary().getClassPreProcessor();
assertEquals("JRocketAgent must be registered",expectedPreProcessor,preProcessor);
assertEquals("JRocketAgent must be registered", expectedPreProcessor, preProcessor);
}

public void testPreProcess() {
ClassPreProcessor preProcessor = new JRockitAgent();
preProcessor.preProcess(null,"foo.Bar",new byte[] {});
preProcessor.preProcess(null, "foo.Bar", new byte[] {});
}

public void testJrockitRecursionProtection () {
URLClassLoader thisLoader = (URLClassLoader)getClass().getClassLoader();
public void testJrockitRecursionProtection() {
URLClassLoader thisLoader = (URLClassLoader) getClass().getClassLoader();
ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();

try {
@@ -60,29 +60,26 @@ public class JRockitAgentTest extends TestCase {

ClassLoader loader = new JRockitClassLoader(thisLoader);

Class clazz;
clazz = Class.forName("java.lang.Object",false,loader);
clazz = Class.forName("junit.framework.TestCase",false,loader);
}
catch (Exception ex) {
Class.forName("java.lang.Object", false, loader);
Class.forName("junit.framework.TestCase", false, loader);
} catch (Exception ex) {
ex.printStackTrace();
fail(ex.toString());
}
finally {
} finally {
Thread.currentThread().setContextClassLoader(contextLoader);
}
}

private class JRockitClassLoader extends ClassLoader {
public final static boolean debug = false;
private List path = new LinkedList();
// private com.bea.jvm.ClassPreProcessor agent;
// private com.bea.jvm.ClassPreProcessor agent;
private Object agent;
private Method preProcess;
public JRockitClassLoader (URLClassLoader clone) throws Exception {
public JRockitClassLoader(URLClassLoader clone) throws Exception {
/* Use extensions loader */
super(clone.getParent());

@@ -90,132 +87,142 @@ public class JRockitAgentTest extends TestCase {
for (int i = 0; i < urls.length; i++) {
Object pathElement;
URL url = urls[i];
if (debug) System.out.println("JRockitClassLoader.JRockitClassLoader() url=" + url.getPath());
if (debug)
System.out.println("JRockitClassLoader.JRockitClassLoader() url=" + url.getPath());
File file = new File(encode(url.getFile()));
if (debug) System.out.println("JRockitClassLoader.JRockitClassLoader() file" + file);
if (file.isDirectory()) pathElement = file;
else if (file.exists() && file.getName().endsWith(".jar")) pathElement = new JarFile(file);
else throw new RuntimeException(file.getAbsolutePath().toString());
if (debug)
System.out.println("JRockitClassLoader.JRockitClassLoader() file" + file);
if (file.isDirectory())
pathElement = file;
else if (file.exists() && file.getName().endsWith(".jar"))
pathElement = new JarFile(file);
else
throw new RuntimeException(file.getAbsolutePath().toString());
path.add(pathElement);
}
Class agentClazz = Class.forName("org.aspectj.weaver.loadtime.JRockitAgent",false,this);
Class agentClazz = Class.forName("org.aspectj.weaver.loadtime.JRockitAgent", false, this);
Object obj = agentClazz.newInstance();
if (debug) System.out.println("JRockitClassLoader.JRockitClassLoader() obj=" + obj);
if (debug)
System.out.println("JRockitClassLoader.JRockitClassLoader() obj=" + obj);
this.agent = obj;
byte[] bytes = new byte[] {};
Class[] parameterTypes = new Class[] { java.lang.ClassLoader.class, java.lang.String.class, bytes.getClass() };
preProcess = agentClazz.getMethod("preProcess",parameterTypes);
Class[] parameterTypes = new Class[] { java.lang.ClassLoader.class, java.lang.String.class, bytes.getClass() };
preProcess = agentClazz.getMethod("preProcess", parameterTypes);
}
/* Get rid of escaped characters */
private String encode (String s) {
private String encode(String s) {
StringBuffer result = new StringBuffer();
int i = s.indexOf("%");
while (i != -1) {
result.append(s.substring(0,i));
String escaped = s.substring(i+1,i+3);
s = s.substring(i+3);
Integer value = Integer.valueOf(escaped,16);
result.append(new Character((char)value.intValue()));
result.append(s.substring(0, i));
String escaped = s.substring(i + 1, i + 3);
s = s.substring(i + 3);
Integer value = Integer.valueOf(escaped, 16);
result.append(new Character((char) value.intValue()));
i = s.indexOf("%");
}
result.append(s);
return result.toString();
}
protected Class findClass(String name) throws ClassNotFoundException {
if (debug) System.out.println("> JRockitClassLoader.findClass() name=" + name);
if (debug)
System.out.println("> JRockitClassLoader.findClass() name=" + name);
Class clazz = null;
try {
clazz = super.findClass(name);
}
catch (ClassNotFoundException ex) {
for (Iterator i = path.iterator(); clazz == null && i.hasNext();) {
} catch (ClassNotFoundException ex) {
for (Iterator i = path.iterator(); clazz == null && i.hasNext();) {
byte[] classBytes = null;
try {
Object pathElement = i.next();
if (pathElement instanceof File) {
File dir = (File)pathElement;
String className = name.replace('.','/') + ".class";
File classFile = new File(dir,className);
if (classFile.exists()) classBytes = loadClassFromFile(name,classFile);
}
else {
JarFile jar = (JarFile)pathElement;
String className = name.replace('.','/') + ".class";
File dir = (File) pathElement;
String className = name.replace('.', '/') + ".class";
File classFile = new File(dir, className);
if (classFile.exists())
classBytes = loadClassFromFile(name, classFile);
} else {
JarFile jar = (JarFile) pathElement;
String className = name.replace('.', '/') + ".class";
ZipEntry entry = jar.getEntry(className);
if (entry != null) classBytes = loadBytesFromZipEntry(jar,entry);
if (entry != null)
classBytes = loadBytesFromZipEntry(jar, entry);
}
if (classBytes != null) {
clazz = defineClass(name,classBytes);
clazz = defineClass(name, classBytes);
}
}
catch (IOException ioException) {
} catch (IOException ioException) {
ex.printStackTrace();
}
}
}
if (debug) System.out.println("< JRockitClassLoader.findClass() name=" + name);

if (debug)
System.out.println("< JRockitClassLoader.findClass() name=" + name);
return clazz;
}
private Class defineClass (String name, byte[] bytes) {
if (debug) System.out.println("> JRockitClassLoader.defineClass() name=" + name);

private Class defineClass(String name, byte[] bytes) {
if (debug)
System.out.println("> JRockitClassLoader.defineClass() name=" + name);
try {
if (agent != null) preProcess.invoke(agent,new Object[] { this, name, bytes });
}
catch (IllegalAccessException iae) {
if (agent != null)
preProcess.invoke(agent, new Object[] { this, name, bytes });
} catch (IllegalAccessException iae) {
iae.printStackTrace();
throw new ClassFormatError(iae.getMessage());
}
catch (InvocationTargetException ite) {
} catch (InvocationTargetException ite) {
ite.printStackTrace();
throw new ClassFormatError(ite.getTargetException().getMessage());
}
if (debug) System.out.println("< JRockitClassLoader.defineClass() name=" + name);
return super.defineClass(name,bytes,0,bytes.length);
if (debug)
System.out.println("< JRockitClassLoader.defineClass() name=" + name);
return super.defineClass(name, bytes, 0, bytes.length);
}
private byte[] loadClassFromFile (String name, File file) throws IOException {
if (debug) System.out.println("JRockitClassLoader.loadClassFromFile() file=" + file);

private byte[] loadClassFromFile(String name, File file) throws IOException {
if (debug)
System.out.println("JRockitClassLoader.loadClassFromFile() file=" + file);

byte[] bytes;
bytes = new byte[(int)file.length()];
bytes = new byte[(int) file.length()];
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
bytes = readBytes(fis,bytes);
bytes = readBytes(fis, bytes);
} finally {
if (fis != null)
fis.close();
}
finally {
if (fis != null) fis.close();
}

return bytes;
}
private byte[] loadBytesFromZipEntry (JarFile jar, ZipEntry entry) throws IOException {
if (debug) System.out.println("JRockitClassLoader.loadBytesFromZipEntry() entry=" + entry);

private byte[] loadBytesFromZipEntry(JarFile jar, ZipEntry entry) throws IOException {
if (debug)
System.out.println("JRockitClassLoader.loadBytesFromZipEntry() entry=" + entry);

byte[] bytes;
bytes = new byte[(int)entry.getSize()];
bytes = new byte[(int) entry.getSize()];
InputStream is = null;
try {
is = jar.getInputStream(entry);
bytes = readBytes(is,bytes);
bytes = readBytes(is, bytes);
} finally {
if (is != null)
is.close();
}
finally {
if (is != null) is.close();
}

return bytes;
}
private byte[] readBytes (InputStream is, byte[] bytes) throws IOException {

private byte[] readBytes(InputStream is, byte[] bytes) throws IOException {
for (int offset = 0; offset < bytes.length;) {
int read = is.read(bytes,offset,bytes.length - offset);
int read = is.read(bytes, offset, bytes.length - offset);
offset += read;
}
return bytes;

Ładowanie…
Anuluj
Zapisz