--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.ajdt.core;
+
+import java.util.Map;
+
+import org.aspectj.ajdt.internal.core.builder.AjCompilerOptions;
+import org.eclipse.core.runtime.IPluginDescriptor;
+import org.eclipse.jdt.core.JavaCore;
+
+/**
+ * This is the plugin class for AspectJ.
+ */
+public class AspectJCore extends JavaCore {
+
+ public static final String COMPILER_PB_INVALID_ABSOLUTE_TYPE_NAME = AjCompilerOptions.OPTION_ReportInvalidAbsoluteTypeName;
+ public static final String COMPILER_PB_INVALID_WILDCARD_TYPE_NAME = AjCompilerOptions.OPTION_ReportInvalidWildcardTypeName;
+ public static final String COMPILER_PB_UNRESOLVABLE_MEMBER = AjCompilerOptions.OPTION_ReportUnresolvableMember;
+ public static final String COMPILER_PB_TYPE_NOT_EXPOSED_TO_WEAVER = AjCompilerOptions.OPTION_ReportTypeNotExposedToWeaver;
+ public static final String COMPILER_PB_SHADOW_NOT_IN_STRUCTURE = AjCompilerOptions.OPTION_ReportShadowNotInStructure;
+ public static final String COMPILER_PB_UNMATCHED_SUPERTYPE_IN_CALL = AjCompilerOptions.OPTION_ReportUnmatchedSuperTypeInCall;
+ public static final String COMPILER_PB_CANNOT_IMPLEMENT_LAZY_TJP = AjCompilerOptions.OPTION_ReportCannotImplementLazyTJP;
+ public static final String COMPILER_PB_NEED_SERIAL_VERSION_UID = AjCompilerOptions.OPTION_ReportNeedSerialVersionUIDField;
+ public static final String COMPILER_PB_INCOMPATIBLE_SERIAL_VERSION = AjCompilerOptions.OPTION_ReportIncompatibleSerialVersion;
+
+ public static final String COMPILER_NO_WEAVE = AjCompilerOptions.OPTION_NoWeave;
+ public static final String COMPILER_SERIALIZABLE_ASPECTS = AjCompilerOptions.OPTION_XSerializableAspects;
+ public static final String COMPILER_LAZY_TJP = AjCompilerOptions.OPTION_XLazyThisJoinPoint;
+ public static final String COMPILER_NO_ADVICE_INLINE = AjCompilerOptions.OPTION_XNoInline;
+ public static final String COMPILER_REWEAVABLE = AjCompilerOptions.OPTION_XReweavable;
+ public static final String COMPILER_REWEAVABLE_COMPRESS = AjCompilerOptions.OPTION_XReweavableCompress;
+
+ public AspectJCore(IPluginDescriptor pluginDescriptor) {
+ super(pluginDescriptor);
+ }
+
+ public static AspectJCore getAspectJCore() {
+ return (AspectJCore) getPlugin();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.JavaCore#getCompilerOptions()
+ */
+ protected Map getCompilerOptions() {
+ return new AjCompilerOptions().getMap();
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.ajdt.internal.core.builder;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+
+import org.aspectj.ajdt.core.AspectJCore;
+import org.aspectj.ajdt.internal.compiler.AjCompilerAdapter;
+import org.aspectj.ajdt.internal.compiler.IBinarySourceProvider;
+import org.aspectj.ajdt.internal.compiler.IIntermediateResultsRequestor;
+import org.aspectj.ajdt.internal.compiler.IOutputClassFileNameProvider;
+import org.aspectj.ajdt.internal.compiler.InterimCompilationResult;
+import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment;
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
+import org.aspectj.ajdt.internal.compiler.problem.AjProblemReporter;
+import org.aspectj.bridge.AbortException;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.bridge.IMessage.Kind;
+import org.aspectj.weaver.Lint;
+import org.aspectj.weaver.bcel.BcelWeaver;
+import org.aspectj.weaver.bcel.BcelWorld;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IJavaModelMarker;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.Compiler;
+import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
+import org.eclipse.jdt.internal.compiler.ICompilerAdapter;
+import org.eclipse.jdt.internal.compiler.ICompilerAdapterFactory;
+import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.core.builder.BatchImageBuilder;
+import org.eclipse.jdt.internal.core.builder.BuildNotifier;
+import org.eclipse.jdt.internal.core.builder.IncrementalImageBuilder;
+import org.eclipse.jdt.internal.core.builder.JavaBuilder;
+
+/**
+ * @author colyer
+ *
+ * This is the builder class used by AJDT, and that the org.eclipse.ajdt.core
+ * plugin references.
+ */
+public class AspectJBuilder extends JavaBuilder implements ICompilerAdapterFactory {
+
+
+ // One builder instance per project (important)
+ private BcelWeaver myWeaver = null;
+ private BcelWorld myBcelWorld = null;
+ private EclipseClassPathManager cpManager = null;
+ private UnwovenResultCollector unwovenResultCollector = null;
+ private OutputFileNameProvider fileNameProvider = null;
+
+ private boolean isBatchBuild = false;
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.internal.events.InternalBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected IProject[] build(int kind, Map ignored, IProgressMonitor monitor)
+ throws CoreException {
+ // super method always causes construction of a new XXXImageBuilder, which
+ // causes construction of a new Compiler, so we will be detected as the
+ // adapter.
+ Compiler.setCompilerAdapterFactory(this);
+ return super.build(kind, ignored, monitor);
+ }
+
+ protected BatchImageBuilder getBatchImageBuilder() {
+ isBatchBuild = true;
+ return new AjBatchImageBuilder(this);
+ }
+
+ protected IncrementalImageBuilder getIncrementalImageBuilder() {
+ isBatchBuild = false;
+ return new AjIncrementalImageBuilder(this);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.ICompilerAdapterFactory#getAdapter(org.eclipse.jdt.internal.compiler.Compiler)
+ */
+ public ICompilerAdapter getAdapter(Compiler forCompiler) {
+ Map javaOptions = forCompiler.options.getMap();
+ // TODO get aspectj options from project and add into map before...
+ AjCompilerOptions ajOptions = new AjCompilerOptions(javaOptions);
+ forCompiler.options = ajOptions;
+
+ if (isBatchBuild || myBcelWorld == null || myWeaver == null) {
+ initWorldAndWeaver(ajOptions);
+ } else {
+ // update the nameEnvironment each time we compile...
+ cpManager.setNameEnvironment(nameEnvironment);
+ }
+
+ // * an eclipse factory -- create from AjLookupEnvironment, need to hide AjBuildManager field
+ AjProblemReporter pr =
+ new AjProblemReporter(DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+ forCompiler.options, new DefaultProblemFactory(Locale.getDefault()));
+ forCompiler.problemReporter = pr;
+ AjLookupEnvironment le =
+ new AjLookupEnvironment(forCompiler, forCompiler.options, pr,nameEnvironment);
+ EclipseFactory eFactory = new EclipseFactory(le,myBcelWorld,ajOptions.xSerializableAspects);
+ le.factory = eFactory;
+ forCompiler.lookupEnvironment = le;
+
+ AjBuildNotifier ajNotifier = (AjBuildNotifier) notifier;
+ if (fileNameProvider == null ) fileNameProvider = new OutputFileNameProvider(getProject());
+
+ // * the set of binary source entries for this compile -- from analyzing deltas, or everything if batch
+ // * the full set of binary source entries for the project -- from IAspectJProject
+ // TODO deal with inpath, injars here...
+ IBinarySourceProvider bsProvider = new NullBinarySourceProvider();
+ Map fullBinarySourceEntries = new HashMap();
+
+ // * the intermediate result set from the last batch compile
+ if (isBatchBuild) {
+ unwovenResultCollector = new UnwovenResultCollector();
+ }
+ Collection resultSetForFullWeave = unwovenResultCollector.getIntermediateResults();
+
+ return new AjCompilerAdapter(forCompiler,isBatchBuild,myBcelWorld,
+ myWeaver,eFactory,unwovenResultCollector,ajNotifier,fileNameProvider,bsProvider,
+ fullBinarySourceEntries,resultSetForFullWeave,
+ ajOptions.noWeave);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.core.builder.JavaBuilder#createBuildNotifier(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.core.resources.IProject)
+ */
+ protected BuildNotifier createBuildNotifier(IProgressMonitor monitor,
+ IProject currentProject) {
+ return new AjBuildNotifier(monitor, currentProject);
+ }
+
+
+ private void initWorldAndWeaver(AjCompilerOptions options) {
+ cpManager = new EclipseClassPathManager(nameEnvironment);
+ myBcelWorld = new BcelWorld(cpManager,new UnhandledMessageHandler(getProject()),null /*(xrefHandler)*/);
+ myBcelWorld.setXnoInline(options.xNoInline);
+ myBcelWorld.setXlazyTjp(options.xLazyThisJoinPoint);
+ setLintProperties(myBcelWorld,options);
+ myWeaver = new BcelWeaver(myBcelWorld);
+ myWeaver.setReweavableMode(options.xReweavable,options.xReweavableCompress);
+ // TODO deal with injars, inpath, and aspectpath here...
+ }
+
+ private void setLintProperties(BcelWorld world, AjCompilerOptions options) {
+ Properties p = new Properties();
+ Lint lintSettings = world.getLint();
+ Map map = options.getMap();
+ p.put(lintSettings.invalidAbsoluteTypeName.getName(),map.get(AjCompilerOptions.OPTION_ReportInvalidAbsoluteTypeName));
+ p.put(lintSettings.invalidWildcardTypeName.getName(),map.get(AjCompilerOptions.OPTION_ReportInvalidWildcardTypeName));
+ p.put(lintSettings.unresolvableMember.getName(),map.get(AjCompilerOptions.OPTION_ReportUnresolvableMember));
+ p.put(lintSettings.typeNotExposedToWeaver.getName(),map.get(AjCompilerOptions.OPTION_ReportTypeNotExposedToWeaver));
+ p.put(lintSettings.shadowNotInStructure.getName(),map.get(AjCompilerOptions.OPTION_ReportShadowNotInStructure));
+ p.put(lintSettings.unmatchedSuperTypeInCall.getName(),map.get(AjCompilerOptions.OPTION_ReportUnmatchedSuperTypeInCall));
+ p.put(lintSettings.canNotImplementLazyTjp.getName(),map.get(AjCompilerOptions.OPTION_ReportCannotImplementLazyTJP));
+ p.put(lintSettings.needsSerialVersionUIDField.getName(),map.get(AjCompilerOptions.OPTION_ReportNeedSerialVersionUIDField));
+ p.put(lintSettings.serialVersionUIDBroken.getName(),map.get(AjCompilerOptions.OPTION_ReportIncompatibleSerialVersion));
+ lintSettings.setFromProperties(p);
+ }
+
+ private static class UnwovenResultCollector implements IIntermediateResultsRequestor {
+
+ private Collection results = new ArrayList();
+
+ /* (non-Javadoc)
+ * @see org.aspectj.ajdt.internal.compiler.IIntermediateResultsRequestor#acceptResult(org.aspectj.ajdt.internal.compiler.InterimCompilationResult)
+ */
+ public void acceptResult(InterimCompilationResult intRes) {
+ results.add(intRes);
+ }
+
+ public Collection getIntermediateResults() {
+ return results;
+ }
+
+ }
+
+ // this class will only get messages that the weaver adapter couldn't tie into
+ // an originating resource in the project - make them messages on the project
+ // itself.
+ private static class UnhandledMessageHandler implements IMessageHandler {
+
+ private IProject project;
+
+ public UnhandledMessageHandler(IProject p) {
+ this.project = p;
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.bridge.IMessageHandler#handleMessage(org.aspectj.bridge.IMessage)
+ */
+ public boolean handleMessage(IMessage message) throws AbortException {
+ try {
+ IMarker marker = project.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
+ marker.setAttribute(IMarker.MESSAGE, message.getMessage());
+ marker.setAttribute(IMarker.SEVERITY, message.isError() ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING);
+ } catch (CoreException e) {
+ AspectJCore.getPlugin().getLog().log(e.getStatus());
+ }
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind)
+ */
+ public boolean isIgnoring(Kind kind) {
+ if (kind == IMessage.DEBUG || kind == IMessage.INFO) return true;
+ return false;
+ }
+
+ }
+
+
+ private static class OutputFileNameProvider implements IOutputClassFileNameProvider {
+
+ private IPath outputLocation;
+
+ public OutputFileNameProvider(IProject p) {
+ try {
+ outputLocation = JavaCore.create(p).getOutputLocation();
+ } catch (JavaModelException e) {
+ outputLocation = new Path(".");
+ AspectJCore.getPlugin().getLog().log(e.getStatus());
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.ajdt.internal.compiler.IOutputClassFileNameProvider#getOutputClassFileName(char[], org.eclipse.jdt.internal.compiler.CompilationResult)
+ */
+ public String getOutputClassFileName(char[] eclipseClassFileName, CompilationResult result) {
+ // In the AJDT implementation, the name provided here will be ignored, we write the results
+ // out in xxxImageBuilder.acceptResult() instead.
+ // simply return the default output directory for the project.
+ String filename = new String(eclipseClassFileName);
+ IPath out = outputLocation.append(filename);
+ out.addFileExtension(".class");
+ return out.toOSString();
+ }
+
+ }
+
+ // default impl class until the implementation is extended to cope with inpath, injars
+ private static class NullBinarySourceProvider implements IBinarySourceProvider {
+
+ /* (non-Javadoc)
+ * @see org.aspectj.ajdt.internal.compiler.IBinarySourceProvider#getBinarySourcesForThisWeave()
+ */
+ public Map getBinarySourcesForThisWeave() {
+ return new HashMap();
+ }
+
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.ajdt.internal.core.builder;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.weaver.TypeX;
+import org.aspectj.weaver.bcel.ClassPathManager;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+
+/**
+ * @author colyer
+ *
+ * Provide a type lookup environment for the weaver, without having to convert
+ * the various eclipse paths into their external form.
+ */
+public class EclipseClassPathManager extends ClassPathManager {
+
+ private INameEnvironment nameEnv;
+
+ public EclipseClassPathManager(INameEnvironment env) {
+ this.nameEnv = env;
+ }
+
+ // class path manager will be used by weaver across multiple compiles,
+ // whereas a name environment may be constructed per-compile.
+ public void setNameEnvironment(INameEnvironment env) {
+ this.nameEnv = env;
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.bcel.ClassPathManager#addPath(java.lang.String, org.aspectj.bridge.IMessageHandler)
+ */
+ public void addPath(String name, IMessageHandler handler) {
+ throw new UnsupportedOperationException("Can't add paths to an *Eclipse*ClassPathManager.");
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.bcel.ClassPathManager#find(org.aspectj.weaver.TypeX)
+ */
+ public ClassFile find(TypeX type) {
+ ClassFile cf = null;
+ String name = type.getName();
+ if (name.endsWith(".class")) {
+ name = name.substring(0,name.length() - ".class".length());
+ }
+ char[][] cname = CharOperation.splitOn('.',name.toCharArray());
+ NameEnvironmentAnswer answer = nameEnv.findType(cname);
+ if (answer == null || !answer.isBinaryType()) {
+ return null;
+ } else {
+ IBinaryType binType = answer.getBinaryType();
+ // XXX - but better than the alternative hacks
+ if (binType instanceof ClassFileReader) {
+ ClassFileReader cfr = (ClassFileReader) binType;
+ cf = new ClassFileReaderBackedClassFile(cfr);
+ } else {
+ throw new IllegalArgumentException(
+ "I'm only geared up to handle ClassFileReaders, and you gave me a " +
+ binType.getClass().getName());
+ }
+ return cf;
+ }
+ }
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.bcel.ClassPathManager#getAllClassFiles()
+ */
+ public List getAllClassFiles() {
+ throw new UnsupportedOperationException("I don't implement getAllClassFiles()");
+ //return Collections.EMPTY_LIST;
+ }
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer("EclipseClassPathManager: ");
+ buf.append(nameEnv.toString());
+ return buf.toString();
+ }
+
+ private class ClassFileReaderBackedClassFile extends ClassPathManager.ClassFile {
+
+ private ClassFileReader source;
+
+ public ClassFileReaderBackedClassFile(ClassFileReader cfr) {
+ source = cfr;
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.bcel.ClassPathManager.ClassFile#getInputStream()
+ */
+ public InputStream getInputStream() throws IOException {
+ return new ByteArrayInputStream(source.getReferenceBytes());
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.bcel.ClassPathManager.ClassFile#getPath()
+ */
+ public String getPath() {
+ return new String(source.getFileName());
+ }
+ }
+}