diff options
author | Andy Clement <aclement@pivotal.io> | 2019-01-23 18:53:51 -0800 |
---|---|---|
committer | Andy Clement <aclement@pivotal.io> | 2019-01-23 18:53:51 -0800 |
commit | afaa961b294eca20fa9d54359c53a1de2d3c41fd (patch) | |
tree | 4b756f0f0dc4764cfcaeb200756de79cd4cdf56a /org.aspectj.matcher/src/main/java/org/aspectj/weaver/ShadowMunger.java | |
parent | 74dcae875f1c89b7e3fa2ffa6b524a3c187a597e (diff) | |
download | aspectj-afaa961b294eca20fa9d54359c53a1de2d3c41fd.tar.gz aspectj-afaa961b294eca20fa9d54359c53a1de2d3c41fd.zip |
mavenized org.aspectj.matcher module - wip
Diffstat (limited to 'org.aspectj.matcher/src/main/java/org/aspectj/weaver/ShadowMunger.java')
-rw-r--r-- | org.aspectj.matcher/src/main/java/org/aspectj/weaver/ShadowMunger.java | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/org.aspectj.matcher/src/main/java/org/aspectj/weaver/ShadowMunger.java b/org.aspectj.matcher/src/main/java/org/aspectj/weaver/ShadowMunger.java new file mode 100644 index 000000000..c07d7e8e7 --- /dev/null +++ b/org.aspectj.matcher/src/main/java/org/aspectj/weaver/ShadowMunger.java @@ -0,0 +1,307 @@ +/* ******************************************************************* + * 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; + // } + +} |