/* *******************************************************************
 * 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 v1.0 
 * which accompanies this distribution and is available at 
 * http://www.eclipse.org/legal/epl-v10.html 
 *  
 * 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<String, IUnwovenClassFile>();
	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 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<String>();
		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.is19VMOrGreater()) {
	    		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<String>();
		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();
		if (LangUtil.is15VMOrGreater()) {
			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.set(false);
		}
	}

	/**
	 * @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 aspectPath) {
		// System.err.println("? WeavingAdaptor.registerAspectLibraries(" + aspectPath + ")");
		for (Iterator i = aspectPath.iterator(); i.hasNext();) {
			String libName = (String) i.next();
			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<String>();
		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
	 * @throws Throwable
	 */
	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<IMessage>();
				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<IMessage>();
			allMessages.addAll(savedMessages);
			allMessages.addAll(super.getUnmodifiableListView());
			return allMessages;
		}
	}

	protected class WeavingAdaptorMessageWriter extends MessageWriter {

		private final Set<IMessage.Kind> ignoring = new HashSet<IMessage.Kind>();
		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<UnwovenClassFile>();
		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;
	}
}