123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947 |
- /* *******************************************************************
- * Copyright (c) 2004 IBM Corporation
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Public License v 2.0
- * which accompanies this distribution and is available at
- * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
- *
- * Contributors:
- * Matthew Webster, Adrian Colyer, John Kew + Lyor Goldstein (caching)
- * Martin Lippert initial implementation
- * ******************************************************************/
-
- package org.aspectj.weaver.tools;
-
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.net.URL;
- import java.net.URLClassLoader;
- import java.security.ProtectionDomain;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Map;
- import java.util.Properties;
- import java.util.Set;
- import java.util.StringTokenizer;
-
- import org.aspectj.bridge.AbortException;
- import org.aspectj.bridge.IMessage;
- import org.aspectj.bridge.IMessage.Kind;
- import org.aspectj.bridge.IMessageContext;
- import org.aspectj.bridge.IMessageHandler;
- import org.aspectj.bridge.IMessageHolder;
- import org.aspectj.bridge.Message;
- import org.aspectj.bridge.MessageHandler;
- import org.aspectj.bridge.MessageUtil;
- import org.aspectj.bridge.MessageWriter;
- import org.aspectj.bridge.Version;
- import org.aspectj.bridge.WeaveMessage;
- import org.aspectj.util.FileUtil;
- import org.aspectj.util.LangUtil;
- import org.aspectj.weaver.IClassFileProvider;
- import org.aspectj.weaver.IUnwovenClassFile;
- import org.aspectj.weaver.IWeaveRequestor;
- import org.aspectj.weaver.World;
- import org.aspectj.weaver.bcel.BcelObjectType;
- import org.aspectj.weaver.bcel.BcelWeaver;
- import org.aspectj.weaver.bcel.BcelWorld;
- import org.aspectj.weaver.bcel.UnwovenClassFile;
- import org.aspectj.weaver.tools.cache.CachedClassEntry;
- import org.aspectj.weaver.tools.cache.CachedClassReference;
- import org.aspectj.weaver.tools.cache.SimpleCache;
- import org.aspectj.weaver.tools.cache.SimpleCacheFactory;
- import org.aspectj.weaver.tools.cache.WeavedClassCache;
-
- // OPTIMIZE add guards for all the debug/info/etc
- /**
- * This adaptor allows the AspectJ compiler to be embedded in an existing system to facilitate load-time weaving. It provides an
- * interface for a weaving class loader to provide a classpath to be woven by a set of aspects. A callback is supplied to allow a
- * class loader to define classes generated by the compiler during the weaving process.
- * <p>
- * A weaving class loader should create a <code>WeavingAdaptor</code> before any classes are defined, typically during construction.
- * The set of aspects passed to the adaptor is fixed for the lifetime of the adaptor although the classpath can be augmented. A
- * system property can be set to allow verbose weaving messages to be written to the console.
- *
- */
- public class WeavingAdaptor implements IMessageContext {
-
- /**
- * System property used to turn on verbose weaving messages
- */
- public static final String WEAVING_ADAPTOR_VERBOSE = "aj.weaving.verbose";
- public static final String SHOW_WEAVE_INFO_PROPERTY = "org.aspectj.weaver.showWeaveInfo";
- public static final String TRACE_MESSAGES_PROPERTY = "org.aspectj.tracing.messages";
-
- private final static String ASPECTJ_BASE_PACKAGE = "org.aspectj.";
- private final static String PACKAGE_INITIAL_CHARS = ASPECTJ_BASE_PACKAGE.charAt(0) + "sj";
-
- private boolean enabled = false;
- protected boolean verbose = getVerbose();
- protected BcelWorld bcelWorld;
- protected BcelWeaver weaver;
- private IMessageHandler messageHandler;
- private WeavingAdaptorMessageHolder messageHolder;
- private boolean abortOnError = false;
- protected GeneratedClassHandler generatedClassHandler;
- protected Map<String, IUnwovenClassFile> generatedClasses = new HashMap<>();
- public BcelObjectType delegateForCurrentClass; // lazily initialized, should be used to prevent parsing bytecode multiple
- // times
- protected ProtectionDomain activeProtectionDomain;
-
- private boolean haveWarnedOnJavax = false;
- protected WeavedClassCache cache;
-
- private int weavingSpecialTypes = 0;
- private static final int INITIALIZED = 0x1;
- private static final int WEAVE_JAVA_PACKAGE = 0x2;
- private static final int WEAVE_JAVAX_PACKAGE = 0x4;
-
- private static final Trace trace = TraceFactory.getTraceFactory().getTrace(WeavingAdaptor.class);
-
- protected WeavingAdaptor() {
- }
-
- /**
- * Construct a WeavingAdaptor with a reference to a weaving class loader. The adaptor will automatically search the class loader
- * hierarchy to resolve classes. The adaptor will also search the hierarchy for WeavingClassLoader instances to determine the
- * set of aspects to be used for weaving.
- *
- * @param loader instance of <code>ClassLoader</code>
- */
- public WeavingAdaptor(WeavingClassLoader loader) {
- // System.err.println("? WeavingAdaptor.<init>(" + loader +"," + aspectURLs.length + ")");
- generatedClassHandler = loader;
- init((ClassLoader)loader, getFullClassPath((ClassLoader) loader), getFullAspectPath((ClassLoader) loader/* ,aspectURLs */));
- }
-
- /**
- * Construct a WeavingAdaptor with a reference to a <code>GeneratedClassHandler</code>, a full search path for resolving classes
- * and a complete set of aspects. The search path must include classes loaded by the class loader constructing the
- * WeavingAdaptor and all its parents in the hierarchy.
- *
- * @param handler <code>GeneratedClassHandler</code>
- * @param classURLs the URLs from which to resolve classes
- * @param aspectURLs the aspects used to weave classes defined by this class loader
- */
- public WeavingAdaptor(GeneratedClassHandler handler, URL[] classURLs, URL[] aspectURLs) {
- // System.err.println("? WeavingAdaptor.<init>()");
- generatedClassHandler = handler;
- init(null, FileUtil.makeClasspath(classURLs), FileUtil.makeClasspath(aspectURLs));
- }
-
- protected List<String> getFullClassPath(ClassLoader loader) {
- List<String> list = new LinkedList<>();
- for (; loader != null; loader = loader.getParent()) {
- if (loader instanceof URLClassLoader) {
- URL[] urls = ((URLClassLoader) loader).getURLs();
- list.addAll(0, FileUtil.makeClasspath(urls));
- } else {
- warn("cannot determine classpath");
- }
- }
- // On Java9 it is possible to fail to find a URLClassLoader from which to derive a suitable classpath
- // For now we can determine it from the java.class.path:
- if (LangUtil.is9VMOrGreater()) {
- list.add(0, LangUtil.getJrtFsFilePath());
- List<String> javaClassPathEntries = makeClasspath(System.getProperty("java.class.path"));
- for (int i=javaClassPathEntries.size()-1;i>=0;i--) {
- String javaClassPathEntry = javaClassPathEntries.get(i);
- if (!list.contains(javaClassPathEntry)) {
- list.add(0,javaClassPathEntry);
- }
- }
- }
- // On Java9 the sun.boot.class.path won't be set. System classes accessible through JRT filesystem
- list.addAll(0, makeClasspath(System.getProperty("sun.boot.class.path")));
- return list;
- }
-
- private List<String> getFullAspectPath(ClassLoader loader) {
- List<String> list = new LinkedList<>();
- for (; loader != null; loader = loader.getParent()) {
- if (loader instanceof WeavingClassLoader) {
- URL[] urls = ((WeavingClassLoader) loader).getAspectURLs();
- list.addAll(0, FileUtil.makeClasspath(urls));
- }
- }
- return list;
- }
-
- private static boolean getVerbose() {
- try {
- return Boolean.getBoolean(WEAVING_ADAPTOR_VERBOSE);
- } catch (Throwable t) {
- // security exception
- return false;
- }
- }
-
- /**
- * Initialize the WeavingAdapter
- * @param loader ClassLoader used by this adapter; which can be null
- * @param classPath classpath of this adapter
- * @param aspectPath list of aspect paths
- */
- private void init(ClassLoader loader, List<String> classPath, List<String> aspectPath) {
- abortOnError = true;
- createMessageHandler();
-
- info("using classpath: " + classPath);
- info("using aspectpath: " + aspectPath);
-
- bcelWorld = new BcelWorld(classPath, messageHandler, null);
- bcelWorld.setXnoInline(false);
- bcelWorld.getLint().loadDefaultProperties();
- bcelWorld.setBehaveInJava5Way(true);
-
- weaver = new BcelWeaver(bcelWorld);
- registerAspectLibraries(aspectPath);
- initializeCache(loader, aspectPath, null, getMessageHandler());
- enabled = true;
- }
-
- /**
- * If the cache is enabled, initialize it and swap out the existing classhandler
- * for the caching one -
- *
- * @param loader classloader for this adapter, may be null
- * @param aspects List of strings representing aspects managed by the adapter; these could be urls or classnames
- * @param existingClassHandler current class handler
- * @param myMessageHandler current message handler
- */
- protected void initializeCache(ClassLoader loader, List<String> aspects, GeneratedClassHandler existingClassHandler, IMessageHandler myMessageHandler) {
- if (WeavedClassCache.isEnabled()) {
- cache = WeavedClassCache.createCache(loader, aspects, existingClassHandler, myMessageHandler);
- // Wrap the existing class handler so that any generated classes are also cached
- if (cache != null) {
- this.generatedClassHandler = cache.getCachingClassHandler();
- }
- }
- }
-
-
- protected void createMessageHandler() {
- messageHolder = new WeavingAdaptorMessageHolder(new PrintWriter(System.err));
- messageHandler = messageHolder;
- if (verbose) {
- messageHandler.dontIgnore(IMessage.INFO);
- }
- if (Boolean.getBoolean(SHOW_WEAVE_INFO_PROPERTY)) {
- messageHandler.dontIgnore(IMessage.WEAVEINFO);
- }
- info("AspectJ Weaver Version " + Version.getText() + " built on " + Version.getTimeText()); //$NON-NLS-1$
- }
-
- protected IMessageHandler getMessageHandler() {
- return messageHandler;
- }
-
- public IMessageHolder getMessageHolder() {
- return messageHolder;
- }
-
- protected void setMessageHandler(IMessageHandler mh) {
- if (mh instanceof ISupportsMessageContext) {
- ISupportsMessageContext smc = (ISupportsMessageContext) mh;
- smc.setMessageContext(this);
- }
- if (mh != messageHolder) {
- messageHolder.setDelegate(mh);
- }
- messageHolder.flushMessages();
- }
-
- protected void disable() {
- if (trace.isTraceEnabled()) {
- trace.enter("disable", this);
- }
-
- enabled = false;
- messageHolder.flushMessages();
-
- if (trace.isTraceEnabled()) {
- trace.exit("disable");
- }
- }
-
- protected void enable() {
- enabled = true;
- messageHolder.flushMessages();
- }
-
- protected boolean isEnabled() {
- return enabled;
- }
-
- /**
- * Appends URL to path used by the WeavingAdptor to resolve classes
- *
- * @param url to be appended to search path
- */
- public void addURL(URL url) {
- File libFile = new File(url.getPath());
- try {
- weaver.addLibraryJarFile(libFile);
- } catch (IOException ex) {
- warn("bad library: '" + libFile + "'");
- }
- }
-
- /**
- * Weave a class using aspects previously supplied to the adaptor.
- *
- * @param name the name of the class
- * @param bytes the class bytes
- * @return the woven bytes
- * @exception IOException weave failed
- */
- public byte[] weaveClass(String name, byte[] bytes) throws IOException {
- return weaveClass(name, bytes, false);
- }
-
- // Track if the weaver is already running on this thread - don't allow re-entrant calls
- private ThreadLocal<Boolean> weaverRunning = new ThreadLocal<Boolean>() {
- @Override
- protected Boolean initialValue() {
- return Boolean.FALSE;
- }
- };
-
- /**
- * Weave a class using aspects previously supplied to the adaptor.
- *
- * @param name the name of the class
- * @param bytes the class bytes
- * @param mustWeave if true then this class *must* get woven (used for concrete aspects generated from XML)
- * @return the woven bytes
- * @exception IOException weave failed
- */
- public byte[] weaveClass(String name, byte[] bytes, boolean mustWeave) throws IOException {
- if (trace == null) {
- // Pr231945: we are likely to be under tomcat and ENABLE_CLEAR_REFERENCES hasn't been set
- System.err
- .println("AspectJ Weaver cannot continue to weave, static state has been cleared. Are you under Tomcat? In order to weave '"
- + name
- + "' during shutdown, 'org.apache.catalina.loader.WebappClassLoader.ENABLE_CLEAR_REFERENCES=false' must be set (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=231945).");
- return bytes;
- }
- if (weaverRunning.get()) {
- // System.out.println("AJC: avoiding re-entrant call to transform " + name);
- return bytes;
- }
- try {
- weaverRunning.set(true);
- if (trace.isTraceEnabled()) {
- trace.enter("weaveClass", this, new Object[] { name, bytes });
- }
-
- if (!enabled) {
- if (trace.isTraceEnabled()) {
- trace.exit("weaveClass", false);
- }
- return bytes;
- }
-
- boolean debugOn = !messageHandler.isIgnoring(Message.DEBUG);
-
- try {
- delegateForCurrentClass = null;
- name = name.replace('/', '.');
- if (couldWeave(name, bytes)) {
- if (accept(name, bytes)) {
-
- // Determine if we have the weaved class cached
- CachedClassReference cacheKey = null;
- final byte[] original_bytes = bytes;
- if (cache != null && !mustWeave) {
- cacheKey = cache.createCacheKey(name, original_bytes);
- CachedClassEntry entry = cache.get(cacheKey, original_bytes);
- if (entry != null) {
- // If the entry has been explicitly ignored
- // return the original bytes
- if (entry.isIgnored()) {
- return bytes;
- }
- return entry.getBytes();
- }
- }
-
- // TODO @AspectJ problem
- // Annotation style aspects need to be included regardless in order to get
- // a valid aspectOf()/hasAspect() generated in them. However - if they are excluded
- // (via include/exclude in aop.xml) they really should only get aspectOf()/hasAspect()
- // and not be included in the full set of aspects being applied by 'this' weaver
- if (debugOn) {
- debug("weaving '" + name + "'");
- }
- bytes = getWovenBytes(name, bytes);
- // temporarily out - searching for @Aspect annotated types is a slow thing to do - we should
- // expect the user to name them if they want them woven - just like code style
- // } else if (shouldWeaveAnnotationStyleAspect(name, bytes)) {
- // if (mustWeave) {
- // if (bcelWorld.getLint().mustWeaveXmlDefinedAspects.isEnabled()) {
- // bcelWorld.getLint().mustWeaveXmlDefinedAspects.signal(name, null);
- // }
- // }
- // // an @AspectJ aspect needs to be at least munged by the aspectOf munger
- // if (debugOn) {
- // debug("weaving '" + name + "'");
- // }
- // bytes = getAtAspectJAspectBytes(name, bytes);
-
- // Add the weaved class to the cache only if there
- // has been an actual change
- // JVK: Is there a better way to check if the class has
- // been transformed without carrying up some value
- // from the depths?
- if (cacheKey != null) {
- // If no transform has been applied, mark the class
- // as ignored.
- if (Arrays.equals(original_bytes, bytes)) {
- cache.ignore(cacheKey, original_bytes);
- } else {
- cache.put(cacheKey, original_bytes, bytes);
- }
- }
- } else if (debugOn) {
- debug("not weaving '" + name + "'");
- }
- } else if (debugOn) {
- debug("cannot weave '" + name + "'");
- }
- } finally {
- delegateForCurrentClass = null;
- }
-
- if (trace.isTraceEnabled()) {
- trace.exit("weaveClass", bytes);
- }
- return bytes;
- } finally {
- weaverRunning.remove();
- }
- }
-
- /**
- * @param name
- * @return true if even valid to weave: either with an accept check or to munge it for @AspectJ aspectof support
- */
- private boolean couldWeave(String name, byte[] bytes) {
- return !generatedClasses.containsKey(name) && shouldWeaveName(name);
- }
-
- // ATAJ
- protected boolean accept(String name, byte[] bytes) {
- return true;
- }
-
- protected boolean shouldDump(String name, boolean before) {
- return false;
- }
-
- private boolean shouldWeaveName(String name) {
- if (PACKAGE_INITIAL_CHARS.indexOf(name.charAt(0)) != -1) {
- if ((weavingSpecialTypes & INITIALIZED) == 0) {
- weavingSpecialTypes |= INITIALIZED;
- // initialize it
- Properties p = weaver.getWorld().getExtraConfiguration();
- if (p != null) {
- boolean b = p.getProperty(World.xsetWEAVE_JAVA_PACKAGES, "false").equalsIgnoreCase("true");
- if (b) {
- weavingSpecialTypes |= WEAVE_JAVA_PACKAGE;
- }
- b = p.getProperty(World.xsetWEAVE_JAVAX_PACKAGES, "false").equalsIgnoreCase("true");
- if (b) {
- weavingSpecialTypes |= WEAVE_JAVAX_PACKAGE;
- }
- }
- }
- if (name.startsWith(ASPECTJ_BASE_PACKAGE)) {
- return false;
- }
- if (name.startsWith("sun.reflect.")) {// JDK reflect
- return false;
- }
- if (name.startsWith("javax.")) {
- if ((weavingSpecialTypes & WEAVE_JAVAX_PACKAGE) != 0) {
- return true;
- } else {
- if (!haveWarnedOnJavax) {
- haveWarnedOnJavax = true;
- warn("javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified");
- }
- return false;
- }
- }
- if (name.startsWith("java.")) {
- if ((weavingSpecialTypes & WEAVE_JAVA_PACKAGE) != 0) {
- return true;
- } else {
- return false;
- }
- }
- }
- // boolean should = !(name.startsWith("org.aspectj.")
- // || (name.startsWith("java.") && (weavingSpecialTypes & WEAVE_JAVA_PACKAGE) == 0)
- // || (name.startsWith("javax.") && (weavingSpecialTypes & WEAVE_JAVAX_PACKAGE) == 0)
- // // || name.startsWith("$Proxy")//JDK proxies//FIXME AV is that 1.3 proxy ? fe. ataspect.$Proxy0 is a java5 proxy...
- // || name.startsWith("sun.reflect."));
- return true;
- }
-
- /**
- * We allow @AJ aspect weaving so that we can add aspectOf() as part of the weaving (and not part of the source compilation)
- *
- * @param name
- * @param bytes bytecode (from classloader), allow to NOT lookup stuff on disk again during resolve
- * @return true if @Aspect
- */
- private boolean shouldWeaveAnnotationStyleAspect(String name, byte[] bytes) {
- if (delegateForCurrentClass == null) {
- // if (weaver.getWorld().isASMAround()) return asmCheckAnnotationStyleAspect(bytes);
- // else
- ensureDelegateInitialized(name, bytes);
- }
- return (delegateForCurrentClass.isAnnotationStyleAspect());
- }
-
- // private boolean asmCheckAnnotationStyleAspect(byte[] bytes) {
- // IsAtAspectAnnotationVisitor detector = new IsAtAspectAnnotationVisitor();
- //
- // ClassReader cr = new ClassReader(bytes);
- // try {
- // cr.accept(detector, true);//, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);
- // } catch (Exception spe) {
- // // if anything goes wrong, e.g., an NPE, then assume it's NOT an @AspectJ aspect...
- // System.err.println("Unexpected problem parsing bytes to discover @Aspect annotation");
- // spe.printStackTrace();
- // return false;
- // }
- //
- // return detector.isAspect();
- // }
-
- protected void ensureDelegateInitialized(String name, byte[] bytes) {
- if (delegateForCurrentClass == null) {
- BcelWorld world = (BcelWorld) weaver.getWorld();
- delegateForCurrentClass = world.addSourceObjectType(name, bytes, false);
- }
- }
-
- /**
- * Weave a set of bytes defining a class.
- *
- * @param name the name of the class being woven
- * @param bytes the bytes that define the class
- * @return byte[] the woven bytes for the class
- * @throws IOException
- */
- private byte[] getWovenBytes(String name, byte[] bytes) throws IOException {
- WeavingClassFileProvider wcp = new WeavingClassFileProvider(name, bytes);
- weaver.weave(wcp);
- return wcp.getBytes();
- }
-
- /**
- * Weave a set of bytes defining a class for only what is needed to turn @AspectJ aspect in a usefull form ie with aspectOf
- * method - see #113587
- *
- * @param name the name of the class being woven
- * @param bytes the bytes that define the class
- * @return byte[] the woven bytes for the class
- * @throws IOException
- */
- private byte[] getAtAspectJAspectBytes(String name, byte[] bytes) throws IOException {
- WeavingClassFileProvider wcp = new WeavingClassFileProvider(name, bytes);
- wcp.setApplyAtAspectJMungersOnly();
- weaver.weave(wcp);
- return wcp.getBytes();
- }
-
- private void registerAspectLibraries(List<String> aspectPath) {
- // System.err.println("? WeavingAdaptor.registerAspectLibraries(" + aspectPath + ")");
- for (String libName : aspectPath) {
- addAspectLibrary(libName);
- }
-
- weaver.prepareForWeave();
- }
-
- /*
- * Register an aspect library with this classloader for use during weaving. This class loader will also return (unmodified) any
- * of the classes in the library in response to a <code>findClass()</code> request. The library is not required to be on the
- * weavingClasspath given when this classloader was constructed.
- *
- * @param aspectLibraryJarFile a jar file representing an aspect library
- *
- * @throws IOException
- */
- private void addAspectLibrary(String aspectLibraryName) {
- File aspectLibrary = new File(aspectLibraryName);
- if (aspectLibrary.isDirectory() || (FileUtil.isZipFile(aspectLibrary))) {
- try {
- info("adding aspect library: '" + aspectLibrary + "'");
- weaver.addLibraryJarFile(aspectLibrary);
- } catch (IOException ex) {
- error("exception adding aspect library: '" + ex + "'");
- }
- } else {
- error("bad aspect library: '" + aspectLibrary + "'");
- }
- }
-
- private static List<String> makeClasspath(String cp) {
- List<String> ret = new ArrayList<>();
- if (cp != null) {
- StringTokenizer tok = new StringTokenizer(cp, File.pathSeparator);
- while (tok.hasMoreTokens()) {
- ret.add(tok.nextToken());
- }
- }
- return ret;
- }
-
- protected boolean debug(String message) {
- return MessageUtil.debug(messageHandler, message);
- }
-
- protected boolean info(String message) {
- return MessageUtil.info(messageHandler, message);
- }
-
- protected boolean warn(String message) {
- return MessageUtil.warn(messageHandler, message);
- }
-
- protected boolean warn(String message, Throwable th) {
- return messageHandler.handleMessage(new Message(message, IMessage.WARNING, th, null));
- }
-
- protected boolean error(String message) {
- return MessageUtil.error(messageHandler, message);
- }
-
- protected boolean error(String message, Throwable th) {
- return messageHandler.handleMessage(new Message(message, IMessage.ERROR, th, null));
- }
-
- public String getContextId() {
- return "WeavingAdaptor";
- }
-
- /**
- * Dump the given bytcode in _dump/... (dev mode)
- *
- * @param name
- * @param b
- * @param before whether we are dumping before weaving
- */
- protected void dump(String name, byte[] b, boolean before) {
- String dirName = getDumpDir();
-
- if (before) {
- dirName = dirName + File.separator + "_before";
- }
-
- String className = name.replace('.', '/');
- final File dir;
- if (className.indexOf('/') > 0) {
- dir = new File(dirName + File.separator + className.substring(0, className.lastIndexOf('/')));
- } else {
- dir = new File(dirName);
- }
- dir.mkdirs();
- String fileName = dirName + File.separator + className + ".class";
- try {
- // System.out.println("WeavingAdaptor.dump() fileName=" + new File(fileName).getAbsolutePath());
- FileOutputStream os = new FileOutputStream(fileName);
- os.write(b);
- os.close();
- } catch (IOException ex) {
- warn("unable to dump class " + name + " in directory " + dirName, ex);
- }
- }
-
- /**
- * @return the directory in which to dump - default is _ajdump but it
- */
- protected String getDumpDir() {
- return "_ajdump";
- }
-
- /**
- * Processes messages arising from weaver operations. Tell weaver to abort on any message more severe than warning.
- */
- protected class WeavingAdaptorMessageHolder extends MessageHandler {
-
- private IMessageHandler delegate;
- private List<IMessage> savedMessages;
-
- protected boolean traceMessages = Boolean.getBoolean(TRACE_MESSAGES_PROPERTY);
-
- public WeavingAdaptorMessageHolder(PrintWriter writer) {
-
- this.delegate = new WeavingAdaptorMessageWriter(writer);
- super.dontIgnore(IMessage.WEAVEINFO);
- }
-
- private void traceMessage(IMessage message) {
- if (message instanceof WeaveMessage) {
- trace.debug(render(message));
- } else if (message.isDebug()) {
- trace.debug(render(message));
- } else if (message.isInfo()) {
- trace.info(render(message));
- } else if (message.isWarning()) {
- trace.warn(render(message), message.getThrown());
- } else if (message.isError()) {
- trace.error(render(message), message.getThrown());
- } else if (message.isFailed()) {
- trace.fatal(render(message), message.getThrown());
- } else if (message.isAbort()) {
- trace.fatal(render(message), message.getThrown());
- } else {
- trace.error(render(message), message.getThrown());
- }
- }
-
- protected String render(IMessage message) {
- return "[" + getContextId() + "] " + message.toString();
- }
-
- public void flushMessages() {
- if (savedMessages == null) {
- savedMessages = new ArrayList<>();
- savedMessages.addAll(super.getUnmodifiableListView());
- clearMessages();
- for (IMessage message : savedMessages) {
- delegate.handleMessage(message);
- }
- }
- // accumulating = false;
- // messages.clear();
- }
-
- public void setDelegate(IMessageHandler messageHandler) {
- delegate = messageHandler;
- }
-
- /*
- * IMessageHandler
- */
-
- @Override
- public boolean handleMessage(IMessage message) throws AbortException {
- if (traceMessages) {
- traceMessage(message);
- }
-
- super.handleMessage(message);
-
- if (abortOnError && 0 <= message.getKind().compareTo(IMessage.ERROR)) {
- throw new AbortException(message);
- }
- // if (accumulating) {
- // boolean result = addMessage(message);
- // if (abortOnError && 0 <= message.getKind().compareTo(IMessage.ERROR)) {
- // throw new AbortException(message);
- // }
- // return result;
- // }
- // else return delegate.handleMessage(message);
-
- if (savedMessages != null) {
- delegate.handleMessage(message);
- }
- return true;
- }
-
- @Override
- public boolean isIgnoring(Kind kind) {
- return delegate.isIgnoring(kind);
- }
-
- @Override
- public void dontIgnore(IMessage.Kind kind) {
- if (null != kind && delegate != null) {
- delegate.dontIgnore(kind);
- }
- }
-
- @Override
- public void ignore(Kind kind) {
- if (null != kind && delegate != null) {
- delegate.ignore(kind);
- }
- }
-
- /*
- * IMessageHolder
- */
-
- @Override
- public List<IMessage> getUnmodifiableListView() {
- // System.err.println("? WeavingAdaptorMessageHolder.getUnmodifiableListView() savedMessages=" + savedMessages);
- List<IMessage> allMessages = new ArrayList<>();
- allMessages.addAll(savedMessages);
- allMessages.addAll(super.getUnmodifiableListView());
- return allMessages;
- }
- }
-
- protected class WeavingAdaptorMessageWriter extends MessageWriter {
-
- private final Set<IMessage.Kind> ignoring = new HashSet<>();
- private final IMessage.Kind failKind;
-
- public WeavingAdaptorMessageWriter(PrintWriter writer) {
- super(writer, true);
-
- ignore(IMessage.WEAVEINFO);
- ignore(IMessage.DEBUG);
- ignore(IMessage.INFO);
- this.failKind = IMessage.ERROR;
- }
-
- @Override
- public boolean handleMessage(IMessage message) throws AbortException {
- // boolean result =
- super.handleMessage(message);
- if (abortOnError && 0 <= message.getKind().compareTo(failKind)) {
- throw new AbortException(message);
- }
- return true;
- }
-
- @Override
- public boolean isIgnoring(Kind kind) {
- return ((null != kind) && (ignoring.contains(kind)));
- }
-
- /**
- * Set a message kind to be ignored from now on
- */
- @Override
- public void ignore(IMessage.Kind kind) {
- if ((null != kind) && (!ignoring.contains(kind))) {
- ignoring.add(kind);
- }
- }
-
- /**
- * Remove a message kind from the list of those ignored from now on.
- */
- @Override
- public void dontIgnore(IMessage.Kind kind) {
- if (null != kind) {
- ignoring.remove(kind);
- }
- }
-
- @Override
- protected String render(IMessage message) {
- return "[" + getContextId() + "] " + super.render(message);
- }
- }
-
- private class WeavingClassFileProvider implements IClassFileProvider {
-
- private final UnwovenClassFile unwovenClass;
- private final List<UnwovenClassFile> unwovenClasses = new ArrayList<>();
- private IUnwovenClassFile wovenClass;
- private boolean isApplyAtAspectJMungersOnly = false;
-
- public WeavingClassFileProvider(String name, byte[] bytes) {
- ensureDelegateInitialized(name, bytes);
- this.unwovenClass = new UnwovenClassFile(name, delegateForCurrentClass.getResolvedTypeX().getName(), bytes);
- this.unwovenClasses.add(unwovenClass);
-
- if (shouldDump(name.replace('/', '.'), true)) {
- dump(name, bytes, true);
- }
-
- }
-
- public void setApplyAtAspectJMungersOnly() {
- isApplyAtAspectJMungersOnly = true;
- }
-
- public boolean isApplyAtAspectJMungersOnly() {
- return isApplyAtAspectJMungersOnly;
- }
-
- public byte[] getBytes() {
- if (wovenClass != null) {
- return wovenClass.getBytes();
- } else {
- return unwovenClass.getBytes();
- }
- }
-
- public Iterator<UnwovenClassFile> getClassFileIterator() {
- return unwovenClasses.iterator();
- }
-
- public IWeaveRequestor getRequestor() {
- return new IWeaveRequestor() {
-
- public void acceptResult(IUnwovenClassFile result) {
- if (wovenClass == null) {
- wovenClass = result;
- String name = result.getClassName();
- if (shouldDump(name.replace('/', '.'), false)) {
- dump(name, result.getBytes(), false);
- }
- } else {
- // Classes generated by weaver e.g. around closure advice
- String className = result.getClassName();
- byte[] resultBytes = result.getBytes();
-
- if (SimpleCacheFactory.isEnabled()) {
- SimpleCache lacache=SimpleCacheFactory.createSimpleCache();
- lacache.put(result.getClassName(), wovenClass.getBytes(), result.getBytes());
- lacache.addGeneratedClassesNames(wovenClass.getClassName(), wovenClass.getBytes(), result.getClassName());
- }
-
- generatedClasses.put(className, result);
- generatedClasses.put(wovenClass.getClassName(), result);
- generatedClassHandler.acceptClass(className, null, resultBytes);
- }
- }
-
- public void processingReweavableState() {
- }
-
- public void addingTypeMungers() {
- }
-
- public void weavingAspects() {
- }
-
- public void weavingClasses() {
- }
-
- public void weaveCompleted() {
- // ResolvedType.resetPrimitives();
- if (delegateForCurrentClass != null) {
- delegateForCurrentClass.weavingCompleted();
- }
- // ResolvedType.resetPrimitives();
- // bcelWorld.discardType(typeBeingProcessed.getResolvedTypeX()); // work in progress
- }
- };
- }
- }
-
- public void setActiveProtectionDomain(ProtectionDomain protectionDomain) {
- activeProtectionDomain = protectionDomain;
- }
- }
|