From 1c2f67adb223e3cd54c5fcea90d35336e44ffdee Mon Sep 17 00:00:00 2001 From: acolyer Date: Tue, 8 Jun 2004 15:14:15 +0000 Subject: [PATCH] new classes used when building inside Eclipse --- .../org/aspectj/ajdt/core/AspectJCore.java | 55 ++++ .../core/builder/AjBatchImageBuilder.java | 40 +++ .../core/builder/AjBuildNotifier.java | 65 +++++ .../builder/AjIncrementalImageBuilder.java | 40 +++ .../internal/core/builder/AspectJBuilder.java | 273 ++++++++++++++++++ .../core/builder/EclipseClassPathManager.java | 119 ++++++++ 6 files changed, 592 insertions(+) create mode 100644 org.aspectj.ajdt.core/src/org/aspectj/ajdt/core/AspectJCore.java create mode 100644 org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBatchImageBuilder.java create mode 100644 org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildNotifier.java create mode 100644 org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjIncrementalImageBuilder.java create mode 100644 org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java create mode 100644 org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseClassPathManager.java diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/core/AspectJCore.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/core/AspectJCore.java new file mode 100644 index 000000000..f80fd75c1 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/core/AspectJCore.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * 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(); + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBatchImageBuilder.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBatchImageBuilder.java new file mode 100644 index 000000000..53442e20a --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBatchImageBuilder.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * 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 org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.core.builder.BatchImageBuilder; +import org.eclipse.jdt.internal.core.builder.SourceFile; + +/** + * @author colyer + * + * BatchImageBuilder used by IDEs (AJDT) + */ +public class AjBatchImageBuilder extends BatchImageBuilder { + + public AjBatchImageBuilder(AspectJBuilder builder) { + super(builder); + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.internal.compiler.ICompilerRequestor#acceptResult(org.eclipse.jdt.internal.compiler.CompilationResult) + */ + public void acceptResult(CompilationResult result) { + if ((result.getCompilationUnit() != null) && (result.getCompilationUnit() instanceof SourceFile)) { + super.acceptResult(result); + } else { + // it's a file originating from binary source... + // we need to handle it ourselves + // TODO handle binary source output + } + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildNotifier.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildNotifier.java new file mode 100644 index 000000000..121d68c24 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildNotifier.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * 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 org.aspectj.bridge.IProgressListener; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.internal.core.builder.BuildNotifier; + +/** + * @author colyer + * + * Build progress notification inside Eclipse + */ +public class AjBuildNotifier extends BuildNotifier implements IProgressListener { + + /** + * @param monitor + * @param project + */ + public AjBuildNotifier(IProgressMonitor monitor, IProject project) { + super(monitor, project); + } + + /* (non-Javadoc) + * @see org.aspectj.bridge.IProgressListener#setText(java.lang.String) + */ + public void setText(String text) { + subTask(text); + } + + /* (non-Javadoc) + * @see org.aspectj.bridge.IProgressListener#setProgress(double) + */ + public void setProgress(double percentDone) { + updateProgress((float)(percentDone/100.0f)); + } + + /* (non-Javadoc) + * @see org.aspectj.bridge.IProgressListener#setCancelledRequested(boolean) + */ + public void setCancelledRequested(boolean cancelRequested) { + // no-op + } + + /* (non-Javadoc) + * @see org.aspectj.bridge.IProgressListener#isCancelledRequested() + */ + public boolean isCancelledRequested() { + // can't delegate to super methods as they throw exception, which is not what we want inside weaver + boolean cancelRequested = cancelling; + if (monitor != null) { + cancelRequested = cancelRequested || monitor.isCanceled(); + } + return cancelRequested; + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjIncrementalImageBuilder.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjIncrementalImageBuilder.java new file mode 100644 index 000000000..d3b781ff6 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjIncrementalImageBuilder.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * 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 org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.core.builder.IncrementalImageBuilder; +import org.eclipse.jdt.internal.core.builder.SourceFile; + +/** + * @author colyer + * + * Incremental builder used by IDE support (AJDT) + */ +public class AjIncrementalImageBuilder extends IncrementalImageBuilder { + + public AjIncrementalImageBuilder(AspectJBuilder builder) { + super(builder); + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.internal.compiler.ICompilerRequestor#acceptResult(org.eclipse.jdt.internal.compiler.CompilationResult) + */ + public void acceptResult(CompilationResult result) { + if ((result.getCompilationUnit() != null) && (result.getCompilationUnit() instanceof SourceFile)) { + super.acceptResult(result); + } else { + // it's a file originating from binary source... + // we need to handle it ourselves + // TODO handle binary source output + } + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java new file mode 100644 index 000000000..276f708b8 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java @@ -0,0 +1,273 @@ +/******************************************************************************* + * 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(); + } + + } +} diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseClassPathManager.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseClassPathManager.java new file mode 100644 index 000000000..84e521c03 --- /dev/null +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseClassPathManager.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * 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()); + } + } +} -- 2.39.5