From 03b20bc1129e03d5e8594262b89021e54ab017f9 Mon Sep 17 00:00:00 2001 From: acolyer Date: Fri, 23 Sep 2005 14:40:27 +0000 Subject: [PATCH] David Knibb's patch for enh 109173 :- Weaving Adaptor enhancements --- .../src/org/aspectj/weaver/loadtime/Aj.java | 43 +++++++- .../loadtime/ClassLoaderWeavingAdaptor.java | 101 ++++++++++++++++-- .../loadtime/DefaultWeavingContext.java | 54 ++++++++++ .../weaver/loadtime/IWeavingContext.java | 45 ++++++++ 4 files changed, 233 insertions(+), 10 deletions(-) create mode 100644 loadtime/src/org/aspectj/weaver/loadtime/DefaultWeavingContext.java create mode 100644 loadtime/src/org/aspectj/weaver/loadtime/IWeavingContext.java diff --git a/loadtime/src/org/aspectj/weaver/loadtime/Aj.java b/loadtime/src/org/aspectj/weaver/loadtime/Aj.java index 1c03f1496..c340a2862 100644 --- a/loadtime/src/org/aspectj/weaver/loadtime/Aj.java +++ b/loadtime/src/org/aspectj/weaver/loadtime/Aj.java @@ -28,6 +28,17 @@ import org.aspectj.weaver.tools.WeavingAdaptor; */ public class Aj implements ClassPreProcessor { + private IWeavingContext weavingContext; + + public Aj(){ + this(null); + } + + + public Aj(IWeavingContext context){ + weavingContext = context; + } + /** * Initialization */ @@ -51,7 +62,7 @@ public class Aj implements ClassPreProcessor { } try { - WeavingAdaptor weavingAdaptor = WeaverContainer.getWeaver(loader); + WeavingAdaptor weavingAdaptor = WeaverContainer.getWeaver(loader, weavingContext); byte[] weaved = weavingAdaptor.weaveClass(className, bytes); if (weavingAdaptor.shouldDump(className.replace('/', '.'))) { dump(className, weaved); @@ -73,12 +84,12 @@ public class Aj implements ClassPreProcessor { private static Map weavingAdaptors = new WeakHashMap(); - static WeavingAdaptor getWeaver(ClassLoader loader) { + static WeavingAdaptor getWeaver(ClassLoader loader, IWeavingContext weavingContext) { synchronized(loader) {//FIXME AV - temp fix for #99861 synchronized (weavingAdaptors) { WeavingAdaptor weavingAdaptor = (WeavingAdaptor) weavingAdaptors.get(loader); if (weavingAdaptor == null) { - weavingAdaptor = new ClassLoaderWeavingAdaptor(loader); + weavingAdaptor = new ClassLoaderWeavingAdaptor(loader, weavingContext); weavingAdaptors.put(loader, weavingAdaptor); } return weavingAdaptor; @@ -136,5 +147,31 @@ public class Aj implements ClassPreProcessor { os.write(b); os.close(); } + + /* + * Shared classes methods + */ + + /** + * 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)).generatedClassesExist(); + } + + public void flushGeneratedClasses(ClassLoader loader){ + ((ClassLoaderWeavingAdaptor)WeaverContainer.getWeaver(loader, weavingContext)).flushGeneratedClasses(); + } } diff --git a/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java b/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java index 42c78aaad..bb41f37cd 100644 --- a/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java +++ b/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java @@ -8,6 +8,7 @@ * * Contributors: * Alexandre Vasseur initial implementation + * David Knibb weaving context enhancments *******************************************************************************/ package org.aspectj.weaver.loadtime; @@ -35,9 +36,11 @@ import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Properties; +import java.util.StringTokenizer; /** * @author Alexandre Vasseur @@ -50,8 +53,11 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor { private List m_includeTypePattern = new ArrayList(); private List m_excludeTypePattern = new ArrayList(); private List m_aspectExcludeTypePattern = new ArrayList(); + + private StringBuffer namespace; + private IWeavingContext weavingContext; - public ClassLoaderWeavingAdaptor(final ClassLoader loader) { + public ClassLoaderWeavingAdaptor(final ClassLoader loader, IWeavingContext wContext) { super(null);// at this stage we don't have yet a generatedClassHandler to define to the VM the closures this.generatedClassHandler = new GeneratedClassHandler() { /** @@ -72,6 +78,12 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor { Aj.defineClass(loader, name, bytes);// could be done lazily using the hook } }; + + if(wContext==null){ + weavingContext = new DefaultWeavingContext(loader); + }else{ + weavingContext = wContext ; + } bcelWorld = new BcelWorld( loader, messageHandler, new ICrossReferenceHandler() { @@ -107,7 +119,6 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor { try { MessageUtil.info(messageHandler, "register classloader " + ((loader!=null)?loader.getClass().getName()+"@"+loader.hashCode():"null")); //TODO av underoptimized: we will parse each XML once per CL that see it - Enumeration xmls = loader.getResources(AOP_XML); List definitions = new ArrayList(); //TODO av dev mode needed ? TBD -Daj5.def=... @@ -118,12 +129,21 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor { definitions.add(DocumentParser.parse((new File(file)).toURL())); } } + + String resourcePath = System.getProperty("org.aspectj.weaver.loadtime.configuration",AOP_XML); + StringTokenizer st = new StringTokenizer(resourcePath,";"); + + while(st.hasMoreTokens()){ + Enumeration xmls = weavingContext.getResources(st.nextToken()); +// System.out.println("? registerDefinitions: found-aop.xml=" + xmls.hasMoreElements() + ", loader=" + loader); - while (xmls.hasMoreElements()) { - URL xml = (URL) xmls.nextElement(); - MessageUtil.info(messageHandler, "using " + xml.getFile()); - definitions.add(DocumentParser.parse(xml)); - } + + while (xmls.hasMoreElements()) { + URL xml = (URL) xmls.nextElement(); + MessageUtil.info(messageHandler, "using " + xml.getFile()); + definitions.add(DocumentParser.parse(xml)); + } + } // still go thru if definitions is empty since we will configure // the default message handler in there @@ -231,6 +251,14 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor { String aspectClassName = (String) aspects.next(); if (acceptAspect(aspectClassName)) { weaver.addLibraryAspect(aspectClassName); + + //generate key for SC + String aspectCode = readAspect(aspectClassName, loader); + if(namespace==null){ + namespace=new StringBuffer(aspectCode); + }else{ + namespace = namespace.append(";"+aspectCode); + } } } } @@ -344,4 +372,63 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor { } return false; } + + /* + * shared classes methods + */ + + /** + * @return Returns the key. + */ + public String getNamespace() { + 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 + * @return true if a class has been generated and is stored in the cache + */ + public boolean generatedClassesExist(){ + if(generatedClasses.size()>0) { + return true; + } + return false; + } + + /** + * Flush the generated classes cache + */ + public void flushGeneratedClasses(){ + generatedClasses = new HashMap(); + } + + + /** + * Read in an aspect from the disk and return its bytecode as a String + * @param name the name of the aspect to read in + * @return the bytecode representation of the aspect + */ + private String readAspect(String name, ClassLoader loader){ + try { + String result = ""; + InputStream is = loader.getResourceAsStream(name.replace('.','/')+".class"); + int b = is.read(); + while(b!=-1){ + result = result + b; + b=is.read(); + } + is.close(); + return result; + } catch (IOException e) { + e.printStackTrace(); + return ""; + }catch (NullPointerException e) { + //probably tried to read in a "non aspect @missing@" aspect + System.err.println("ClassLoaderWeavingAdaptor.readAspect() name: "+name+" Exception: "+e); + return ""; + } + } + } diff --git a/loadtime/src/org/aspectj/weaver/loadtime/DefaultWeavingContext.java b/loadtime/src/org/aspectj/weaver/loadtime/DefaultWeavingContext.java new file mode 100644 index 000000000..7110e0c54 --- /dev/null +++ b/loadtime/src/org/aspectj/weaver/loadtime/DefaultWeavingContext.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + *******************************************************************************/ +package org.aspectj.weaver.loadtime; + +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; + +/** + * Use in non-OSGi environment + * + * @author David Knibb + */ +public class DefaultWeavingContext implements IWeavingContext { + + private ClassLoader loader; + + public DefaultWeavingContext(){ + loader = getClass().getClassLoader(); + } + + /** + * Construct a new WeavingContext to use the specifed ClassLoader + * This is the constructor which should be used. + * @param loader + */ + public DefaultWeavingContext(ClassLoader loader) { + this.loader = loader; + } + + /** + * Same as ClassLoader.getResources() + */ + public Enumeration getResources(String name) throws IOException { + return loader.getResources(name); + } + + /** + * @return null as we are not in an OSGi environment (therefore no bundles) + */ + public String getBundleIdFromURL(URL url) { + return null; + } + +} diff --git a/loadtime/src/org/aspectj/weaver/loadtime/IWeavingContext.java b/loadtime/src/org/aspectj/weaver/loadtime/IWeavingContext.java new file mode 100644 index 000000000..285fc81dc --- /dev/null +++ b/loadtime/src/org/aspectj/weaver/loadtime/IWeavingContext.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * David Knibb initial implementation + *******************************************************************************/ +package org.aspectj.weaver.loadtime; + +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; + +/** + * This class adds support to AspectJ for an OSGi environment + * + * @author David Knibb + */ +public interface IWeavingContext { + + /** + * Allows the standard ClassLoader.getResources() mechanisms to be + * replaced with a different implementation. + * In an OSGi environment, this will allow for filtering to take + * place on the results of ClassLoader.getResources(). In a non-OSGi + * environment, ClassLoader.getResources should be returned. + * @param name the name of the resource to search for + * @return an enumeration containing all of the matching resources found + * @throws IOException + */ + public Enumeration getResources(String name) throws IOException; + + /** + * In an OSGi environment, determin which bundle a URL originated from. + * In a non-OSGi environment, implementors should return null. + * @param url + * @return + */ + public String getBundleIdFromURL(URL url); + +} -- 2.39.5