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();
+ }
}
\ No newline at end of file
*/
public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
- private final static String AOP_XML = Constants.AOP_USER_XML + ";" + Constants.AOP_AJC_XML + ";" + Constants.AOP_OSGI_XML;
-
- private boolean initialized;
-
- private List m_dumpTypePattern = new ArrayList();
- private boolean m_dumpBefore = false;
- private List m_includeTypePattern = new ArrayList();
- private List m_excludeTypePattern = new ArrayList();
- private List m_includeStartsWith = new ArrayList();
- private List m_excludeStartsWith = new ArrayList();
- private List m_aspectExcludeTypePattern = new ArrayList();
- private List m_aspectExcludeStartsWith = new ArrayList();
- private List m_aspectIncludeTypePattern = new ArrayList();
- private List m_aspectIncludeStartsWith = new ArrayList();
-
- private StringBuffer namespace;
- private IWeavingContext weavingContext;
-
- private List concreteAspects = new ArrayList();
+ private final static String AOP_XML = Constants.AOP_USER_XML + ";" + Constants.AOP_AJC_XML + ";" + Constants.AOP_OSGI_XML;
+
+ private boolean initialized;
+
+ private List m_dumpTypePattern = new ArrayList();
+ private boolean m_dumpBefore = false;
+ private List m_includeTypePattern = new ArrayList();
+ private List m_excludeTypePattern = new ArrayList();
+ private List m_includeStartsWith = new ArrayList();
+ private List m_excludeStartsWith = new ArrayList();
+ private List m_aspectExcludeTypePattern = new ArrayList();
+ private List m_aspectExcludeStartsWith = new ArrayList();
+ private List m_aspectIncludeTypePattern = new ArrayList();
+ private List m_aspectIncludeStartsWith = new ArrayList();
+
+ private StringBuffer namespace;
+ private IWeavingContext weavingContext;
+
+ private List concreteAspects = new ArrayList();
private static Trace trace = TraceFactory.getTraceFactory().getTrace(ClassLoaderWeavingAdaptor.class);
-
- public ClassLoaderWeavingAdaptor() {
- super();
- if (trace.isTraceEnabled()) trace.enter("<init>",this);
- if (trace.isTraceEnabled()) trace.exit("<init>");
- }
-
- /**
- * We don't need a reference to the class loader and using it during
- * construction can cause problems with recursion. It also makes sense
- * to supply the weaving context during initialization to.
- * @deprecated
- */
- public ClassLoaderWeavingAdaptor(final ClassLoader deprecatedLoader, final IWeavingContext deprecatedContext) {
- super();
- if (trace.isTraceEnabled()) trace.enter("<init>",this,new Object[] { deprecatedLoader, deprecatedContext });
- if (trace.isTraceEnabled()) trace.exit("<init>");
- }
-
- class SimpleGeneratedClassHandler implements GeneratedClassHandler {
- private WeakClassLoaderReference loaderRef;
- SimpleGeneratedClassHandler(ClassLoader loader) {
- loaderRef = new WeakClassLoaderReference(loader);
- }
-
- /**
- * Callback when we need to define a Closure in the JVM
- *
- */
- public void acceptClass(String name, byte[] bytes) {
- try {
- if (shouldDump(name.replace('/', '.'), false)) {
- dump(name, bytes, false);
- }
- } catch (Throwable throwable) {
- throwable.printStackTrace();
- }
-
- defineClass(loaderRef.getClassLoader(), name, bytes); // could be done lazily using the hook
- }
- };
-
- protected void initialize (final ClassLoader classLoader, IWeavingContext context) {
- if (initialized) return;
-
- boolean success = true;
- // if (trace.isTraceEnabled()) trace.enter("initialize",this,new Object[] { classLoader, context });
-
- this.weavingContext = context;
- if (weavingContext == null) {
- weavingContext = new DefaultWeavingContext(classLoader);
- }
-
- createMessageHandler();
-
- this.generatedClassHandler =
- new SimpleGeneratedClassHandler(classLoader);
-
- List definitions = weavingContext.getDefinitions(classLoader,this);
- if (definitions.isEmpty()) {
- disable(); // TODO maw Needed to ensure messages are flushed
- if (trace.isTraceEnabled()) trace.exit("initialize",definitions);
- return;
- }
-
- bcelWorld = new LTWWorld(
- classLoader, weavingContext, // TODO when the world works in terms of the context, we can remove the loader...
- getMessageHandler(), null);
-
- weaver = new BcelWeaver(bcelWorld);
-
- // register the definitions
- success = registerDefinitions(weaver, classLoader, definitions);
- if (success) {
-
- // after adding aspects
- weaver.prepareForWeave();
-
- enable(); // TODO maw Needed to ensure messages are flushed
- success = weaveAndDefineConceteAspects();
- }
-
- if (success) {
- enable();
- }
- else {
- disable();
- bcelWorld = null;
- weaver = null;
- }
-
- initialized = true;
- if (trace.isTraceEnabled()) trace.exit("initialize",isEnabled());
- }
-
- /**
- * Load and cache the aop.xml/properties according to the classloader visibility rules
- *
- * @param weaver
- * @param loader
- */
- List parseDefinitions(final ClassLoader loader) {
- if (trace.isTraceEnabled()) trace.enter("parseDefinitions", this);
-
- List definitions = new ArrayList();
- try {
- info("register classloader " + getClassLoaderName(loader));
- //TODO av underoptimized: we will parse each XML once per CL that see it
-
- //TODO av dev mode needed ? TBD -Daj5.def=...
- if (loader.equals(ClassLoader.getSystemClassLoader())) {
- String file = System.getProperty("aj5.def", null);
- if (file != null) {
- info("using (-Daj5.def) " + file);
- definitions.add(DocumentParser.parse((new File(file)).toURL()));
- }
- }
-
- String resourcePath = System.getProperty("org.aspectj.weaver.loadtime.configuration",AOP_XML);
- if (trace.isTraceEnabled()) trace.event("parseDefinitions",this,resourcePath);
-
- StringTokenizer st = new StringTokenizer(resourcePath,";");
-
- while(st.hasMoreTokens()){
- String nextDefinition = st.nextToken();
- if (nextDefinition.startsWith("file:")) {
- try {
- String fpath = new URL(nextDefinition).getFile();
- File configFile = new File(fpath);
- if (!configFile.exists()) {
- warn("configuration does not exist: "+nextDefinition);
- } else {
- definitions.add(DocumentParser.parse(configFile.toURL()));
- }
- } catch (MalformedURLException mue) {
- error("malformed definition url: "+nextDefinition);
- }
- } else {
- Enumeration xmls = weavingContext.getResources(nextDefinition);
- // System.out.println("? registerDefinitions: found-aop.xml=" + xmls.hasMoreElements() + ", loader=" + loader);
-
- Set seenBefore = new HashSet();
- while (xmls.hasMoreElements()) {
- URL xml = (URL) xmls.nextElement();
- if (trace.isTraceEnabled()) trace.event("parseDefinitions",this,xml);
- if (!seenBefore.contains(xml)) {
- info("using configuration " + weavingContext.getFile(xml));
- definitions.add(DocumentParser.parse(xml));
- seenBefore.add(xml);
- }
- else {
- warn("ignoring duplicate definition: " + xml);
- }
- }
- }
- }
- if (definitions.isEmpty()) {
- info("no configuration found. Disabling weaver for class loader " + getClassLoaderName(loader));
- }
- } catch (Exception e) {
- definitions.clear();
- warn("parse definitions failed",e);
- }
-
- if (trace.isTraceEnabled()) trace.exit("parseDefinitions",definitions);
+
+ public ClassLoaderWeavingAdaptor() {
+ super();
+ if (trace.isTraceEnabled())
+ trace.enter("<init>", this);
+ if (trace.isTraceEnabled())
+ trace.exit("<init>");
+ }
+
+ /**
+ * We don't need a reference to the class loader and using it during construction can cause problems with recursion. It also
+ * makes sense to supply the weaving context during initialization to.
+ *
+ * @deprecated
+ */
+ public ClassLoaderWeavingAdaptor(final ClassLoader deprecatedLoader, final IWeavingContext deprecatedContext) {
+ super();
+ if (trace.isTraceEnabled())
+ trace.enter("<init>", this, new Object[] { deprecatedLoader, deprecatedContext });
+ if (trace.isTraceEnabled())
+ trace.exit("<init>");
+ }
+
+ class SimpleGeneratedClassHandler implements GeneratedClassHandler {
+ private WeakClassLoaderReference loaderRef;
+
+ SimpleGeneratedClassHandler(ClassLoader loader) {
+ loaderRef = new WeakClassLoaderReference(loader);
+ }
+
+ /**
+ * Callback when we need to define a Closure in the JVM
+ *
+ */
+ public void acceptClass(String name, byte[] bytes) {
+ try {
+ if (shouldDump(name.replace('/', '.'), false)) {
+ dump(name, bytes, false);
+ }
+ } catch (Throwable throwable) {
+ throwable.printStackTrace();
+ }
+
+ defineClass(loaderRef.getClassLoader(), name, bytes); // could be done lazily using the hook
+ }
+ }
+
+ protected void initialize(final ClassLoader classLoader, IWeavingContext context) {
+ if (initialized)
+ return;
+
+ boolean success = true;
+ // if (trace.isTraceEnabled()) trace.enter("initialize",this,new Object[] { classLoader, context });
+
+ this.weavingContext = context;
+ if (weavingContext == null) {
+ weavingContext = new DefaultWeavingContext(classLoader);
+ }
+
+ createMessageHandler();
+
+ this.generatedClassHandler = new SimpleGeneratedClassHandler(classLoader);
+
+ List definitions = weavingContext.getDefinitions(classLoader, this);
+ if (definitions.isEmpty()) {
+ disable(); // TODO maw Needed to ensure messages are flushed
+ if (trace.isTraceEnabled())
+ trace.exit("initialize", definitions);
+ return;
+ }
+
+ bcelWorld = new LTWWorld(classLoader, weavingContext, // TODO when the world works in terms of the context, we can remove
+ // the loader...
+ getMessageHandler(), null);
+
+ weaver = new BcelWeaver(bcelWorld);
+
+ // register the definitions
+ success = registerDefinitions(weaver, classLoader, definitions);
+ if (success) {
+
+ // after adding aspects
+ weaver.prepareForWeave();
+
+ enable(); // TODO maw Needed to ensure messages are flushed
+ success = weaveAndDefineConceteAspects();
+ }
+
+ if (success) {
+ enable();
+ } else {
+ disable();
+ bcelWorld = null;
+ weaver = null;
+ }
+
+ initialized = true;
+ if (trace.isTraceEnabled())
+ trace.exit("initialize", isEnabled());
+ }
+
+ /**
+ * Load and cache the aop.xml/properties according to the classloader visibility rules
+ *
+ * @param weaver
+ * @param loader
+ */
+ List parseDefinitions(final ClassLoader loader) {
+ if (trace.isTraceEnabled())
+ trace.enter("parseDefinitions", this);
+
+ List definitions = new ArrayList();
+ try {
+ info("register classloader " + getClassLoaderName(loader));
+ // TODO av underoptimized: we will parse each XML once per CL that see it
+
+ // TODO av dev mode needed ? TBD -Daj5.def=...
+ if (loader.equals(ClassLoader.getSystemClassLoader())) {
+ String file = System.getProperty("aj5.def", null);
+ if (file != null) {
+ info("using (-Daj5.def) " + file);
+ definitions.add(DocumentParser.parse((new File(file)).toURL()));
+ }
+ }
+
+ String resourcePath = System.getProperty("org.aspectj.weaver.loadtime.configuration", AOP_XML);
+ if (trace.isTraceEnabled())
+ trace.event("parseDefinitions", this, resourcePath);
+
+ StringTokenizer st = new StringTokenizer(resourcePath, ";");
+
+ while (st.hasMoreTokens()) {
+ String nextDefinition = st.nextToken();
+ if (nextDefinition.startsWith("file:")) {
+ try {
+ String fpath = new URL(nextDefinition).getFile();
+ File configFile = new File(fpath);
+ if (!configFile.exists()) {
+ warn("configuration does not exist: " + nextDefinition);
+ } else {
+ definitions.add(DocumentParser.parse(configFile.toURL()));
+ }
+ } catch (MalformedURLException mue) {
+ error("malformed definition url: " + nextDefinition);
+ }
+ } else {
+ Enumeration xmls = weavingContext.getResources(nextDefinition);
+ // System.out.println("? registerDefinitions: found-aop.xml=" + xmls.hasMoreElements() + ", loader=" + loader);
+
+ Set seenBefore = new HashSet();
+ while (xmls.hasMoreElements()) {
+ URL xml = (URL) xmls.nextElement();
+ if (trace.isTraceEnabled())
+ trace.event("parseDefinitions", this, xml);
+ if (!seenBefore.contains(xml)) {
+ info("using configuration " + weavingContext.getFile(xml));
+ definitions.add(DocumentParser.parse(xml));
+ seenBefore.add(xml);
+ } else {
+ warn("ignoring duplicate definition: " + xml);
+ }
+ }
+ }
+ }
+ if (definitions.isEmpty()) {
+ info("no configuration found. Disabling weaver for class loader " + getClassLoaderName(loader));
+ }
+ } catch (Exception e) {
+ definitions.clear();
+ warn("parse definitions failed", e);
+ }
+
+ if (trace.isTraceEnabled())
+ trace.exit("parseDefinitions", definitions);
return definitions;
- }
-
- private boolean registerDefinitions(final BcelWeaver weaver, final ClassLoader loader, List definitions) {
- if (trace.isTraceEnabled()) trace.enter("registerDefinitions",this,definitions);
- boolean success = true;
-
- try {
- registerOptions(weaver, loader, definitions);
- registerAspectExclude(weaver, loader, definitions);
- registerAspectInclude(weaver, loader, definitions);
- success = registerAspects(weaver, loader, definitions);
- registerIncludeExclude(weaver, loader, definitions);
- registerDump(weaver, loader, definitions);
- } catch (Exception ex) {
- trace.error("register definition failed",ex);
- success = false;
- warn("register definition failed",(ex instanceof AbortException)?null:ex);
- }
-
- if (trace.isTraceEnabled()) trace.exit("registerDefinitions",success);
- return success;
- }
-
- private String getClassLoaderName (ClassLoader loader) {
- return weavingContext.getClassLoaderName();
- }
-
- /**
- * Configure the weaver according to the option directives
- * TODO av - don't know if it is that good to reuse, since we only allow a small subset of options in LTW
- *
- * @param weaver
- * @param loader
- * @param definitions
- */
- private void registerOptions(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
- StringBuffer allOptions = new StringBuffer();
- for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
- Definition definition = (Definition) iterator.next();
- allOptions.append(definition.getWeaverOptions()).append(' ');
- }
-
- Options.WeaverOption weaverOption = Options.parse(allOptions.toString(), loader, getMessageHandler());
-
- // configure the weaver and world
- // AV - code duplicates AspectJBuilder.initWorldAndWeaver()
- World world = weaver.getWorld();
- setMessageHandler(weaverOption.messageHandler);
- world.setXlazyTjp(weaverOption.lazyTjp);
- world.setXHasMemberSupportEnabled(weaverOption.hasMember);
- world.setOptionalJoinpoints(weaverOption.optionalJoinpoints);
- world.setPinpointMode(weaverOption.pinpoint);
- weaver.setReweavableMode(weaverOption.notReWeavable);
- world.performExtraConfiguration(weaverOption.xSet);
- world.setXnoInline(weaverOption.noInline);
- // AMC - autodetect as per line below, needed for AtAjLTWTests.testLTWUnweavable
- world.setBehaveInJava5Way(LangUtil.is15VMOrGreater());
- world.setAddSerialVerUID(weaverOption.addSerialVersionUID);
-
- /* First load defaults */
+ }
+
+ private boolean registerDefinitions(final BcelWeaver weaver, final ClassLoader loader, List definitions) {
+ if (trace.isTraceEnabled())
+ trace.enter("registerDefinitions", this, definitions);
+ boolean success = true;
+
+ try {
+ registerOptions(weaver, loader, definitions);
+ registerAspectExclude(weaver, loader, definitions);
+ registerAspectInclude(weaver, loader, definitions);
+ success = registerAspects(weaver, loader, definitions);
+ registerIncludeExclude(weaver, loader, definitions);
+ registerDump(weaver, loader, definitions);
+ } catch (Exception ex) {
+ trace.error("register definition failed", ex);
+ success = false;
+ warn("register definition failed", (ex instanceof AbortException) ? null : ex);
+ }
+
+ if (trace.isTraceEnabled())
+ trace.exit("registerDefinitions", success);
+ return success;
+ }
+
+ private String getClassLoaderName(ClassLoader loader) {
+ return weavingContext.getClassLoaderName();
+ }
+
+ /**
+ * Configure the weaver according to the option directives TODO av - don't know if it is that good to reuse, since we only allow
+ * a small subset of options in LTW
+ *
+ * @param weaver
+ * @param loader
+ * @param definitions
+ */
+ private void registerOptions(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
+ StringBuffer allOptions = new StringBuffer();
+ for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
+ Definition definition = (Definition) iterator.next();
+ allOptions.append(definition.getWeaverOptions()).append(' ');
+ }
+
+ Options.WeaverOption weaverOption = Options.parse(allOptions.toString(), loader, getMessageHandler());
+
+ // configure the weaver and world
+ // AV - code duplicates AspectJBuilder.initWorldAndWeaver()
+ World world = weaver.getWorld();
+ setMessageHandler(weaverOption.messageHandler);
+ world.setXlazyTjp(weaverOption.lazyTjp);
+ world.setXHasMemberSupportEnabled(weaverOption.hasMember);
+ world.setOptionalJoinpoints(weaverOption.optionalJoinpoints);
+ world.setPinpointMode(weaverOption.pinpoint);
+ weaver.setReweavableMode(weaverOption.notReWeavable);
+ world.performExtraConfiguration(weaverOption.xSet);
+ world.setXnoInline(weaverOption.noInline);
+ // AMC - autodetect as per line below, needed for AtAjLTWTests.testLTWUnweavable
+ world.setBehaveInJava5Way(LangUtil.is15VMOrGreater());
+ world.setAddSerialVerUID(weaverOption.addSerialVersionUID);
+
+ /* First load defaults */
bcelWorld.getLint().loadDefaultProperties();
-
+
/* Second overlay LTW defaults */
bcelWorld.getLint().adviceDidNotMatch.setKind(null);
-
- /* Third load user file using -Xlintfile so that -Xlint wins */
- if (weaverOption.lintFile != null) {
- InputStream resource = null;
- try {
- resource = loader.getResourceAsStream(weaverOption.lintFile);
- Exception failure = null;
- if (resource != null) {
- try {
- Properties properties = new Properties();
- properties.load(resource);
- world.getLint().setFromProperties(properties);
- } catch (IOException e) {
- failure = e;
- }
- }
- if (failure != null || resource == null) {
- warn("Cannot access resource for -Xlintfile:"+weaverOption.lintFile,failure);
-// world.getMessageHandler().handleMessage(new Message(
-// "Cannot access resource for -Xlintfile:"+weaverOption.lintFile,
-// IMessage.WARNING,
-// failure,
-// null));
- }
- } finally {
- try { resource.close(); } catch (Throwable t) {;}
- }
- }
-
- /* Fourth override with -Xlint */
- if (weaverOption.lint != null) {
- if (weaverOption.lint.equals("default")) {//FIXME should be AjBuildConfig.AJLINT_DEFAULT but yetanother deps..
- bcelWorld.getLint().loadDefaultProperties();
- } else {
- bcelWorld.getLint().setAll(weaverOption.lint);
- }
- }
- //TODO proceedOnError option
- }
-
- private void registerAspectExclude(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
- String fastMatchInfo = null;
- for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
- Definition definition = (Definition) iterator.next();
- for (Iterator iterator1 = definition.getAspectExcludePatterns().iterator(); iterator1.hasNext();) {
- String exclude = (String) iterator1.next();
- TypePattern excludePattern = new PatternParser(exclude).parseTypePattern();
- m_aspectExcludeTypePattern.add(excludePattern);
- fastMatchInfo = looksLikeStartsWith(exclude);
- if (fastMatchInfo != null) {
- m_aspectExcludeStartsWith.add(fastMatchInfo);
- }
- }
- }
- }
-
- private void registerAspectInclude(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
- String fastMatchInfo = null;
- for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
- Definition definition = (Definition) iterator.next();
- for (Iterator iterator1 = definition.getAspectIncludePatterns().iterator(); iterator1.hasNext();) {
- String include = (String) iterator1.next();
- TypePattern includePattern = new PatternParser(include).parseTypePattern();
- m_aspectIncludeTypePattern.add(includePattern);
- fastMatchInfo = looksLikeStartsWith(include);
- if (fastMatchInfo != null) {
- m_aspectIncludeStartsWith.add(fastMatchInfo);
- }
- }
- }
- }
-
- protected void lint (String name, String[] infos) {
- Lint lint = bcelWorld.getLint();
- Kind kind = lint.getLintKind(name);
- kind.signal(infos,null,null);
- }
-
- public String getContextId () {
+
+ /* Third load user file using -Xlintfile so that -Xlint wins */
+ if (weaverOption.lintFile != null) {
+ InputStream resource = null;
+ try {
+ resource = loader.getResourceAsStream(weaverOption.lintFile);
+ Exception failure = null;
+ if (resource != null) {
+ try {
+ Properties properties = new Properties();
+ properties.load(resource);
+ world.getLint().setFromProperties(properties);
+ } catch (IOException e) {
+ failure = e;
+ }
+ }
+ if (failure != null || resource == null) {
+ warn("Cannot access resource for -Xlintfile:" + weaverOption.lintFile, failure);
+ // world.getMessageHandler().handleMessage(new Message(
+ // "Cannot access resource for -Xlintfile:"+weaverOption.lintFile,
+ // IMessage.WARNING,
+ // failure,
+ // null));
+ }
+ } finally {
+ try {
+ resource.close();
+ } catch (Throwable t) {
+ }
+ }
+ }
+
+ /* Fourth override with -Xlint */
+ if (weaverOption.lint != null) {
+ if (weaverOption.lint.equals("default")) {// FIXME should be AjBuildConfig.AJLINT_DEFAULT but yetanother deps..
+ bcelWorld.getLint().loadDefaultProperties();
+ } else {
+ bcelWorld.getLint().setAll(weaverOption.lint);
+ }
+ }
+ // TODO proceedOnError option
+ }
+
+ private void registerAspectExclude(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
+ String fastMatchInfo = null;
+ for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
+ Definition definition = (Definition) iterator.next();
+ for (Iterator iterator1 = definition.getAspectExcludePatterns().iterator(); iterator1.hasNext();) {
+ String exclude = (String) iterator1.next();
+ TypePattern excludePattern = new PatternParser(exclude).parseTypePattern();
+ m_aspectExcludeTypePattern.add(excludePattern);
+ fastMatchInfo = looksLikeStartsWith(exclude);
+ if (fastMatchInfo != null) {
+ m_aspectExcludeStartsWith.add(fastMatchInfo);
+ }
+ }
+ }
+ }
+
+ private void registerAspectInclude(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
+ String fastMatchInfo = null;
+ for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
+ Definition definition = (Definition) iterator.next();
+ for (Iterator iterator1 = definition.getAspectIncludePatterns().iterator(); iterator1.hasNext();) {
+ String include = (String) iterator1.next();
+ TypePattern includePattern = new PatternParser(include).parseTypePattern();
+ m_aspectIncludeTypePattern.add(includePattern);
+ fastMatchInfo = looksLikeStartsWith(include);
+ if (fastMatchInfo != null) {
+ m_aspectIncludeStartsWith.add(fastMatchInfo);
+ }
+ }
+ }
+ }
+
+ protected void lint(String name, String[] infos) {
+ Lint lint = bcelWorld.getLint();
+ Kind kind = lint.getLintKind(name);
+ kind.signal(infos, null, null);
+ }
+
+ public String getContextId() {
return weavingContext.getId();
}
-
- /**
- * Register the aspect, following include / exclude rules
- *
- * @param weaver
- * @param loader
- * @param definitions
- */
- private boolean registerAspects(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
- if (trace.isTraceEnabled()) trace.enter("registerAspects",this, new Object[] { weaver, loader, definitions} );
- boolean success = true;
-
- //TODO: the exclude aspect allow to exclude aspect defined upper in the CL hierarchy - is it what we want ??
- // if not, review the getResource so that we track which resource is defined by which CL
-
- //iterate aspectClassNames
- //exclude if in any of the exclude list
- for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
- Definition definition = (Definition) iterator.next();
- for (Iterator aspects = definition.getAspectClassNames().iterator(); aspects.hasNext();) {
- String aspectClassName = (String) aspects.next();
- if (acceptAspect(aspectClassName)) {
- info("register aspect " + aspectClassName);
-// System.err.println("? ClassLoaderWeavingAdaptor.registerAspects() aspectName=" + aspectClassName + ", loader=" + loader + ", bundle=" + weavingContext.getClassLoaderName());
- /*ResolvedType aspect = */weaver.addLibraryAspect(aspectClassName);
-
- //generate key for SC
- if(namespace==null){
- namespace=new StringBuffer(aspectClassName);
- }else{
- namespace = namespace.append(";"+aspectClassName);
- }
- }
- else {
-// warn("aspect excluded: " + aspectClassName);
- lint("aspectExcludedByConfiguration", new String[] { aspectClassName, getClassLoaderName(loader) });
- }
- }
- }
-
- //iterate concreteAspects
- //exclude if in any of the exclude list - note that the user defined name matters for that to happen
- for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
- Definition definition = (Definition) iterator.next();
- for (Iterator aspects = definition.getConcreteAspects().iterator(); aspects.hasNext();) {
- Definition.ConcreteAspect concreteAspect = (Definition.ConcreteAspect) aspects.next();
- if (acceptAspect(concreteAspect.name)) {
- info("define aspect " + concreteAspect.name);
- ConcreteAspectCodeGen gen = new ConcreteAspectCodeGen(concreteAspect, weaver.getWorld());
- if (!gen.validate()) {
- error("Concrete-aspect '"+concreteAspect.name+"' could not be registered");
- success = false;
- break;
- }
-
- ((BcelWorld)weaver.getWorld()).addSourceObjectType(Utility.makeJavaClass(concreteAspect.name, gen.getBytes()));
-
- concreteAspects.add(gen);
-
- weaver.addLibraryAspect(concreteAspect.name);
-
- //generate key for SC
- if(namespace==null){
- namespace=new StringBuffer(concreteAspect.name);
- }else{
- namespace = namespace.append(";"+concreteAspect.name);
- }
- }
- }
- }
-
- /* We couldn't register one or more aspects so disable the adaptor */
- if (!success) {
- warn("failure(s) registering aspects. Disabling weaver for class loader " + getClassLoaderName(loader));
- }
-
- /* We didn't register any aspects so disable the adaptor */
- else if (namespace == null) {
- success = false;
- info("no aspects registered. Disabling weaver for class loader " + getClassLoaderName(loader));
- }
-
- if (trace.isTraceEnabled()) trace.exit("registerAspects",success);
- return success;
- }
-
- private boolean weaveAndDefineConceteAspects () {
- if (trace.isTraceEnabled()) trace.enter("weaveAndDefineConceteAspects",this,concreteAspects);
- boolean success = true;
-
- for (Iterator iterator = concreteAspects.iterator(); iterator.hasNext();) {
- ConcreteAspectCodeGen gen = (ConcreteAspectCodeGen)iterator.next();
- String name = gen.getClassName();
- byte[] bytes = gen.getBytes();
-
- try {
- byte[] newBytes = weaveClass(name, bytes,true);
- this.generatedClassHandler.acceptClass(name,newBytes);
- }
- catch (IOException ex) {
- trace.error("weaveAndDefineConceteAspects",ex);
- error("exception weaving aspect '" + name + "'",ex);
- }
- }
-
- if (trace.isTraceEnabled()) trace.exit("weaveAndDefineConceteAspects",success);
- return success;
- }
-
- /**
- * Register the include / exclude filters
- * We duplicate simple patterns in startWith filters that will allow faster matching without ResolvedType
- *
- * @param weaver
- * @param loader
- * @param definitions
- */
- private void registerIncludeExclude(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
- String fastMatchInfo = null;
- for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
- Definition definition = (Definition) iterator.next();
- for (Iterator iterator1 = definition.getIncludePatterns().iterator(); iterator1.hasNext();) {
- String include = (String) iterator1.next();
- TypePattern includePattern = new PatternParser(include).parseTypePattern();
- m_includeTypePattern.add(includePattern);
- fastMatchInfo = looksLikeStartsWith(include);
- if (fastMatchInfo != null) {
- m_includeStartsWith.add(fastMatchInfo);
- }
- }
- for (Iterator iterator1 = definition.getExcludePatterns().iterator(); iterator1.hasNext();) {
- String exclude = (String) iterator1.next();
- TypePattern excludePattern = new PatternParser(exclude).parseTypePattern();
- m_excludeTypePattern.add(excludePattern);
- fastMatchInfo = looksLikeStartsWith(exclude);
- if (fastMatchInfo != null) {
- m_excludeStartsWith.add(fastMatchInfo);
- }
- }
- }
- }
-
- /**
- * Checks if the type pattern can be handled as a startswith check
- *
- * TODO AV - enhance to support "char.sss" ie FQN direclty (match iff equals)
- * we could also add support for "*..*charss" endsWith style?
- *
- * @param typePattern
- * @return null if not possible, or the startWith sequence to test against
- */
- private String looksLikeStartsWith(String typePattern) {
- if (typePattern.indexOf('@') >= 0
- || typePattern.indexOf('+') >= 0
- || typePattern.indexOf(' ') >= 0
- || typePattern.charAt(typePattern.length()-1) != '*') {
- return null;
- }
- // now must looks like with "charsss..*" or "cha.rss..*" etc
- // note that "*" and "*..*" won't be fast matched
- // and that "charsss.*" will not neither
- int length = typePattern.length();
- if (typePattern.endsWith("..*") && length > 3) {
- if (typePattern.indexOf("..") == length-3 // no ".." before last sequence
- && typePattern.indexOf('*') == length-1) { // no "*" before last sequence
- return typePattern.substring(0, length-2).replace('$', '.');
- // ie "charsss." or "char.rss." etc
- }
- }
- return null;
- }
-
- /**
- * Register the dump filter
- *
- * @param weaver
- * @param loader
- * @param definitions
- */
- private void registerDump(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
- for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
- Definition definition = (Definition) iterator.next();
- for (Iterator iterator1 = definition.getDumpPatterns().iterator(); iterator1.hasNext();) {
- String dump = (String) iterator1.next();
- TypePattern pattern = new PatternParser(dump).parseTypePattern();
- m_dumpTypePattern.add(pattern);
- }
- if (definition.shouldDumpBefore()) {
- m_dumpBefore = true;
- }
- }
- }
-
- protected boolean accept(String className, byte[] bytes) {
- // avoid ResolvedType if not needed
- if (m_excludeTypePattern.isEmpty() && m_includeTypePattern.isEmpty()) {
- return true;
- }
-
- // still try to avoid ResolvedType if we have simple patterns
- String fastClassName = className.replace('/', '.').replace('$', '.');
- for (int i = 0; i < m_excludeStartsWith.size(); i++) {
- if (fastClassName.startsWith((String)m_excludeStartsWith.get(i))) {
- return false;
- }
- }
-
- /*
- * Bug 120363
- * If we have an exclude pattern that cannot be matched using "starts with"
- * then we cannot fast accept
- */
- if (m_excludeTypePattern.isEmpty()) {
- boolean fastAccept = false;//defaults to false if no fast include
- for (int i = 0; i < m_includeStartsWith.size(); i++) {
- fastAccept = fastClassName.startsWith((String)m_includeStartsWith.get(i));
- if (fastAccept) {
- break;
- }
- }
- }
-
- // needs further analysis
- // TODO AV - needs refactoring
- // during LTW this calling resolve at that stage is BAD as we do have the bytecode from the classloader hook
- // but still go thru resolve that will do a getResourcesAsStream on disk
- // this is also problematic for jit stub which are not on disk - as often underlying infra
- // does returns null or some other info for getResourceAsStream (f.e. WLS 9 CR248491)
- // Instead I parse the given bytecode. But this also means it will be parsed again in
- // new WeavingClassFileProvider() from WeavingAdaptor.getWovenBytes()...
-
- ensureDelegateInitialized(className,bytes);
- ResolvedType classInfo = delegateForCurrentClass.getResolvedTypeX();//BAD: weaver.getWorld().resolve(UnresolvedType.forName(className), true);
-
- //exclude are "AND"ed
- for (Iterator iterator = m_excludeTypePattern.iterator(); iterator.hasNext();) {
- TypePattern typePattern = (TypePattern) iterator.next();
- if (typePattern.matchesStatically(classInfo)) {
- // exclude match - skip
- return false;
- }
- }
- //include are "OR"ed
- boolean accept = true;//defaults to true if no include
- for (Iterator iterator = m_includeTypePattern.iterator(); iterator.hasNext();) {
- TypePattern typePattern = (TypePattern) iterator.next();
- accept = typePattern.matchesStatically(classInfo);
- if (accept) {
- break;
- }
- // goes on if this include did not match ("OR"ed)
- }
- return accept;
- }
-
-
- //FIXME we don't use include/exclude of others aop.xml
- //this can be nice but very dangerous as well to change that
- private boolean acceptAspect(String aspectClassName) {
- // avoid ResolvedType if not needed
- if (m_aspectExcludeTypePattern.isEmpty() && m_aspectIncludeTypePattern.isEmpty()) {
- return true;
- }
-
- // still try to avoid ResolvedType if we have simple patterns
- // EXCLUDE: if one match then reject
- String fastClassName = aspectClassName.replace('/', '.').replace('.', '$');
- for (int i = 0; i < m_aspectExcludeStartsWith.size(); i++) {
- if (fastClassName.startsWith((String)m_aspectExcludeStartsWith.get(i))) {
- return false;
- }
- }
- //INCLUDE: if one match then accept
- for (int i = 0; i < m_aspectIncludeStartsWith.size(); i++) {
- if (fastClassName.startsWith((String)m_aspectIncludeStartsWith.get(i))) {
- return true;
- }
- }
-
- // needs further analysis
- ResolvedType classInfo = weaver.getWorld().resolve(UnresolvedType.forName(aspectClassName), true);
- //exclude are "AND"ed
- for (Iterator iterator = m_aspectExcludeTypePattern.iterator(); iterator.hasNext();) {
- TypePattern typePattern = (TypePattern) iterator.next();
- if (typePattern.matchesStatically(classInfo)) {
- // exclude match - skip
- return false;
- }
- }
- //include are "OR"ed
- boolean accept = true;//defaults to true if no include
- for (Iterator iterator = m_aspectIncludeTypePattern.iterator(); iterator.hasNext();) {
- TypePattern typePattern = (TypePattern) iterator.next();
- accept = typePattern.matchesStatically(classInfo);
- if (accept) {
- break;
- }
- // goes on if this include did not match ("OR"ed)
- }
- return accept;
- }
-
- protected boolean shouldDump(String className, boolean before) {
- // Don't dump before weaving unless asked to
- if (before && !m_dumpBefore) {
- return false;
- }
-
- // avoid ResolvedType if not needed
- if (m_dumpTypePattern.isEmpty()) {
- return false;
- }
-
- //TODO AV - optimize for className.startWith only
- ResolvedType classInfo = weaver.getWorld().resolve(UnresolvedType.forName(className), true);
- //dump
- for (Iterator iterator = m_dumpTypePattern.iterator(); iterator.hasNext();) {
- TypePattern typePattern = (TypePattern) iterator.next();
- if (typePattern.matchesStatically(classInfo)) {
- // dump match
- return true;
- }
- }
- return false;
- }
-
- /*
- * shared classes methods
- */
-
- /**
+
+ /**
+ * Register the aspect, following include / exclude rules
+ *
+ * @param weaver
+ * @param loader
+ * @param definitions
+ */
+ private boolean registerAspects(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
+ if (trace.isTraceEnabled())
+ trace.enter("registerAspects", this, new Object[] { weaver, loader, definitions });
+ boolean success = true;
+
+ // TODO: the exclude aspect allow to exclude aspect defined upper in the CL hierarchy - is it what we want ??
+ // if not, review the getResource so that we track which resource is defined by which CL
+
+ // iterate aspectClassNames
+ // exclude if in any of the exclude list
+ for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
+ Definition definition = (Definition) iterator.next();
+ for (Iterator aspects = definition.getAspectClassNames().iterator(); aspects.hasNext();) {
+ String aspectClassName = (String) aspects.next();
+ if (acceptAspect(aspectClassName)) {
+ info("register aspect " + aspectClassName);
+ // System.err.println("? ClassLoaderWeavingAdaptor.registerAspects() aspectName=" + aspectClassName +
+ // ", loader=" + loader + ", bundle=" + weavingContext.getClassLoaderName());
+ /* ResolvedType aspect = */weaver.addLibraryAspect(aspectClassName);
+
+ // generate key for SC
+ if (namespace == null) {
+ namespace = new StringBuffer(aspectClassName);
+ } else {
+ namespace = namespace.append(";" + aspectClassName);
+ }
+ } else {
+ // warn("aspect excluded: " + aspectClassName);
+ lint("aspectExcludedByConfiguration", new String[] { aspectClassName, getClassLoaderName(loader) });
+ }
+ }
+ }
+
+ // iterate concreteAspects
+ // exclude if in any of the exclude list - note that the user defined name matters for that to happen
+ for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
+ Definition definition = (Definition) iterator.next();
+ for (Iterator aspects = definition.getConcreteAspects().iterator(); aspects.hasNext();) {
+ Definition.ConcreteAspect concreteAspect = (Definition.ConcreteAspect) aspects.next();
+ if (acceptAspect(concreteAspect.name)) {
+ info("define aspect " + concreteAspect.name);
+ ConcreteAspectCodeGen gen = new ConcreteAspectCodeGen(concreteAspect, weaver.getWorld());
+ if (!gen.validate()) {
+ error("Concrete-aspect '" + concreteAspect.name + "' could not be registered");
+ success = false;
+ break;
+ }
+
+ ((BcelWorld) weaver.getWorld()).addSourceObjectType(Utility.makeJavaClass(concreteAspect.name, gen.getBytes()));
+
+ concreteAspects.add(gen);
+
+ weaver.addLibraryAspect(concreteAspect.name);
+
+ // generate key for SC
+ if (namespace == null) {
+ namespace = new StringBuffer(concreteAspect.name);
+ } else {
+ namespace = namespace.append(";" + concreteAspect.name);
+ }
+ }
+ }
+ }
+
+ /* We couldn't register one or more aspects so disable the adaptor */
+ if (!success) {
+ warn("failure(s) registering aspects. Disabling weaver for class loader " + getClassLoaderName(loader));
+ }
+
+ /* We didn't register any aspects so disable the adaptor */
+ else if (namespace == null) {
+ success = false;
+ info("no aspects registered. Disabling weaver for class loader " + getClassLoaderName(loader));
+ }
+
+ if (trace.isTraceEnabled())
+ trace.exit("registerAspects", success);
+ return success;
+ }
+
+ private boolean weaveAndDefineConceteAspects() {
+ if (trace.isTraceEnabled())
+ trace.enter("weaveAndDefineConceteAspects", this, concreteAspects);
+ boolean success = true;
+
+ for (Iterator iterator = concreteAspects.iterator(); iterator.hasNext();) {
+ ConcreteAspectCodeGen gen = (ConcreteAspectCodeGen) iterator.next();
+ String name = gen.getClassName();
+ byte[] bytes = gen.getBytes();
+
+ try {
+ byte[] newBytes = weaveClass(name, bytes, true);
+ this.generatedClassHandler.acceptClass(name, newBytes);
+ } catch (IOException ex) {
+ trace.error("weaveAndDefineConceteAspects", ex);
+ error("exception weaving aspect '" + name + "'", ex);
+ }
+ }
+
+ if (trace.isTraceEnabled())
+ trace.exit("weaveAndDefineConceteAspects", success);
+ return success;
+ }
+
+ /**
+ * Register the include / exclude filters We duplicate simple patterns in startWith filters that will allow faster matching
+ * without ResolvedType
+ *
+ * @param weaver
+ * @param loader
+ * @param definitions
+ */
+ private void registerIncludeExclude(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
+ String fastMatchInfo = null;
+ for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
+ Definition definition = (Definition) iterator.next();
+ for (Iterator iterator1 = definition.getIncludePatterns().iterator(); iterator1.hasNext();) {
+ String include = (String) iterator1.next();
+ TypePattern includePattern = new PatternParser(include).parseTypePattern();
+ m_includeTypePattern.add(includePattern);
+ fastMatchInfo = looksLikeStartsWith(include);
+ if (fastMatchInfo != null) {
+ m_includeStartsWith.add(fastMatchInfo);
+ }
+ }
+ for (Iterator iterator1 = definition.getExcludePatterns().iterator(); iterator1.hasNext();) {
+ String exclude = (String) iterator1.next();
+ TypePattern excludePattern = new PatternParser(exclude).parseTypePattern();
+ m_excludeTypePattern.add(excludePattern);
+ fastMatchInfo = looksLikeStartsWith(exclude);
+ if (fastMatchInfo != null) {
+ m_excludeStartsWith.add(fastMatchInfo);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks if the type pattern can be handled as a startswith check
+ *
+ * TODO AV - enhance to support "char.sss" ie FQN direclty (match iff equals) we could also add support for "*..*charss"
+ * endsWith style?
+ *
+ * @param typePattern
+ * @return null if not possible, or the startWith sequence to test against
+ */
+ private String looksLikeStartsWith(String typePattern) {
+ if (typePattern.indexOf('@') >= 0 || typePattern.indexOf('+') >= 0 || typePattern.indexOf(' ') >= 0
+ || typePattern.charAt(typePattern.length() - 1) != '*') {
+ return null;
+ }
+ // now must looks like with "charsss..*" or "cha.rss..*" etc
+ // note that "*" and "*..*" won't be fast matched
+ // and that "charsss.*" will not neither
+ int length = typePattern.length();
+ if (typePattern.endsWith("..*") && length > 3) {
+ if (typePattern.indexOf("..") == length - 3 // no ".." before last sequence
+ && typePattern.indexOf('*') == length - 1) { // no "*" before last sequence
+ return typePattern.substring(0, length - 2).replace('$', '.');
+ // ie "charsss." or "char.rss." etc
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Register the dump filter
+ *
+ * @param weaver
+ * @param loader
+ * @param definitions
+ */
+ private void registerDump(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
+ for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
+ Definition definition = (Definition) iterator.next();
+ for (Iterator iterator1 = definition.getDumpPatterns().iterator(); iterator1.hasNext();) {
+ String dump = (String) iterator1.next();
+ TypePattern pattern = new PatternParser(dump).parseTypePattern();
+ m_dumpTypePattern.add(pattern);
+ }
+ if (definition.shouldDumpBefore()) {
+ m_dumpBefore = true;
+ }
+ }
+ }
+
+ protected boolean accept(String className, byte[] bytes) {
+ // avoid ResolvedType if not needed
+ if (m_excludeTypePattern.isEmpty() && m_includeTypePattern.isEmpty()) {
+ return true;
+ }
+
+ // still try to avoid ResolvedType if we have simple patterns
+ String fastClassName = className.replace('/', '.').replace('$', '.');
+ for (int i = 0; i < m_excludeStartsWith.size(); i++) {
+ if (fastClassName.startsWith((String) m_excludeStartsWith.get(i))) {
+ return false;
+ }
+ }
+
+ /*
+ * Bug 120363 If we have an exclude pattern that cannot be matched using "starts with" then we cannot fast accept
+ */
+ if (m_excludeTypePattern.isEmpty()) {
+ boolean fastAccept = false;// defaults to false if no fast include
+ for (int i = 0; i < m_includeStartsWith.size(); i++) {
+ fastAccept = fastClassName.startsWith((String) m_includeStartsWith.get(i));
+ if (fastAccept) {
+ break;
+ }
+ }
+ }
+
+ // needs further analysis
+ // TODO AV - needs refactoring
+ // during LTW this calling resolve at that stage is BAD as we do have the bytecode from the classloader hook
+ // but still go thru resolve that will do a getResourcesAsStream on disk
+ // this is also problematic for jit stub which are not on disk - as often underlying infra
+ // does returns null or some other info for getResourceAsStream (f.e. WLS 9 CR248491)
+ // Instead I parse the given bytecode. But this also means it will be parsed again in
+ // new WeavingClassFileProvider() from WeavingAdaptor.getWovenBytes()...
+
+ ensureDelegateInitialized(className, bytes);
+ ResolvedType classInfo = delegateForCurrentClass.getResolvedTypeX();// BAD:
+ // weaver.getWorld().resolve(UnresolvedType.forName(
+ // className), true);
+
+ // exclude are "AND"ed
+ for (Iterator iterator = m_excludeTypePattern.iterator(); iterator.hasNext();) {
+ TypePattern typePattern = (TypePattern) iterator.next();
+ if (typePattern.matchesStatically(classInfo)) {
+ // exclude match - skip
+ return false;
+ }
+ }
+ // include are "OR"ed
+ boolean accept = true;// defaults to true if no include
+ for (Iterator iterator = m_includeTypePattern.iterator(); iterator.hasNext();) {
+ TypePattern typePattern = (TypePattern) iterator.next();
+ accept = typePattern.matchesStatically(classInfo);
+ if (accept) {
+ break;
+ }
+ // goes on if this include did not match ("OR"ed)
+ }
+ return accept;
+ }
+
+ // FIXME we don't use include/exclude of others aop.xml
+ // this can be nice but very dangerous as well to change that
+ private boolean acceptAspect(String aspectClassName) {
+ // avoid ResolvedType if not needed
+ if (m_aspectExcludeTypePattern.isEmpty() && m_aspectIncludeTypePattern.isEmpty()) {
+ return true;
+ }
+
+ // still try to avoid ResolvedType if we have simple patterns
+ // EXCLUDE: if one match then reject
+ String fastClassName = aspectClassName.replace('/', '.').replace('.', '$');
+ for (int i = 0; i < m_aspectExcludeStartsWith.size(); i++) {
+ if (fastClassName.startsWith((String) m_aspectExcludeStartsWith.get(i))) {
+ return false;
+ }
+ }
+ // INCLUDE: if one match then accept
+ for (int i = 0; i < m_aspectIncludeStartsWith.size(); i++) {
+ if (fastClassName.startsWith((String) m_aspectIncludeStartsWith.get(i))) {
+ return true;
+ }
+ }
+
+ // needs further analysis
+ ResolvedType classInfo = weaver.getWorld().resolve(UnresolvedType.forName(aspectClassName), true);
+ // exclude are "AND"ed
+ for (Iterator iterator = m_aspectExcludeTypePattern.iterator(); iterator.hasNext();) {
+ TypePattern typePattern = (TypePattern) iterator.next();
+ if (typePattern.matchesStatically(classInfo)) {
+ // exclude match - skip
+ return false;
+ }
+ }
+ // include are "OR"ed
+ boolean accept = true;// defaults to true if no include
+ for (Iterator iterator = m_aspectIncludeTypePattern.iterator(); iterator.hasNext();) {
+ TypePattern typePattern = (TypePattern) iterator.next();
+ accept = typePattern.matchesStatically(classInfo);
+ if (accept) {
+ break;
+ }
+ // goes on if this include did not match ("OR"ed)
+ }
+ return accept;
+ }
+
+ protected boolean shouldDump(String className, boolean before) {
+ // Don't dump before weaving unless asked to
+ if (before && !m_dumpBefore) {
+ return false;
+ }
+
+ // avoid ResolvedType if not needed
+ if (m_dumpTypePattern.isEmpty()) {
+ return false;
+ }
+
+ // TODO AV - optimize for className.startWith only
+ ResolvedType classInfo = weaver.getWorld().resolve(UnresolvedType.forName(className), true);
+ // dump
+ for (Iterator iterator = m_dumpTypePattern.iterator(); iterator.hasNext();) {
+ TypePattern typePattern = (TypePattern) iterator.next();
+ if (typePattern.matchesStatically(classInfo)) {
+ // dump match
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /*
+ * shared classes methods
+ */
+
+ /**
* @return Returns the key.
*/
public String getNamespace() {
-// System.out.println("ClassLoaderWeavingAdaptor.getNamespace() classloader=" + weavingContext.getClassLoaderName() + ", namespace=" + namespace);
- if(namespace==null) return "";
- else return new String(namespace);
+ // System.out.println("ClassLoaderWeavingAdaptor.getNamespace() classloader=" + weavingContext.getClassLoaderName() +
+ // ", namespace=" + namespace);
+ if (namespace == null)
+ return "";
+ else
+ return new String(namespace);
}
- /**
- * Check to see if any classes are stored in the generated classes cache.
- * Then flush the cache if it is not empty
- * @param className TODO
- * @return true if a class has been generated and is stored in the cache
- */
- public boolean generatedClassesExistFor (String className) {
-// System.err.println("? ClassLoaderWeavingAdaptor.generatedClassesExist() classname=" + className + ", size=" + generatedClasses);
- if (className == null) return !generatedClasses.isEmpty();
- else return generatedClasses.containsKey(className);
- }
-
- /**
- * Flush the generated classes cache
- */
- public void flushGeneratedClasses() {
-// System.err.println("? ClassLoaderWeavingAdaptor.flushGeneratedClasses() generatedClasses=" + generatedClasses);
- generatedClasses = new HashMap();
- }
+ /**
+ * Check to see if any classes are stored in the generated classes cache. Then flush the cache if it is not empty
+ *
+ * @param className TODO
+ * @return true if a class has been generated and is stored in the cache
+ */
+ public boolean generatedClassesExistFor(String className) {
+ // System.err.println("? ClassLoaderWeavingAdaptor.generatedClassesExist() classname=" + className + ", size=" +
+ // generatedClasses);
+ if (className == null)
+ return !generatedClasses.isEmpty();
+ else
+ return generatedClasses.containsKey(className);
+ }
+
+ /**
+ * Flush the generated classes cache
+ */
+ public void flushGeneratedClasses() {
+ // System.err.println("? ClassLoaderWeavingAdaptor.flushGeneratedClasses() generatedClasses=" + generatedClasses);
+ generatedClasses = new HashMap();
+ }
private void defineClass(ClassLoader loader, String name, byte[] bytes) {
- if (trace.isTraceEnabled()) trace.enter("defineClass",this,new Object[] {loader,name,bytes});
- Object clazz = null;
+ if (trace.isTraceEnabled())
+ trace.enter("defineClass", this, new Object[] { loader, name, bytes });
+ Object clazz = null;
debug("generating class '" + name + "'");
-
+
try {
- //TODO av protection domain, and optimize
- Method defineClass = ClassLoader.class.getDeclaredMethod(
- "defineClass", new Class[] { String.class,
- bytes.getClass(), int.class, int.class });
+ // TODO av protection domain, and optimize
+ Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", new Class[] { String.class, bytes.getClass(),
+ int.class, int.class });
defineClass.setAccessible(true);
- clazz = defineClass.invoke(loader, new Object[] { name, bytes,
- new Integer(0), new Integer(bytes.length) });
+ clazz = defineClass.invoke(loader, new Object[] { name, bytes, new Integer(0), new Integer(bytes.length) });
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof LinkageError) {
- warn("define generated class failed",e.getTargetException());
- //is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved)
+ warn("define generated class failed", e.getTargetException());
+ // is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved)
// TODO maw I don't think this is OK and
} else {
- warn("define generated class failed",e.getTargetException());
+ warn("define generated class failed", e.getTargetException());
}
} catch (Exception e) {
- warn("define generated class failed",e);
+ warn("define generated class failed", e);
}
- if (trace.isTraceEnabled()) trace.exit("defineClass",clazz);
+ if (trace.isTraceEnabled())
+ trace.exit("defineClass", clazz);
}
}
\ No newline at end of file
*******************************************************************************/
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;
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));
+ }
}
*******************************************************************************/
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;
+ }
+ }
}
/**
* 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;
try {
xmlReader = XMLReaderFactory.createXMLReader();
}
-
+
/* .. and ignore "System property ... not set" and then try this instead */
catch (SAXException ex) {
xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
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"));
+ }
}
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() {
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() {
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);
}
}
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 {
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 {
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());
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;