123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- /* *******************************************************************
- * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
- * 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:
- * PARC initial implementation
- * ******************************************************************/
-
- package org.aspectj.weaver;
-
- import java.io.File;
- import java.io.IOException;
- import java.util.Collection;
- import java.util.HashSet;
- import java.util.Map;
- import java.util.Set;
-
- import org.aspectj.bridge.IMessage;
- import org.aspectj.bridge.ISourceLocation;
- import org.aspectj.bridge.MessageUtil;
- import org.aspectj.bridge.SourceLocation;
- import org.aspectj.util.FuzzyBoolean;
- import org.aspectj.util.PartialOrder;
- import org.aspectj.weaver.patterns.PerClause;
- import org.aspectj.weaver.patterns.Pointcut;
- import org.aspectj.weaver.patterns.TypePattern;
-
- /**
- * For every shadow munger, nothing can be done with it until it is concretized. Then...
- *
- * (Then we call fast match.)
- *
- * For every shadow munger, for every shadow, first match is called, then (if match returned true) the shadow munger is specialized
- * for the shadow, which may modify state. Then implement is called.
- */
- public abstract class ShadowMunger implements PartialOrder.PartialComparable, IHasPosition {
-
- public static final ShadowMunger[] NONE = new ShadowMunger[0];
-
- private static int VERSION_1 = 1; // ShadowMunger version for serialization
-
- protected static final int ShadowMungerAdvice = 1;
- protected static final int ShadowMungerDeow = 2;
-
- public String handle = null;
-
- private int shadowMungerKind;
-
- protected int start, end;
- protected ISourceContext sourceContext;
- private ISourceLocation sourceLocation;
- private ISourceLocation binarySourceLocation;
- private File binaryFile;
- private ResolvedType declaringType;
- private boolean isBinary;
- private boolean checkedIsBinary;
-
- protected Pointcut pointcut;
-
- protected ShadowMunger() {
- }
-
- public ShadowMunger(Pointcut pointcut, int start, int end, ISourceContext sourceContext, int shadowMungerKind) {
- this.shadowMungerKind = shadowMungerKind;
- this.pointcut = pointcut;
- this.start = start;
- this.end = end;
- this.sourceContext = sourceContext;
- }
-
- /**
- * All overriding methods should call super
- */
- public boolean match(Shadow shadow, World world) {
- if (world.isXmlConfigured() && world.isAspectIncluded(declaringType)) {
- TypePattern scoped = world.getAspectScope(declaringType);
- if (scoped != null) {
- // Check the 'cached' exclusion map
- Set<ResolvedType> excludedTypes = world.getExclusionMap().get(declaringType);
- ResolvedType type = shadow.getEnclosingType().resolve(world);
- if (excludedTypes != null && excludedTypes.contains(type)) {
- return false;
- }
- boolean b = scoped.matches(type, TypePattern.STATIC).alwaysTrue();
- if (!b) {
- if (!world.getMessageHandler().isIgnoring(IMessage.INFO)) {
- world.getMessageHandler().handleMessage(
- MessageUtil.info("Type '" + type.getName() + "' not woven by aspect '" + declaringType.getName()
- + "' due to scope exclusion in XML definition"));
- }
- if (excludedTypes == null) {
- excludedTypes = new HashSet<ResolvedType>();
- excludedTypes.add(type);
- world.getExclusionMap().put(declaringType, excludedTypes);
- } else {
- excludedTypes.add(type);
- }
- return false;
- }
- }
- }
- if (world.areInfoMessagesEnabled() && world.isTimingEnabled()) {
- long starttime = System.nanoTime();
- FuzzyBoolean isMatch = pointcut.match(shadow);
- long endtime = System.nanoTime();
- world.record(pointcut, endtime - starttime);
- return isMatch.maybeTrue();
- } else {
- FuzzyBoolean isMatch = pointcut.match(shadow);
- return isMatch.maybeTrue();
- }
- }
-
- public int fallbackCompareTo(Object other) {
- return toString().compareTo(toString());
- }
-
- public int getEnd() {
- return end;
- }
-
- public int getStart() {
- return start;
- }
-
- public ISourceLocation getSourceLocation() {
- if (sourceLocation == null) {
- if (sourceContext != null) {
- sourceLocation = sourceContext.makeSourceLocation(this);
- }
- }
- if (isBinary()) {
- if (binarySourceLocation == null) {
- binarySourceLocation = getBinarySourceLocation(sourceLocation);
- }
- return binarySourceLocation;
- }
- return sourceLocation;
- }
-
- public Pointcut getPointcut() {
- return pointcut;
- }
-
- // pointcut may be updated during rewriting...
- public void setPointcut(Pointcut pointcut) {
- this.pointcut = pointcut;
- }
-
- /**
- * Invoked when the shadow munger of a resolved type are processed.
- *
- * @param aType
- */
- public void setDeclaringType(ResolvedType aType) {
- declaringType = aType;
- }
-
- public ResolvedType getDeclaringType() {
- return declaringType;
- }
-
- public abstract ResolvedType getConcreteAspect();
-
- /**
- * Returns the binarySourceLocation for the given sourcelocation. This isn't cached because it's used when faulting in the
- * binary nodes and is called with ISourceLocations for all advice, pointcuts and deows contained within the
- * resolvedDeclaringAspect.
- */
- public ISourceLocation getBinarySourceLocation(ISourceLocation sl) {
- if (sl == null) {
- return null;
- }
- String sourceFileName = null;
- if (getDeclaringType() instanceof ReferenceType) {
- String s = ((ReferenceType) getDeclaringType()).getDelegate().getSourcefilename();
- int i = s.lastIndexOf('/');
- if (i != -1) {
- sourceFileName = s.substring(i + 1);
- } else {
- sourceFileName = s;
- }
- }
- ISourceLocation sLoc = new SourceLocation(getBinaryFile(), sl.getLine(), sl.getEndLine(),
- ((sl.getColumn() == 0) ? ISourceLocation.NO_COLUMN : sl.getColumn()), sl.getContext(), sourceFileName);
- return sLoc;
- }
-
- /**
- * Returns the File with pathname to the class file, for example either:<br>
- * C:\temp \ajcSandbox\workspace\ajcTest16957.tmp\simple.jar!pkg\BinaryAspect.class if the class file is in a jar file, or <br>
- * C:\temp\ajcSandbox\workspace\ajcTest16957.tmp!pkg\BinaryAspect.class if the class file is in a directory
- */
- private File getBinaryFile() {
- if (binaryFile == null) {
- String binaryPath = getDeclaringType().getBinaryPath();
- if (binaryPath == null) {
- // Looks like an aspect that has been picked up from the classpath (likely an abstract one
- // being extended). As it didn't come in via inpath or aspectpath the binarypath has not
- // yet been constructed.
-
- // We can't discover where the file came from now, that info has been lost. So just
- // use "classpath" for now - until we discover we need to get this right.
-
- binaryPath = "classpath";
- getDeclaringType().setBinaryPath(binaryPath);
- // ReferenceTypeDelegate delegate = ((ReferenceType) getDeclaringType()).getDelegate();
- // if (delegate instanceof BcelObjectType) {
- // grab javaclass... but it doesnt know the originating file
- // }
- }
- if (binaryPath.indexOf("!") == -1) {
- File f = getDeclaringType().getSourceLocation().getSourceFile();
- // Replace the source file suffix with .class
- int i = f.getPath().lastIndexOf('.');
- String path = null;
- if (i != -1) {
- path = f.getPath().substring(0, i) + ".class";
- } else {
- path = f.getPath() + ".class";
- }
- binaryFile = new File(binaryPath + "!" + path);
- } else {
- binaryFile = new File(binaryPath);
- }
- }
- return binaryFile;
- }
-
- /**
- * Returns whether or not this shadow munger came from a binary aspect - keep a record of whether or not we've checked if we're
- * binary otherwise we keep calculating the same thing many times
- */
- public boolean isBinary() {
- if (!checkedIsBinary) {
- ResolvedType rt = getDeclaringType();
- if (rt != null) {
- isBinary = ((rt.getBinaryPath() == null) ? false : true);
- }
- checkedIsBinary = true;
- }
- return isBinary;
- }
-
- public abstract ShadowMunger concretize(ResolvedType fromType, World world, PerClause clause);
-
- public abstract void specializeOn(Shadow shadow);
-
- /**
- * Implement this munger at the specified shadow, returning a boolean to indicate success.
- *
- * @param shadow the shadow where this munger should be applied
- * @return true if the implement was successful
- */
- public abstract boolean implementOn(Shadow shadow);
-
- public abstract ShadowMunger parameterizeWith(ResolvedType declaringType, Map<String, UnresolvedType> typeVariableMap);
-
- /**
- * @return a Collection of ResolvedTypes for all checked exceptions that might be thrown by this munger
- */
- public abstract Collection<ResolvedType> getThrownExceptions();
-
- /**
- * Does the munger have to check that its exception are accepted by the shadow ? It is not the case for annotation style around
- * advice, for example: that can throw Throwable, even if the advised method does not throw any exceptions.
- *
- * @return true if munger has to check that its exceptions can be thrown based on the shadow
- */
- public abstract boolean mustCheckExceptions();
-
- public void write(CompressingDataOutputStream stream) throws IOException {
- stream.writeInt(VERSION_1);
- stream.writeInt(shadowMungerKind); // determines real subclass
- stream.writeInt(start);
- stream.writeInt(end);
- PersistenceSupport.write(stream, sourceContext);
- PersistenceSupport.write(stream, sourceLocation);
- PersistenceSupport.write(stream, binarySourceLocation);
- PersistenceSupport.write(stream, binaryFile);
- declaringType.write(stream);
- stream.writeBoolean(isBinary);
- stream.writeBoolean(checkedIsBinary);
- pointcut.write(stream);
- }
-
- //
- // public static ShadowMunger read(VersionedDataInputStream stream, World world) throws IOException {
- // stream.readInt();
- // int kind = stream.readInt();
- // ShadowMunger newShadowMunger = null;
- // switch (kind) {
- // case ShadowMungerAdvice:
- // // world.getWeavingSupport().createAdviceMunger(attribute, pointcut, signature)
- // case ShadowMungerDeow:
- // newShadowMunger = Checker.read(stream, world);
- // default:
- // throw new IllegalStateException("Unexpected type of shadow munger found on deserialization: " + kind);
- // }
- // newShadowMunger.binaryFile = null;
- // }
-
- }
|