--- /dev/null
+Rewritten...
+
+[bcel] hundreds of classes removed, one class now represents groups of instructions rather than one class per instruction
+[bcel] verifier packaged separately purely for use by AspectJ tests, not delivered in aspectj packages now
+[weaver] optimized KindedAnnotationAccessVar - renamed to AnnotationAccessVar
+[weaver] simplified member/resolvedmember hierarchy - still more to do, trying to remove need for casts, we should *know* what we
+ are dealing with at each point
+
+todo:
+
+[weaver]
+[bcel] remove notion of Gens entirely (LineNumberGen/LocalVariableGen) and switch fully to lighter way tags
+[weaver] activate 'assertGoodBody()' code through command line option to catch bugs in the field
+[weaver] is reweavable turned off when LTW?
+
+measure performance - lot of hash table things used to keep types lightweight unless they need the extra data - might be a better way?
+OPTIMIZE task tag marks places noticed on the way through where we could do better
+
+hierarchies to attack:
+ASTNode
+UnresolvedType (messy...)
+Member
+
+
+28th April
+Looking at LazyMethodGen.pack() - 12% of the cpu usage for what we are testing. pack() is quite tricky to make better, wonder if we
+can differentiate amongst targeters to speed things up? Also instructionHandle has 'attributes' - for no good reason that I can see
+
+Removed static in BranchHandle...
+
+
+Performance analysis, following: http://java.sun.com/developer/technicalArticles/Programming/perfanal/
+
+
+Reveals of 5415 ticks (weaving rt.jar), we spend 25% of the time in WeaverAdapter.removeFromMap() !
+- changed that code to a CharOpt comparison
+- further changed to null 'lastReturnedResult' when it is finished with, should reduce ongoing calls
+- want to removeFromMap() quickly if we can. we can't usually because we have rebuilt the char array because
+ post weave we build a new UnwovenClassFile() - I've changed the code to copy across the charname which
+ means we can do remove() rather than searching all keys because the char array is the same one as what was
+ used for the key when it was put in.
+
+ knocks 25seconds (was 1 minute, now 35s) off the weave time
+
+--- Deliverable sizes: aspectjweaver.jar
+
+1.6.0 = 1,907,848 bytes:1094 classes
+26Apr = 1,718,083:893
+26Apr = 1,618,024:849 (verifier removed from delivered package)
+27Apr = 1,612,996:848
+
+
+----------------
+Finally have a loadtime weaving test
+
+see - d:\e312\eclipse\plugins
+ltwToolsProto.bat
+
+of the 20seconds it takes for 1925 classes, 1.81% is:
+
+org.aspectj.weaver.tools.WeavingAdaptor.weaveClass: 57.5% (1142 inclusive / 0 exclusive)
+org.aspectj.weaver.tools.WeavingAdaptor.getWovenBytes: 49.14% (976 inclusive / 0 exclusive)
+org.aspectj.weaver.bcel.BcelWeaver.weave: 48.94% (972 inclusive / 11 exclusive)
+org.aspectj.weaver.bcel.BcelWeaver.weaveAndNotify: 45.37% (901 inclusive / 0 exclusive)
+org.aspectj.weaver.bcel.BcelWeaver.getClassFilesFor: 22% (437 inclusive / 0 exclusive)
+org.aspectj.weaver.bcel.LazyClassGen.getJavaClassBytesIncludingReweavable: 22% (437 inclusive / 0 exclusive)
+org.aspectj.weaver.bcel.LazyClassGen.writeBack: 17.88% (355 inclusive / 4 exclusive)
+org.aspectj.weaver.bcel.LazyMethodGen.getMethod: 17.42% (346 inclusive / 0 exclusive)
+org.aspectj.weaver.bcel.LazyMethodGen.pack: 13.09% (260 inclusive / 3 exclusive)
+org.aspectj.weaver.bcel.LazyMethodGen.newPackBody: 8.36% (166 inclusive / 81 exclusive)
+org.aspectj.apache.bcel.generic.InstructionList.delete: 1.31% (26 inclusive / 1 exclusive)
+
+
+29Apr
+now the extra bytecode parse in UnwovenClassFile - can we get rid of it by using the ctor that supplies a classname?
+
+
+2may
+looked at the analysis and getSourceLocation() was being called a lot - wasn't sure why given I didn't use tjp in the advice - turns
+out a dummy xrefhandler is added in LTWWorld, and so all the guards to avoid doing anything if there is no xrefhandler are worthless.
+fixed.
+
+ noticed ClassParser ctor messing about remembering if the source is a zip and wrapping a baos in a bufferedinputstream - added new
+ ctor to avoid that and removed the zip nonsense
+
+2May = 1,588,317:841 but fails tests, buggerit
+
* PARC initial implementation
* ******************************************************************/
-
package org.aspectj.weaver;
import java.io.IOException;
import org.aspectj.util.TypeSafeEnum;
/**
- * The 5 kinds of advice in AspectJ.
+ * The five kinds of advice in AspectJ.
*
* @author Erik Hilsdale
* @author Jim Hugunin
*/
public class AdviceKind extends TypeSafeEnum {
+
private int precedence;
private boolean isAfter;
private boolean isCflow;
+
public AdviceKind(String name, int key, int precedence, boolean isAfter, boolean isCflow) {
super(name, key);
this.precedence = precedence;
return this == PerThisEntry || this == PerTargetEntry;
}
-}
+}
\ No newline at end of file
public static short WEAVER_VERSION_MAJOR_AJ150M4 = 3;
public static short WEAVER_VERSION_MAJOR_AJ150 = 2;
public static short WEAVER_VERSION_MINOR_AJ150 = 0;
+
+ // These are the weaver major/minor numbers for AspectJ 1.6.0
+ public static short WEAVER_VERSION_MAJOR_AJ160M2 = 5;
+ public static short WEAVER_VERSION_MAJOR_AJ160 = 4;
+ public static short WEAVER_VERSION_MINOR_AJ160 = 0;
+
// These are the weaver major/minor versions for *this* weaver
- private static short CURRENT_VERSION_MAJOR = WEAVER_VERSION_MAJOR_AJ150M4;
- private static short CURRENT_VERSION_MINOR = WEAVER_VERSION_MINOR_AJ150;
+ private static short CURRENT_VERSION_MAJOR = WEAVER_VERSION_MAJOR_AJ160M2;
+ private static short CURRENT_VERSION_MINOR = WEAVER_VERSION_MINOR_AJ160;
public static final WeaverVersionInfo UNKNOWN =
new WeaverVersionInfo(WEAVER_VERSION_MAJOR_UNKNOWN,WEAVER_VERSION_MINOR_UNKNOWN);
public static ResolvedMember perSingletonAspectOfMethod(UnresolvedType declaringType) {
- return new ResolvedMemberImpl(Member.METHOD,
- declaringType, PUBLIC_STATIC, "aspectOf",
- "()" + declaringType.getSignature());
+ return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, "aspectOf", "()" + declaringType.getSignature());
}
public static ResolvedMember perSingletonHasAspectMethod(UnresolvedType declaringType) {
boolean hasAnnotation(UnresolvedType ofType);
ResolvedType[] getAnnotationTypes();
- // SomeType getAnnotation(UnresolvedType ofType);
+
+ AnnotationX getAnnotationOfType(UnresolvedType ofType);
}
sb.append("]");
return sb.toString();
}
+
+ public boolean hasNamedValue(String n) {
+ if (nvPairs==null) return false;
+ for (int i=0;i<nvPairs.size();i++) {
+ AnnotationNameValuePair pair = (AnnotationNameValuePair)nvPairs.get(i);
+ if (pair.getName().equals(n)) return true;
+ }
+ return false;
+ }
+
+ /**
+ * Return true if the annotation has a value with the specified name (n) and value (v)
+ */
+ public boolean hasNameValuePair(String n, String v) {
+ if (nvPairs==null) return false;
+ for (int i=0;i<nvPairs.size();i++) {
+ AnnotationNameValuePair pair = (AnnotationNameValuePair)nvPairs.get(i);
+ if (pair.getName().equals(n)) {
+ if (pair.getValue().stringify().equals(v)) return true;
+ }
+ }
+ return false;
+ }
}
/**
* AnnotationX instances are holders for an annotation from either Bcel or
- * ASM. We have this holder so that types about the bcel weaver package
+ * eclipse. We have this holder so that types about the bcel weaver package
* can work with something not bytecode toolkit specific.
*/
public class AnnotationX {
public static final AnnotationX[] NONE = new AnnotationX[0];
private AnnotationGen theRealBcelAnnotation;
- private AnnotationAJ theRealASMAnnotation;
+ private AnnotationAJ theRealEclipseAnnotation; // OPTIMIZE push out into compiler, not ever used if purely binary weaving ?
private int mode = -1;
- private final static int MODE_ASM = 1;
+ private final static int MODE_ECLIPSE = 1;
private final static int MODE_BCEL = 2;
private ResolvedType signature = null;
}
public AnnotationX(AnnotationAJ a,World world) {
- theRealASMAnnotation = a;
- signature = UnresolvedType.forSignature(theRealASMAnnotation.getTypeSignature()).resolve(world);
- mode= MODE_ASM;
+ theRealEclipseAnnotation = a;
+ signature = UnresolvedType.forSignature(theRealEclipseAnnotation.getTypeSignature()).resolve(world);
+ mode= MODE_ECLIPSE;
}
public AnnotationGen getBcelAnnotation() {
public String toString() {
if (mode==MODE_BCEL) return theRealBcelAnnotation.toString();
- else return theRealASMAnnotation.toString();
+ else return theRealEclipseAnnotation.toString();
}
public String getTypeName() {
if (mode==MODE_BCEL) return theRealBcelAnnotation.getTypeName();
- else return Utility.signatureToString(theRealASMAnnotation.getTypeSignature());
+ else return Utility.signatureToString(theRealEclipseAnnotation.getTypeSignature());
}
public String getTypeSignature() {
if (mode==MODE_BCEL) return theRealBcelAnnotation.getTypeSignature();
- else return theRealASMAnnotation.getTypeSignature();
+ else return theRealEclipseAnnotation.getTypeSignature();
}
supportedTargets.add(ev.getEnumValueString());
}
} else {
- List values = theRealASMAnnotation.getNameValuePairs();
+ List values = theRealEclipseAnnotation.getNameValuePairs();
AnnotationNameValuePair nvp = (AnnotationNameValuePair)values.get(0);
ArrayAnnotationValue aav = (ArrayAnnotationValue)nvp.getValue();
AnnotationValue[] avs = aav.getValues();
public void print(StringBuffer sb) {
if (mode==MODE_BCEL) sb.append(theRealBcelAnnotation.toString());
- else sb.append(theRealASMAnnotation.stringify());
+ else sb.append(theRealEclipseAnnotation.stringify());
+ }
+
+ public boolean hasNameValuePair(String n, String v) {
+ if (mode==MODE_BCEL) return theRealBcelAnnotation.hasNameValuePair(n,v);
+ else return theRealEclipseAnnotation.hasNameValuePair(n,v);
+ }
+
+ public boolean hasNamedValue(String n) {
+ if (mode==MODE_BCEL) return theRealBcelAnnotation.hasNamedValue(n);
+ else return theRealEclipseAnnotation.hasNamedValue(n);
}
}
\ No newline at end of file
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * 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:
+ * Andy Clement initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * Represents a resolved array type
+ *
+ * @author Andy Clement
+ */
+public class ArrayReferenceType extends ReferenceType {
+
+ private ResolvedType componentType;
+
+
+ public ArrayReferenceType(String sig, String erasureSig, World world, ResolvedType componentType) {
+ super(sig, erasureSig, world);
+ this.componentType = componentType;
+ }
+
+ // These methods are from the original implementation when Array was a ResolvedType and not a ReferenceType
+
+ public final ResolvedMember[] getDeclaredFields() {
+ return ResolvedMember.NONE;
+ }
+
+ public final ResolvedMember[] getDeclaredMethods() {
+ // ??? should this return clone? Probably not...
+ // If it ever does, here is the code:
+ // ResolvedMember cloneMethod =
+ // new ResolvedMember(Member.METHOD,this,Modifier.PUBLIC,UnresolvedType.OBJECT,"clone",new UnresolvedType[]{});
+ // return new ResolvedMember[]{cloneMethod};
+ return ResolvedMember.NONE;
+ }
+
+ public final ResolvedType[] getDeclaredInterfaces() {
+ return new ResolvedType[] { world.getCoreType(CLONEABLE), world.getCoreType(SERIALIZABLE) };
+ }
+
+ public final ResolvedMember[] getDeclaredPointcuts() {
+ return ResolvedMember.NONE;
+ }
+
+ public boolean hasAnnotation(UnresolvedType ofType) {
+ return false;
+ }
+
+ public final ResolvedType getSuperclass() {
+ return world.getCoreType(OBJECT);
+ }
+
+ public final boolean isAssignableFrom(ResolvedType o) {
+ if (!o.isArray())
+ return false;
+ if (o.getComponentType().isPrimitiveType()) {
+ return o.equals(this);
+ } else {
+ return getComponentType().resolve(world).isAssignableFrom(o.getComponentType().resolve(world));
+ }
+ }
+
+ public boolean isAssignableFrom(ResolvedType o, boolean allowMissing) {
+ return isAssignableFrom(o);
+ }
+
+ public final boolean isCoerceableFrom(ResolvedType o) {
+ if (o.equals(UnresolvedType.OBJECT) || o.equals(UnresolvedType.SERIALIZABLE) || o.equals(UnresolvedType.CLONEABLE)) {
+ return true;
+ }
+ if (!o.isArray())
+ return false;
+ if (o.getComponentType().isPrimitiveType()) {
+ return o.equals(this);
+ } else {
+ return getComponentType().resolve(world).isCoerceableFrom(o.getComponentType().resolve(world));
+ }
+ }
+
+ public final int getModifiers() {
+ int mask = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
+ return (componentType.getModifiers() & mask) | Modifier.FINAL;
+ }
+
+ public UnresolvedType getComponentType() {
+ return componentType;
+ }
+
+ public ResolvedType getResolvedComponentType() {
+ return componentType;
+ }
+
+ public ISourceContext getSourceContext() {
+ return getResolvedComponentType().getSourceContext();
+ }
+
+
+ // Methods overridden from ReferenceType follow
+
+ public TypeVariable[] getTypeVariables() {
+ if (this.typeVariables == null && componentType.getTypeVariables() != null) {
+ this.typeVariables = componentType.getTypeVariables();
+ for (int i = 0; i < this.typeVariables.length; i++) {
+ this.typeVariables[i].resolve(world);
+ }
+ }
+ return this.typeVariables;
+ }
+
+ public boolean isAnnotation() {
+ return false;
+ }
+
+ public boolean isAnonymous() {
+ return false;
+ }
+
+ public boolean isAnnotationStyleAspect() {
+ return false;
+ }
+
+ public boolean isAspect() {
+ return false;
+ }
+
+ public boolean isPrimitiveType() {
+ return typeKind == TypeKind.PRIMITIVE;
+ }
+
+ public boolean isSimpleType() {
+ return typeKind == TypeKind.SIMPLE;
+ }
+
+ public boolean isRawType() {
+ return typeKind == TypeKind.RAW;
+ }
+
+ public boolean isGenericType() {
+ return typeKind == TypeKind.GENERIC;
+ }
+
+ public boolean isParameterizedType() {
+ return typeKind == TypeKind.PARAMETERIZED;
+ }
+
+ public boolean isTypeVariableReference() {
+ return typeKind == TypeKind.TYPE_VARIABLE;
+ }
+
+ public boolean isGenericWildcard() {
+ return typeKind == TypeKind.WILDCARD;
+ }
+
+ public boolean isEnum() {
+ return false;
+ }
+
+ public boolean isNested() {
+ return false;
+ }
+
+ public boolean isClass() {
+ return false;
+ }
+
+ public boolean canAnnotationTargetType() {
+ return false;
+ }
+
+ public AnnotationTargetKind[] getAnnotationTargetKinds() {
+ return null;
+ }
+
+ public boolean isAnnotationWithRuntimeRetention() {
+ return false;
+ }
+}
import java.util.Iterator;
import java.util.List;
+import org.aspectj.apache.bcel.classfile.Field;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.Utility;
import org.aspectj.apache.bcel.generic.Type;
* the fields' type in order to locate it. Currently just fails silently if any of the lookup code
* doesn't find anything...
*/
- public void addDeclareAnnotationRelationship(ISourceLocation sourceLocation, String typename,String fieldName) {
+ public void addDeclareAnnotationRelationship(ISourceLocation sourceLocation, String typename,Field field) {
if (!AsmManager.isCreatingModel()) return;
String pkg = null;
IProgramElement typeElem = AsmManager.getDefault().getHierarchy().findElementForType(pkg,type);
if (typeElem == null) return;
- IProgramElement fieldElem = AsmManager.getDefault().getHierarchy().findElementForSignature(typeElem,IProgramElement.Kind.FIELD,fieldName);
+ IProgramElement fieldElem = AsmManager.getDefault().getHierarchy().findElementForSignature(typeElem,IProgramElement.Kind.FIELD,field.getName());
if (fieldElem== null) return;
String targetHandle = fieldElem.getHandleIdentifier();
+++ /dev/null
-/* *******************************************************************
- * 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;
-
-/**
- * Exception to use inside the bcweaver.
- */
-public class BetaException extends RuntimeException {
-
- public BetaException() {
- super();
- }
-
- public BetaException(String s) {
- super(s);
- }
-
-}
package org.aspectj.weaver;
+import java.util.Map;
+
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.util.PartialOrder;
if (munger==null) return false;
return munger.isLateMunger();
}
+
+ public abstract ConcreteTypeMunger parameterizeWith(Map parameterizationMap, World world);
}
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
+import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.aspectj.weaver.bcel.BcelAdvice;
this.shouldConcretizeIfNeeded = shouldConcretizeIfNeeded;
}
+
+ private Hashtable cflowFields = new Hashtable();
+ private Hashtable cflowBelowFields = new Hashtable();
+
// public void addConcreteShadowMungers(Collection c) {
// shadowMungers.addAll(c);
// }
return declareAnnotationsOnMethods;
}
+ public Map getCflowBelowFields() {
+ return cflowBelowFields;
+ }
+
+ public Map getCflowFields() {
+ return cflowFields;
+ }
+
+ public void clearCaches() {
+ cflowFields.clear();
+ cflowBelowFields.clear();
+ }
+
}
if (xcut == null) {
members.put(aspectType, aspectType.collectCrosscuttingMembers(inWeavingPhase));
clearCaches();
- CflowPointcut.clearCaches(aspectType);
change = true;
} else {
if (xcut.replaceWith(aspectType.collectCrosscuttingMembers(inWeavingPhase),inWeavingPhase)) {
clearCaches();
-
- CflowPointcut.clearCaches(aspectType);
change = true;
} else {
if (!AsmManager.getDefault().getHandleProvider().dependsOnLocation()
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2007 Contributors
+ * 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:
+ * Linton Ye https://bugs.eclipse.org/bugs/show_bug.cgi?id=193065
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.util.Collection;
+
+/**
+ * <p>
+ * This interface is introduced to support tools like PointcutDoctor.
+ * </p>
+ * <p>
+ * A CustomMungerFactory is used to create ShadowMungers and/or
+ * ConcreteTypeMungers so that an extender can extract extra information during
+ * the weaving process.
+ * </p>
+ * <p>
+ * A CustomMungerFactory is assigned to a weaver through its AjCompiler in
+ * extenders' code, and gets invoked by the weaver right before the weaving
+ * starts. The custom shadow/type mungers being created will be added into the
+ * shadow/type munger list in the weaver and participate the weaving process.
+ * For example, the match method of each custom shadow munger will be called
+ * against each shadow.
+ * </p>
+ * @author lintonye
+ *
+ */
+public interface CustomMungerFactory {
+
+ /**
+ * @param aspectType
+ * @return a Collection<ShadowMunger> of custom shadow mungers for the
+ * given aspect
+ */
+ public Collection/* ShadowMunger */createCustomShadowMungers(
+ ResolvedType aspectType);
+
+ /**
+ * @param aspectType
+ * @return a Collection<ConcreteTypeMunger> of custom type mungers for the
+ * given aspect
+ */
+ public Collection/* ConcreteTypeMunger */createCustomTypeMungers(
+ ResolvedType aspectType);
+
+ public Collection/* ShadowMunger */getAllCreatedCustomShadowMungers();
+
+ public Collection/* ConcreteTypeMunger */getAllCreatedCustomTypeMungers();
+}
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.weaver.AjAttribute.EffectiveSignatureAttribute;
public ResolvedType[] getAnnotationTypes() {
return realMember.getAnnotationTypes();
}
+
+ public AnnotationX getAnnotationOfType(UnresolvedType ofType) {
+ return realMember.getAnnotationOfType(ofType);
+ }
public void setAnnotationTypes(UnresolvedType[] annotationtypes) {
realMember.setAnnotationTypes(annotationtypes);
return realMember.resolve(world);
}
- public int compareTo(Object other) {
- return realMember.compareTo(other);
- }
-
- public String toLongString() {
- return realMember.toLongString();
- }
-
- public Kind getKind() {
+ public MemberKind getKind() {
return realMember.getKind();
}
public UnresolvedType[] getParameterTypes() {
return realMember.getParameterTypes();
}
+
+ public AnnotationX[][] getParameterAnnotations() {
+ return realMember.getParameterAnnotations();
+ }
+
+ public ResolvedType[][] getParameterAnnotationTypes() {
+ return realMember.getParameterAnnotationTypes();
+ }
public String getSignature() {
return realMember.getSignature();
return realMember.isCompatibleWith(am);
}
- public boolean isProtected(World world) {
- return realMember.isProtected(world);
- }
-
- public boolean isStatic(World world) {
- return realMember.isStatic(world);
- }
-
- public boolean isStrict(World world) {
- return realMember.isStrict(world);
- }
-
public boolean isStatic() {
return realMember.isStatic();
}
realMember.resetName(newName);
}
- public void resetKind(Kind newKind) {
+ public void resetKind(MemberKind newKind) {
realMember.resetKind(newKind);
}
public void evictWeavingState() { realMember.evictWeavingState(); }
- public Member slimline() {
- return this;
+ public ResolvedMember parameterizedWith(Map m, World w) {
+ return realMember.parameterizedWith(m,w);
+ }
+
+ public String getAnnotationDefaultValue() {
+ return realMember.getAnnotationDefaultValue();
}
}
public final Kind advisingSynchronizedMethods = new Kind("advisingSynchronizedMethods",
"advice matching the synchronized method shadow ''{0}'' will be executed outside the lock rather than inside (compiler limitation)");
+ public final Kind mustWeaveXmlDefinedAspects = new Kind("mustWeaveXmlDefinedAspects",
+ "XML Defined aspects must be woven in cases where cflow pointcuts are involved. Currently the include/exclude patterns exclude ''{0}''");
+
private static Trace trace = TraceFactory.getTraceFactory().getTrace(Lint.class);
public Lint(World world) {
* ******************************************************************/
package org.aspectj.weaver;
-import java.io.DataInputStream;
-import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
-import org.aspectj.util.TypeSafeEnum;
public interface Member {
- public static class Kind extends TypeSafeEnum {
- public Kind(String name, int key) { super(name, key); }
-
- public static Kind read(DataInputStream s) throws IOException {
- int key = s.readByte();
- switch(key) {
- case 1: return METHOD;
- case 2: return FIELD;
- case 3: return CONSTRUCTOR;
- case 4: return STATIC_INITIALIZATION;
- case 5: return POINTCUT;
- case 6: return ADVICE;
- case 7: return HANDLER;
- case 8: return MONITORENTER;
- case 9: return MONITOREXIT;
- }
- throw new BCException("weird kind " + key);
- }
- }
-
- public static final Member[] NONE = new Member[0];
- public static final Kind METHOD = new Kind("METHOD", 1);
- public static final Kind FIELD = new Kind("FIELD", 2);
- public static final Kind CONSTRUCTOR = new Kind("CONSTRUCTOR", 3);
- public static final Kind STATIC_INITIALIZATION = new Kind("STATIC_INITIALIZATION", 4);
- public static final Kind POINTCUT = new Kind("POINTCUT", 5);
- public static final Kind ADVICE = new Kind("ADVICE", 6);
- public static final Kind HANDLER = new Kind("HANDLER", 7);
- public static final Kind MONITORENTER = new Kind("MONITORENTER", 8);
- public static final Kind MONITOREXIT = new Kind("MONITOREXIT", 9);
-
-
+ public static final Member[] NONE = new Member[0];
+ public static final MemberKind METHOD = new MemberKind("METHOD", 1);
+ public static final MemberKind FIELD = new MemberKind("FIELD", 2);
+ public static final MemberKind CONSTRUCTOR = new MemberKind("CONSTRUCTOR", 3);
+ public static final MemberKind STATIC_INITIALIZATION = new MemberKind("STATIC_INITIALIZATION", 4);
+ public static final MemberKind POINTCUT = new MemberKind("POINTCUT", 5);
+ public static final MemberKind ADVICE = new MemberKind("ADVICE", 6);
+ public static final MemberKind HANDLER = new MemberKind("HANDLER", 7);
+ public static final MemberKind MONITORENTER = new MemberKind("MONITORENTER", 8);
+ public static final MemberKind MONITOREXIT = new MemberKind("MONITOREXIT", 9);
+
+ public static final AnnotationX[][] NO_PARAMETER_ANNOTATIONXS = new AnnotationX[][]{};
+ public static final ResolvedType[][] NO_PARAMETER_ANNOTATION_TYPES = new ResolvedType[][]{};
+
+ public MemberKind getKind();
+
public ResolvedMember resolve(World world);
- public int compareTo(Object other);
-
- public String toLongString();
-
- public Kind getKind();
+ public String getName();
public UnresolvedType getDeclaringType();
- public UnresolvedType getReturnType();
-
+ public AnnotationX[] getAnnotations();
+ public UnresolvedType getReturnType();
+ public UnresolvedType getType();
public UnresolvedType getGenericReturnType();
- public UnresolvedType[] getGenericParameterTypes();
-
- public UnresolvedType getType();
-
- public String getName();
+ public String[] getParameterNames(World world);
public UnresolvedType[] getParameterTypes();
-
+ public UnresolvedType[] getGenericParameterTypes();
+
/**
* Return full signature, including return type, e.g. "()LFastCar;" for a signature without the return type,
- * use getParameterSignature() - it is importnant to choose the right one in the face of covariance.
+ * use getParameterSignature() - it is important to choose the right one in the face of covariance.
*/
public String getSignature();
public UnresolvedType[] getExceptions(World world);
- public boolean isProtected(World world);
-
- public boolean isStatic(World world);
-
- public boolean isStrict(World world);
-
public boolean isStatic();
public boolean isInterface();
public boolean isPrivate();
- /**
- * Returns true iff the member is generic (NOT parameterized)
- * For example, a method declared in a generic type
- */
- public boolean canBeParameterized();
-
public int getCallsiteModifiers();
public String getExtractableName();
- /**
- * If you want a sensible answer, resolve the member and call
- * hasAnnotation() on the ResolvedMember.
- */
- public boolean hasAnnotation(UnresolvedType ofType);
-
- /* (non-Javadoc)
- * @see org.aspectj.weaver.AnnotatedElement#getAnnotationTypes()
- */
- public ResolvedType[] getAnnotationTypes();
-
- public AnnotationX[] getAnnotations();
+// public AnnotationX[] getAnnotations();
public Collection/*ResolvedType*/getDeclaringTypes(World world);
- // ---- reflective thisJoinPoint stuff
+ // ---- reflective thisJoinPoint related methods
public String getSignatureMakerName();
public String getSignatureType();
public String getSignatureString(World world);
- public String[] getParameterNames(World world);
-
- public Member slimline();
-
}
\ No newline at end of file
import java.util.List;
-public class MemberImpl implements Comparable, AnnotatedElement,Member {
-
- protected Kind kind;
- protected int modifiers;
- protected UnresolvedType declaringType;
+public class MemberImpl implements Comparable, Member {
+
+ protected MemberKind kind;
protected String name;
+
+ protected UnresolvedType declaringType;
+ protected int modifiers;
protected UnresolvedType returnType;
protected UnresolvedType[] parameterTypes;
private final String signature;
private String paramSignature;
+
+ // OPTIMIZE move out of the member!
private boolean reportedCantFindDeclaringType = false;
private boolean reportedUnresolvableMember = false;
+
+ public AnnotationX[] getAnnotations() {
+ throw new IllegalStateException("Cannot answer getAnnotations() for MemberImpl "+this.toString());
+ }
/**
* All the signatures that a join point with this member as its signature has.
private JoinPointSignatureIterator joinPointSignatures = null;
public MemberImpl(
- Kind kind,
+ MemberKind kind,
UnresolvedType declaringType,
int modifiers,
String name,
this.declaringType = declaringType;
this.modifiers = modifiers;
this.name = name;
+ if (kind!=STATIC_INITIALIZATION && name!=null && name.equals("<clinit>")) {
+ throw new RuntimeException("!");
+ }
this.signature = signature;
if (kind == FIELD) {
this.returnType = UnresolvedType.forSignature(signature);
}
public MemberImpl(
- Kind kind,
+ MemberKind kind,
UnresolvedType declaringType,
int modifiers,
UnresolvedType returnType,
super();
this.kind = kind;
this.declaringType = declaringType;
- this.modifiers = modifiers;
+ this.modifiers = modifiers;
+ if (name!=null && name.equals("<clinit>") && kind!=STATIC_INITIALIZATION) {
+ throw new RuntimeException("!");
+ }
+
this.returnType = returnType;
this.name = name;
this.parameterTypes = parameterTypes;
private static MemberImpl field(String declaring, int mods, UnresolvedType ty, String name) {
- return new MemberImpl(
- FIELD,
- UnresolvedType.forName(declaring),
- mods,
- ty,
- name,
- UnresolvedType.NONE);
+ return new MemberImpl(FIELD, UnresolvedType.forName(declaring), mods, ty, name, UnresolvedType.NONE);
}
public static MemberImpl method(UnresolvedType declTy, int mods, UnresolvedType rTy, String name, UnresolvedType[] paramTys) {
"(" + catchType.getSignature() + ")V");
}
- // ---- parsing methods
-
- /** Takes a string in this form:
- *
- * <blockquote><pre>
- * static? TypeName TypeName.Id
- * </pre></blockquote>
- * Pretty much just for testing, and as such should perhaps be moved.
- */
-
- public static MemberImpl fieldFromString(String str) {
- str = str.trim();
- final int len = str.length();
- int i = 0;
- int mods = 0;
- if (str.startsWith("static", i)) {
- mods = Modifier.STATIC;
- i += 6;
- while (Character.isWhitespace(str.charAt(i))) i++;
- }
- int start = i;
- while (! Character.isWhitespace(str.charAt(i))) i++;
- UnresolvedType retTy = UnresolvedType.forName(str.substring(start, i));
-
- start = i;
- i = str.lastIndexOf('.');
- UnresolvedType declaringTy = UnresolvedType.forName(str.substring(start, i).trim());
- start = ++i;
- String name = str.substring(start, len).trim();
- return new MemberImpl(
- FIELD,
- declaringTy,
- mods,
- retTy,
- name,
- UnresolvedType.NONE);
- }
-
- /** Takes a string in this form:
- *
- * <blockquote><pre>
- * (static|interface|private)? TypeName TypeName . Id ( TypeName , ...)
- * </pre></blockquote>
- * Pretty much just for testing, and as such should perhaps be moved.
- */
-
- public static Member methodFromString(String str) {
- str = str.trim();
- // final int len = str.length();
- int i = 0;
-
- int mods = 0;
- if (str.startsWith("static", i)) {
- mods = Modifier.STATIC;
- i += 6;
- } else if (str.startsWith("interface", i)) {
- mods = Modifier.INTERFACE;
- i += 9;
- } else if (str.startsWith("private", i)) {
- mods = Modifier.PRIVATE;
- i += 7;
- }
- while (Character.isWhitespace(str.charAt(i))) i++;
-
- int start = i;
- while (! Character.isWhitespace(str.charAt(i))) i++;
- UnresolvedType returnTy = UnresolvedType.forName(str.substring(start, i));
-
- start = i;
- i = str.indexOf('(', i);
- i = str.lastIndexOf('.', i);
- UnresolvedType declaringTy = UnresolvedType.forName(str.substring(start, i).trim());
-
- start = ++i;
- i = str.indexOf('(', i);
- String name = str.substring(start, i).trim();
- start = ++i;
- i = str.indexOf(')', i);
-
- String[] paramTypeNames = parseIds(str.substring(start, i).trim());
-
- return method(declaringTy, mods, returnTy, name, UnresolvedType.forNames(paramTypeNames));
- }
-
- private static String[] parseIds(String str) {
- if (str.length() == 0) return ZERO_STRINGS;
- List l = new ArrayList();
- int start = 0;
- while (true) {
- int i = str.indexOf(',', start);
- if (i == -1) {
- l.add(str.substring(start).trim());
- break;
- }
- l.add(str.substring(start, i).trim());
- start = i+1;
- }
- return (String[]) l.toArray(new String[l.size()]);
- }
-
- private static final String[] ZERO_STRINGS = new String[0];
// ---- things we know without resolution
return buf.toString();
}
+ // Overridden by subclasses - a method can be advice
+ public MemberKind getKind() {
+ return kind;
+ }
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#toLongString()
- */
- public String toLongString() {
- StringBuffer buf = new StringBuffer();
- buf.append(kind);
- buf.append(' ');
- if (modifiers != 0) {
- buf.append(Modifier.toString(modifiers));
- buf.append(' ');
- }
- buf.append(toString());
- buf.append(" <");
- buf.append(signature);
- buf.append(" >");
- return buf.toString();
- }
-
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getKind()
- */
- public Kind getKind() { return kind; }
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getDeclaringType()
- */
public UnresolvedType getDeclaringType() { return declaringType; }
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getReturnType()
- */
+
public UnresolvedType getReturnType() { return returnType; }
public UnresolvedType getGenericReturnType() { return getReturnType(); }
public UnresolvedType[] getGenericParameterTypes() { return getParameterTypes(); }
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getType()
- */
- public UnresolvedType getType() { return returnType; }
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getName()
- */
- public String getName() { return name; }
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getParameterTypes()
- */
+
+ public UnresolvedType getType() {
+ return returnType;
+ }
+
+ public String getName() {
+ return name;
+ }
+
public UnresolvedType[] getParameterTypes() { return parameterTypes; }
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getSignature()
- */
+
public String getSignature() { return signature; }
public int getArity() { return parameterTypes.length; }
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getParameterSignature()
- */
public String getParameterSignature() {
if (paramSignature != null) return paramSignature;
StringBuffer sb = new StringBuffer();
return resolved.getModifiers();
}
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getExceptions(org.aspectj.weaver.World)
- */
public UnresolvedType[] getExceptions(World world) {
ResolvedMember resolved = resolve(world);
if (resolved == null) {
}
return resolved.getExceptions();
}
-
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#isProtected(org.aspectj.weaver.World)
- */
- public final boolean isProtected(World world) {
- return Modifier.isProtected(resolve(world).getModifiers());
- }
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#isStatic(org.aspectj.weaver.World)
- */
- public final boolean isStatic(World world) {
- return Modifier.isStatic(resolve(world).getModifiers());
- }
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#isStrict(org.aspectj.weaver.World)
- */
- public final boolean isStrict(World world) {
- return Modifier.isStrict(resolve(world).getModifiers());
- }
-
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#isStatic()
- */
+
public final boolean isStatic() {
return Modifier.isStatic(modifiers);
}
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#isInterface()
- */
public final boolean isInterface() {
- return Modifier.isInterface(modifiers); // this is kinda weird
+ return Modifier.isInterface(modifiers);
}
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#isPrivate()
- */
public final boolean isPrivate() {
return Modifier.isPrivate(modifiers);
}
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#canBeParameterized()
- */
public boolean canBeParameterized() {
return false;
}
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getCallsiteModifiers()
- */
public final int getCallsiteModifiers() {
return modifiers & ~ Modifier.INTERFACE;
}
return modifiers;
}
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getExtractableName()
- */
public final String getExtractableName() {
- if (name.equals("<init>")) return "init$";
- else if (name.equals("<clinit>")) return "clinit$";
+ if (kind==CONSTRUCTOR/*name.equals("<init>")*/) return "init$";
+ else if (kind==STATIC_INITIALIZATION/*name.equals("<clinit>")*/) return "clinit$";
else return name;
}
-
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#hasAnnotation(org.aspectj.weaver.UnresolvedType)
- */
- public boolean hasAnnotation(UnresolvedType ofType) {
- throw new UnsupportedOperationException("You should resolve this member and call hasAnnotation() on the result...");
- }
-
- /* (non-Javadoc)
- * @see org.aspectj.weaver.AnnotatedElement#getAnnotationTypes()
- */
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getAnnotationTypes()
- */
- public ResolvedType[] getAnnotationTypes() {
- throw new UnsupportedOperationException("You should resolve this member and call hasAnnotation() on the result...");
- }
-
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getAnnotations()
- */
- public AnnotationX[] getAnnotations() {
- throw new UnsupportedOperationException("You should resolve this member '"+this+"' and call getAnnotations() on the result...");
- }
+
+// public AnnotationX[] getAnnotations() {
+// throw new UnsupportedOperationException("You should resolve this member '"+this+"' and call getAnnotations() on the result...");
+// }
// ---- fields 'n' stuff
-
- /* (non-Javadoc)
- * @see org.aspectj.weaver.Member#getDeclaringTypes(org.aspectj.weaver.World)
- */
public Collection/*ResolvedType*/ getDeclaringTypes(World world) {
ResolvedType myType = getDeclaringType().resolve(world);
Collection ret = new HashSet();
* @see org.aspectj.weaver.Member#getSignatureMakerName()
*/
public String getSignatureMakerName() {
- if (getName().equals("<clinit>")) return "makeInitializerSig";
+// if (getName().equals("<clinit>")) return "makeInitializerSig";
- Kind kind = getKind();
+ MemberKind kind = getKind();
if (kind == METHOD) {
return "makeMethodSig";
} else if (kind == CONSTRUCTOR) {
* @see org.aspectj.weaver.Member#getSignatureType()
*/
public String getSignatureType() {
- Kind kind = getKind();
- if (getName().equals("<clinit>")) return "org.aspectj.lang.reflect.InitializerSignature";
+ MemberKind kind = getKind();
+// if (getName().equals("<clinit>")) return "org.aspectj.lang.reflect.InitializerSignature";
if (kind == METHOD) {
return "org.aspectj.lang.reflect.MethodSignature";
*/
public String getSignatureString(World world) {
if (getName().equals("<clinit>")) return getStaticInitializationSignatureString(world);
-
- Kind kind = getKind();
+//
+ MemberKind kind = getKind();
if (kind == METHOD) {
return getMethodSignatureString(world);
} else if (kind == CONSTRUCTOR) {
}
protected String makeString(int i) {
- return Integer.toString(i, 16); //??? expensive
+ return Integer.toString(i, 16);
}
}
}
- public Member slimline() {
- return this;
- }
-
}
--- /dev/null
+/* *******************************************************************
+ * 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.DataInputStream;
+import java.io.IOException;
+
+import org.aspectj.util.TypeSafeEnum;
+
+public class MemberKind extends TypeSafeEnum {
+ public MemberKind(String name, int key) { super(name, key); }
+
+ public static MemberKind read(DataInputStream s) throws IOException {
+ int key = s.readByte();
+ switch(key) {
+ case 1: return Member.METHOD;
+ case 2: return Member.FIELD;
+ case 3: return Member.CONSTRUCTOR;
+ case 4: return Member.STATIC_INITIALIZATION;
+ case 5: return Member.POINTCUT;
+ case 6: return Member.ADVICE;
+ case 7: return Member.HANDLER;
+ case 8: return Member.MONITORENTER;
+ case 9: return Member.MONITOREXIT;
+ }
+ throw new BCException("weird kind " + key);
+ }
+}
\ No newline at end of file
}
public static String itdAtDeclareParentsField(UnresolvedType aspectType, UnresolvedType itdType) {
- return makeName(aspectType.getNameAsIdentifier(), itdType.getNameAsIdentifier());
+ return makeName("instance",aspectType.getNameAsIdentifier(), itdType.getNameAsIdentifier());
}
public static String privilegedAccessMethodForMethod(String name, UnresolvedType objectType, UnresolvedType aspectType) {
return enclosingType.getName() + "$AjcClosure" + index;
}
- public static String aroundCallbackMethodName(
- Member shadowSig,
- LazyClassGen enclosingType)
- {
- String ret =
- shadowSig.getExtractableName()
- + "_aroundBody"
- + enclosingType.getNewGeneratedNameTag();
- return ret;
+ public static String aroundCallbackMethodName(Member shadowSig, LazyClassGen enclosingType) {
+ StringBuffer ret = new StringBuffer();
+ ret.append(shadowSig.getExtractableName()).append("_aroundBody").append(enclosingType.getNewGeneratedNameTag());
+// String ret =
+// shadowSig.getExtractableName()
+// + "_aroundBody"
+// + enclosingType.getNewGeneratedNameTag();
+ return ret.toString();
}
public static String proceedMethodName(String adviceMethodName) {
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.aspectj.bridge.ISourceLocation;
return nftm;
}
+ public ResolvedTypeMunger parameterizeWith(Map m, World w) {
+ ResolvedMember parameterizedSignature = getSignature().parameterizedWith(m,w);
+ NewFieldTypeMunger nftm = new NewFieldTypeMunger(parameterizedSignature,getSuperMethodsCalled(),typeVariableAliases);
+ nftm.setDeclaredSignature(getSignature());
+ nftm.setSourceLocation(getSourceLocation());
+ return nftm;
+ }
+
public boolean equals(Object other) {
if (! (other instanceof NewFieldTypeMunger)) return false;
NewFieldTypeMunger o = (NewFieldTypeMunger) other;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.aspectj.bridge.ISourceLocation;
public class NewMethodTypeMunger extends ResolvedTypeMunger {
+
+
public NewMethodTypeMunger(
ResolvedMember signature,
Set superMethodsCalled,
result = 37*result + ((typeVariableAliases == null) ? 0 : typeVariableAliases.hashCode());
return result;
}
-
+
+ public ResolvedTypeMunger parameterizeWith(Map m, World w) {
+ ResolvedMember parameterizedSignature = getSignature().parameterizedWith(m,w);
+ NewMethodTypeMunger nmtm = new NewMethodTypeMunger(parameterizedSignature,getSuperMethodsCalled(),typeVariableAliases);
+ nmtm.setDeclaredSignature(getSignature());
+ nmtm.setSourceLocation(getSourceLocation());
+ return nmtm;
+ }
+
}
ResolvedMember[] parameterizedPointcuts = null;
ResolvedType[] parameterizedInterfaces = null;
Collection parameterizedDeclares = null;
+ Collection parameterizedTypeMungers = null;
//??? should set delegate before any use
public ReferenceType(String signature, World world) {
typeKind=TypeKind.GENERIC;
}
- public final boolean isClass() {
+ public boolean isClass() {
return delegate.isClass();
}
- public final boolean isGenericType() {
+ public boolean isGenericType() {
return !isParameterizedType() && !isRawType() && delegate.isGeneric();
}
public void addAnnotation(AnnotationX annotationX) {
delegate.addAnnotation(annotationX);
}
+
public boolean hasAnnotation(UnresolvedType ofType) {
return delegate.hasAnnotation(ofType);
}
}
// true iff the statement "this = (ThisType) other" would compile
- public final boolean isCoerceableFrom(ResolvedType o) {
+ public boolean isCoerceableFrom(ResolvedType o) {
ResolvedType other = o.resolve(world);
if (this.isAssignableFrom(other) || other.isAssignableFrom(this)) {
return false;
}
- public final boolean isAssignableFrom(ResolvedType other) {
+ public boolean isAssignableFrom(ResolvedType other) {
return isAssignableFrom(other,false);
}
// true iff the statement "this = other" would compile.
- public final boolean isAssignableFrom(ResolvedType other,boolean allowMissing) {
+ public boolean isAssignableFrom(ResolvedType other,boolean allowMissing) {
if (other.isPrimitiveType()) {
if (!world.isInJava5Mode()) return false;
if (ResolvedType.validBoxing.contains(this.getSignature()+other.getSignature())) return true;
return declares;
}
- protected Collection getTypeMungers() { return delegate.getTypeMungers(); }
+ protected Collection getTypeMungers() {
+ return delegate.getTypeMungers();
+ }
+ // GENERICITDFIX
+//// Map parameterizationMap = getAjMemberParameterizationMap();
+//
+// // if (parameterizedTypeMungers != null) return parameterizedTypeMungers;
+// Collection ret = null;
+// if (ajMembersNeedParameterization()) {
+// Collection genericDeclares = delegate.getTypeMungers();
+// parameterizedTypeMungers = new ArrayList();
+// Map parameterizationMap = getAjMemberParameterizationMap();
+// for (Iterator iter = genericDeclares.iterator(); iter.hasNext();) {
+// ConcreteTypeMunger munger = (ConcreteTypeMunger)iter.next();
+// parameterizedTypeMungers.add(munger.parameterizeWith(parameterizationMap,world));
+// }
+// ret = parameterizedTypeMungers;
+// } else {
+// ret = delegate.getTypeMungers();
+// }
+// return ret;
+// }
protected Collection getPrivilegedAccesses() { return delegate.getPrivilegedAccesses(); }
import org.aspectj.weaver.patterns.PerClause;
/**
- * Abstraction over a type. Abstract implementation provided by
- * AbstractReferenceTypeDelegate.
+ * Abstraction over a type - a reference type is Object and a descendant of Object, other types (int/etc) are
+ * considered primitive types. Abstract implementation provided by AbstractReferenceTypeDelegate.
*/
public interface ReferenceTypeDelegate {
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
+import java.util.Map;
import org.aspectj.bridge.ISourceLocation;
public ShadowMunger getAssociatedShadowMunger();
+ public AnnotationX[][] getParameterAnnotations();
+ public ResolvedType[][] getParameterAnnotationTypes();
+
+ public String getAnnotationDefaultValue();
+
+ public AnnotationX[] getAnnotations();
+
+ /**
+ * Returns true iff the member is generic (NOT parameterized)
+ * For example, a method declared in a generic type
+ */
+ public boolean canBeParameterized();
+
// ??? true or false?
public boolean isAjSynthetic();
public boolean matches(ResolvedMember aCandidateMatch);
public void resetName(String newName);
- public void resetKind(Kind newKind);
+ public void resetKind(MemberKind newKind);
public void resetModifiers(int newModifiers);
public void resetReturnTypeToObjectArray();
public void evictWeavingState();
+
+ public ResolvedMember parameterizedWith(Map m, World w);
}
\ No newline at end of file
public static boolean showParameterNames = true;
private String[] parameterNames = null;
- protected UnresolvedType[] checkedExceptions = UnresolvedType.NONE;
+ protected UnresolvedType[] checkedExceptions = UnresolvedType.NONE; // OPTIMIZE unpack on demand
// private boolean isAjSynthetic = false;
protected int start, end;
protected ISourceContext sourceContext = null;
// protected ResolvedMember backingGenericMember = null;
protected Set annotationTypes = null;
+ protected ResolvedType[][] parameterAnnotationTypes = null;
+
// Some members are 'created' to represent other things (for example ITDs). These
// members have their annotations stored elsewhere, and this flag indicates that is
// the case. It is up to the caller to work out where that is!
//XXX deprecate this in favor of the constructor below
public ResolvedMemberImpl(
- Kind kind,
+ MemberKind kind,
UnresolvedType declaringType,
int modifiers,
UnresolvedType returnType,
public ResolvedMemberImpl(
- Kind kind,
+ MemberKind kind,
UnresolvedType declaringType,
int modifiers,
UnresolvedType returnType,
}
public ResolvedMemberImpl(
- Kind kind,
+ MemberKind kind,
UnresolvedType declaringType,
int modifiers,
UnresolvedType returnType,
}
public ResolvedMemberImpl(
- Kind kind,
+ MemberKind kind,
UnresolvedType declaringType,
int modifiers,
String name,
if (annotationTypes == null) return null;
return (ResolvedType[])annotationTypes.toArray(new ResolvedType[]{});
}
+
+ public AnnotationX getAnnotationOfType(UnresolvedType ofType) {
+ throw new UnsupportedOperationException("You should resolve this member and call getAnnotationOfType() on the result...");
+ }
public AnnotationX[] getAnnotations() {
if ((bits&HAS_BACKING_GENERIC_MEMBER)!=0 && metaInfo.backingGenericMember!=null) return metaInfo.backingGenericMember.getAnnotations();
// if (backingGenericMember != null) return backingGenericMember.getAnnotations();
- return super.getAnnotations();
+// return super.getAnnotations();
+ throw new IllegalStateException("Unable to answer getAnnotations() for "+this.toString());
}
public void setAnnotationTypes(UnresolvedType[] annotationtypes) {
}
}
+ public ResolvedType[][] getParameterAnnotationTypes() {
+ if (parameterAnnotationTypes == null) return null;
+ return parameterAnnotationTypes;
+ }
+
+ public AnnotationX[][] getParameterAnnotations() {
+ if (hasBackingGenericMember()) return getBackingGenericMember().getParameterAnnotations();
+ throw new IllegalStateException("Only a resolvedmember with backing generic member can answer this. Member="+toString());
+ }
+
public void addAnnotation(AnnotationX annotation) {
// FIXME asc only allows for annotation types, not instances - should it?
if (annotationTypes == null) annotationTypes = new HashSet();
public static ResolvedMemberImpl readResolvedMember(VersionedDataInputStream s, ISourceContext sourceContext) throws IOException {
- ResolvedMemberImpl m = new ResolvedMemberImpl(Kind.read(s), UnresolvedType.read(s), s.readInt(),
+ ResolvedMemberImpl m = new ResolvedMemberImpl(MemberKind.read(s), UnresolvedType.read(s), s.readInt(),
s.readUTF(), s.readUTF());
m.checkedExceptions = UnresolvedType.readArray(s);
return ret;
}
+
+ /**
+ * Replace occurrences of type variables in the signature with values contained in the map. The map is of the form A=String,B=Integer and
+ * so a signature List<A> Foo.m(B i) {} would become List<String> Foo.m(Integer i) {}
+ */
+ public ResolvedMember parameterizedWith(Map m, World w) {
+// if (//isParameterized && <-- might need this bit...
+// !getDeclaringType().isGenericType()) {
+// throw new IllegalStateException("Can't ask to parameterize a member of non-generic type: "+getDeclaringType()+" kind("+getDeclaringType().typeKind+")");
+// }
+ declaringType = declaringType.resolve(w);
+ if (declaringType.isRawType()) declaringType = ((ResolvedType)declaringType).getGenericType();
+ TypeVariable[] typeVariables = getDeclaringType().getTypeVariables();
+// if (isParameterized && (typeVariables.length != typeParameters.length)) {
+// throw new IllegalStateException("Wrong number of type parameters supplied");
+// }
+// Map typeMap = new HashMap();
+// boolean typeParametersSupplied = typeParameters!=null && typeParameters.length>0;
+// if (typeVariables!=null) {
+// // If no 'replacements' were supplied in the typeParameters array then collapse
+// // type variables to their first bound.
+// for (int i = 0; i < typeVariables.length; i++) {
+// UnresolvedType ut = (!typeParametersSupplied?typeVariables[i].getFirstBound():typeParameters[i]);
+// typeMap.put(typeVariables[i].getName(),ut);
+// }
+// }
+// // For ITDs on generic types that use type variables from the target type, the aliases
+// // record the alternative names used throughout the ITD expression that must map to
+// // the same value as the type variables real name.
+// if (aliases!=null) {
+// int posn = 0;
+// for (Iterator iter = aliases.iterator(); iter.hasNext();) {
+// String typeVariableAlias = (String) iter.next();
+// typeMap.put(typeVariableAlias,(!typeParametersSupplied?typeVariables[posn].getFirstBound():typeParameters[posn]));
+// posn++;
+// }
+// }
+
+ UnresolvedType parameterizedReturnType = parameterize(getGenericReturnType(),m,true,w);
+ UnresolvedType[] parameterizedParameterTypes = new UnresolvedType[getGenericParameterTypes().length];
+ UnresolvedType[] genericParameterTypes = getGenericParameterTypes();
+ for (int i = 0; i < parameterizedParameterTypes.length; i++) {
+ parameterizedParameterTypes[i] =
+ parameterize(genericParameterTypes[i], m,true,w);
+ }
+ ResolvedMemberImpl ret = new ResolvedMemberImpl(
+ getKind(),
+ declaringType,
+ getModifiers(),
+ parameterizedReturnType,
+ getName(),
+ parameterizedParameterTypes,
+ getExceptions(),
+ this
+ );
+ ret.setTypeVariables(getTypeVariables());
+ ret.setSourceContext(getSourceContext());
+ ret.setPosition(getStart(),getEnd());
+ ret.setParameterNames(getParameterNames());
+ return ret;
+ }
+
public void setTypeVariables(TypeVariable[] tvars) {
typeVariables = tvars;
}
}
protected UnresolvedType parameterize(UnresolvedType aType, Map typeVariableMap, boolean inParameterizedType) {
+ return parameterize(aType,typeVariableMap,inParameterizedType,null);
+ }
+
+ protected UnresolvedType parameterize(UnresolvedType aType, Map typeVariableMap, boolean inParameterizedType,World w) {
if (aType instanceof TypeVariableReference) {
String variableName = ((TypeVariableReference)aType).getTypeVariable().getName();
if (!typeVariableMap.containsKey(variableName)) {
return (UnresolvedType) typeVariableMap.get(variableName);
} else if (aType.isParameterizedType()) {
if (inParameterizedType) {
- if (aType instanceof UnresolvedType) aType= aType.resolve(((ResolvedType)getDeclaringType()).getWorld());
+// if (!(getDeclaringType() instanceof ResolvedType)) {
+// int stop = 1;
+// }
+ if (aType instanceof UnresolvedType) {
+ if (w!=null) aType = aType.resolve(w);
+ else {
+ aType= aType.resolve(((ResolvedType)getDeclaringType()).getWorld());
+ }
+ }
return aType.parameterize(typeVariableMap);
} else {
return aType.getRawType();
* using this method - this is safe.
*/
public void resetName(String newName) {this.name = newName;}
- public void resetKind(Kind newKind) {this.kind=newKind; }
+ public void resetKind(MemberKind newKind) {this.kind=newKind; }
public void resetModifiers(int newModifiers) {this.modifiers=newModifiers;}
public void resetReturnTypeToObjectArray() {
StringBuffer sig = new StringBuffer();
UnresolvedType[] myParameterTypes = getGenericParameterTypes();
for (int i = 0; i < myParameterTypes.length; i++) {
- appendSigWithTypeVarBoundsRemoved(myParameterTypes[i], sig);
+ appendSigWithTypeVarBoundsRemoved(myParameterTypes[i], sig, new HashSet());
}
myParameterSignatureWithBoundsRemoved = sig.toString();
return myParameterSignatureWithBoundsRemoved;
// does NOT produce a meaningful java signature, but does give a unique string suitable for
// comparison.
- private void appendSigWithTypeVarBoundsRemoved(UnresolvedType aType, StringBuffer toBuffer) {
+ public static void appendSigWithTypeVarBoundsRemoved(UnresolvedType aType, StringBuffer toBuffer, Set alreadyUsedTypeVars) {
if (aType.isTypeVariableReference()) {
- toBuffer.append("T;");
+ // pr204505
+ if (alreadyUsedTypeVars.contains(aType)) {
+ toBuffer.append("...");
+ } else {
+ alreadyUsedTypeVars.add(aType);
+ appendSigWithTypeVarBoundsRemoved(aType.getUpperBound(), toBuffer, alreadyUsedTypeVars);
+ }
+// toBuffer.append("T;");
} else if (aType.isParameterizedType()) {
toBuffer.append(aType.getRawType().getSignature());
toBuffer.append("<");
for (int i = 0; i < aType.getTypeParameters().length; i++) {
- appendSigWithTypeVarBoundsRemoved(aType.getTypeParameters()[i], toBuffer);
+ appendSigWithTypeVarBoundsRemoved(aType.getTypeParameters()[i], toBuffer, alreadyUsedTypeVars);
}
toBuffer.append(">;");
} else {
}
public void evictWeavingState() { }
+
+ public String getAnnotationDefaultValue() {
+ throw new UnsupportedOperationException("You should resolve this member and call getAnnotationDefaultValue() on the result...");
+ }
}
public static final ResolvedType[] EMPTY_RESOLVED_TYPE_ARRAY = new ResolvedType[0];
public static final String PARAMETERIZED_TYPE_IDENTIFIER = "P";
+ // Set during a type pattern match call - this currently used to hold the annotations
+ // that may be attached to a type when it used as a parameter
+ public ResolvedType[] temporaryAnnotationTypes;
private ResolvedType[] resolvedTypeParams;
private String binaryPath;
return EMPTY_RESOLVED_TYPE_ARRAY;
}
+ public AnnotationX getAnnotationOfType(UnresolvedType ofType) {
+ return null;
+ }
+
public final UnresolvedType getSuperclass(World world) {
return getSuperclass();
}
boolean shouldSkip = false;
for (int j = 0; j < rtx.interTypeMungers.size(); j++) {
ConcreteTypeMunger munger = (ConcreteTypeMunger) rtx.interTypeMungers.get(j);
- if (munger.getMunger()!=null && munger.getMunger().getKind() == ResolvedTypeMunger.Parent) {
+ if (munger.getMunger()!=null && munger.getMunger().getKind() == ResolvedTypeMunger.Parent
+ && ((NewParentTypeMunger)munger.getMunger()).getNewParent().equals(iface) // pr171953
+ ) {
shouldSkip = true;
break;
}
crosscuttingMembers = new CrosscuttingMembers(this,shouldConcretizeIfNeeded);
crosscuttingMembers.setPerClause(getPerClause());
crosscuttingMembers.addShadowMungers(collectShadowMungers());
- crosscuttingMembers.addTypeMungers(getTypeMungers());
+ // GENERICITDFIX
+// crosscuttingMembers.addTypeMungers(collectTypeMungers());
+ crosscuttingMembers.addTypeMungers(getTypeMungers());
//FIXME AV - skip but needed ?? or ?? crosscuttingMembers.addLateTypeMungers(getLateTypeMungers());
crosscuttingMembers.addDeclares(collectDeclares(!this.doesNotExposeShadowMungers()));
crosscuttingMembers.addPrivilegedAccesses(getPrivilegedAccesses());
return crosscuttingMembers;
}
+ public final Collection collectTypeMungers() {
+ if (! this.isAspect() ) return Collections.EMPTY_LIST;
+
+ ArrayList ret = new ArrayList();
+ //if (this.isAbstract()) {
+// for (Iterator i = getDeclares().iterator(); i.hasNext();) {
+// Declare dec = (Declare) i.next();
+// if (!dec.isAdviceLike()) ret.add(dec);
+// }
+//
+// if (!includeAdviceLike) return ret;
+
+ if (!this.isAbstract()) {
+ final Iterators.Filter dupFilter = Iterators.dupFilter();
+ Iterators.Getter typeGetter = new Iterators.Getter() {
+ public Iterator get(Object o) {
+ return
+ dupFilter.filter(
+ ((ResolvedType)o).getDirectSupertypes());
+ }
+ };
+ Iterator typeIterator = Iterators.recur(this, typeGetter);
+
+ while (typeIterator.hasNext()) {
+ ResolvedType ty = (ResolvedType) typeIterator.next();
+ for (Iterator i = ty.getTypeMungers().iterator(); i.hasNext();) {
+ ConcreteTypeMunger dec = (ConcreteTypeMunger) i.next();
+ ret.add(dec);
+ }
+ }
+ }
+
+ return ret;
+ }
+
public final Collection collectDeclares(boolean includeAdviceLike) {
if (! this.isAspect() ) return Collections.EMPTY_LIST;
// ---- types
public static ResolvedType makeArray(ResolvedType type, int dim) {
if (dim == 0) return type;
- ResolvedType array = new Array("[" + type.getSignature(),"["+type.getErasureSignature(),type.getWorld(),type);
+ ResolvedType array = new ArrayReferenceType("[" + type.getSignature(),"["+type.getErasureSignature(),type.getWorld(),type);
return makeArray(array,dim-1);
}
protected void collectInterTypeMungers(List collector) {
for (Iterator iter = getDirectSupertypes(); iter.hasNext();) {
ResolvedType superType = (ResolvedType) iter.next();
+ if (superType == null) {
+ throw new BCException("UnexpectedProblem: a supertype in the hierarchy for " + this.getName() + " is null");
+ }
superType.collectInterTypeMungers(collector);
}
//??? returning too soon
private boolean compareToExistingMembers(ConcreteTypeMunger munger, Iterator existingMembers) {
ResolvedMember sig = munger.getSignature();
+
+ ResolvedType declaringAspectType = munger.getAspectType();
+// if (declaringAspectType.isRawType()) declaringAspectType = declaringAspectType.getGenericType();
+// if (declaringAspectType.isGenericType()) {
+//
+// ResolvedType genericOnType = getWorld().resolve(sig.getDeclaringType()).getGenericType();
+// ConcreteTypeMunger ctm = munger.parameterizedFor(discoverActualOccurrenceOfTypeInHierarchy(genericOnType));
+// sig = ctm.getSignature(); // possible sig change when type
+// }
+// if (munger.getMunger().hasTypeVariableAliases()) {
+// ResolvedType genericOnType =
+// getWorld().resolve(sig.getDeclaringType()).getGenericType();
+// ConcreteTypeMunger ctm =
+// munger.parameterizedFor(discoverActualOccurrenceOfTypeInHierarchy(genericOnType));
+// sig = ctm.getSignature(); // possible sig change when type parameters filled in
+// }
while (existingMembers.hasNext()) {
ResolvedMember existingMember = (ResolvedMember)existingMembers.next();
// FIXME this whole method seems very hokey - unaware of covariance/varargs/bridging - it
// could do with a rewrite !
boolean sameReturnTypes = (existingMember.getReturnType().equals(sig.getReturnType()));
- if (sameReturnTypes)
- getWorld().getMessageHandler().handleMessage(
- MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_MEMBER_CONFLICT,munger.getAspectType().getName(),
- existingMember),
- munger.getSourceLocation())
- );
+ if (sameReturnTypes) {
+ // pr206732 - if the existingMember is due to a previous application of this same ITD (which can
+ // happen if this is a binary type being brought in from the aspectpath). The 'better' fix is
+ // to recognize it is from the aspectpath at a higher level and dont do this, but that is rather
+ // more work.
+ boolean isDuplicateOfPreviousITD = false;
+ ResolvedType declaringRt = existingMember.getDeclaringType().resolve(world);
+ WeaverStateInfo wsi = declaringRt.getWeaverState();
+ if (wsi!=null) {
+ List mungersAffectingThisType = wsi.getTypeMungers(declaringRt);
+ if (mungersAffectingThisType!=null) {
+ for (Iterator iterator = mungersAffectingThisType.iterator(); iterator.hasNext() && !isDuplicateOfPreviousITD;) {
+ ConcreteTypeMunger ctMunger = (ConcreteTypeMunger) iterator.next();
+ // relatively crude check - is the ITD for the same as the existingmember and does it come from the same aspect
+ if (ctMunger.getSignature().equals(existingMember) && ctMunger.aspectType.equals(munger.getAspectType())) {
+ isDuplicateOfPreviousITD=true;
+ }
+ }
+ }
+ }
+ if (!isDuplicateOfPreviousITD) {
+ getWorld().getMessageHandler().handleMessage(
+ MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_MEMBER_CONFLICT,munger.getAspectType().getName(),
+ existingMember),
+ munger.getSourceLocation())
+ );
+ }
+ }
}
} else if (isDuplicateMemberWithinTargetType(existingMember,this,sig)) {
getWorld().getMessageHandler().handleMessage(
}
for (int i = 0; i < typeParameters.length; i++) {
- UnresolvedType aType = (ResolvedType)typeParameters[i];
+ ResolvedType aType = (ResolvedType)typeParameters[i];
if (aType.isTypeVariableReference() &&
// assume the worst - if its definetly not a type declared one, it could be anything
((TypeVariableReference)aType).getTypeVariable().getDeclaringElementKind()!=TypeVariable.TYPE) {
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.aspectj.bridge.ISourceLocation;
if (declaringType.isRawType()) throw new IllegalStateException("Use generic type, not raw type");
if (declaringType.isParameterizedType()) throw new IllegalStateException("Use generic type, not parameterized type");
}
+// boolean aChangeOccurred = false;
+//
+// UnresolvedType rt = signature.getReturnType();
+// if (rt.isParameterizedType() || rt.isGenericType()) {rt = rt.getRawType();aChangeOccurred=true;}
+// UnresolvedType[] pt = signature.getParameterTypes();
+// for (int i = 0; i < pt.length; i++) {
+// if (pt[i].isParameterizedType() || pt[i].isGenericType()) { pt[i] = pt[i].getRawType();aChangeOccurred=true;}
+// }
+// if (aChangeOccurred) {
+// this.signature = new ResolvedMemberImpl(signature.getKind(),signature.getDeclaringType(),signature.getModifiers(),rt,signature.getName(),pt,signature.getExceptions());
+// }
}
public void setSourceLocation(ISourceLocation isl) {
public boolean existsToSupportShadowMunging() {
return false;
}
+
+ public ResolvedTypeMunger parameterizeWith(Map m, World w) {
+ throw new BCException("Dont call parameterizeWith() on a type munger of this kind: "+this.getClass());
+ }
}
public abstract class Shadow {
// every Shadow has a unique id, doesn't matter if it wraps...
- private static int nextShadowID = 100; // easier to spot than zero.
+ private static int nextShadowID = 100; // easier to spot than zero. // OPTIMIZE is this a bug? static?
private final Kind kind;
private final Member signature;
return getSignature()
.getParameterTypes().length;
}
+
+ /**
+ * Return name of the argument at position 'i' at this shadow. This does not
+ * make sense for all shadows - but can be useful in the case of, for example,
+ * method-execution.
+ * @return null if it cannot be determined
+ */
+ public String getArgName(int i,World w) {
+ String [] names = getSignature().getParameterNames(w);
+ if (names==null || i>=names.length) return null;
+ return names[i];
+ }
public abstract UnresolvedType getEnclosingType();
}
public String toResolvedString(World world) {
- return getKind() + "(" + world.resolve(getSignature()).toGenericString() + ")";
+ StringBuffer sb = new StringBuffer();
+ sb.append(getKind());
+ sb.append("(");
+ Member m = getSignature();
+ if (m==null) {
+ sb.append("<<missing signature>>");
+ } else {
+ ResolvedMember rm = world.resolve(m);
+ if (rm==null) {
+ sb.append("<<unresolvableMember:").append(m).append(">>");
+ } else {
+ String genString = rm.toGenericString();
+ if (genString==null) {
+ sb.append("<<unableToGetGenericStringFor:").append(rm).append(">>");
+ } else {
+ sb.append(genString);
+ }
+
+ }
+ }
+ sb.append(")");
+ return sb.toString();
+ // was: return getKind() + "(" + world.resolve(getSignature()).toGenericString() + ")";
}
/**
* PARC initial implementation
* ******************************************************************/
-
package org.aspectj.weaver;
import java.io.File;
* which may modify state.
* Then implement is called.
*/
-
public abstract class ShadowMunger implements PartialOrder.PartialComparable, IHasPosition {
- protected Pointcut pointcut;
-
+
+ protected Pointcut pointcut;
// these three fields hold the source location of this munger
protected int start, end;
protected ISourceContext sourceContext;
this.end = end;
this.sourceContext = sourceContext;
}
+
public abstract ShadowMunger concretize(ResolvedType fromType, World world, PerClause clause);
// (see pr122458) It is possible for a parameterized type to have *no* type parameters visible in its signature.
// This happens for an inner type of a parameterized type which simply inherits the type parameters
// of its parent. In this case it is parameterized but theres no < in the signature.
-
int startOfParams = signature.indexOf('<');
+
if (startOfParams==-1) {
// Should be an inner type of a parameterized type - could assert there is a '$' in the signature....
String signatureErasure = "L" + signature.substring(1);
// the type parameters of interest are only those that apply to the 'last type' in the signature
// if the signature is 'PMyInterface<String>$MyOtherType;' then there are none...
String lastType = null;
- int nestedTypePosition = signature.indexOf("$");
+ int nestedTypePosition = signature.indexOf("$", endOfParams); // don't look for $ INSIDE the parameters
if (nestedTypePosition!=-1) lastType = signature.substring(nestedTypePosition+1);
else lastType = new String(signature);
startOfParams = lastType.indexOf("<");
if (startOfParams!=-1) {
typeParams = createTypeParams(lastType.substring(startOfParams +1, endOfParams));
}
-
return new UnresolvedType(signature,signatureErasure,typeParams);
}
// can't replace above with convertSigToType - leads to stackoverflow
public UnresolvedType parameterize(Map typeBindings) {
UnresolvedType ut = (UnresolvedType) typeBindings.get(getName());
- if (ut!=null) return ut;
+ if (ut!=null) return world.resolve(ut);
return this;
}
/**
* A UnresolvedType represents a type to the weaver. It has a basic signature that knows
- * nothing about type variables, type parameters, etc.. TypeXs are resolved in some World
+ * nothing about type variables, type parameters, etc.. UnresolvedTypes are resolved in some World
* (a repository of types). When a UnresolvedType is resolved it turns into a
* ResolvedType which may be a primitive type, an array type or a ReferenceType.
* ReferenceTypes may refer to simple, generic, parameterized or type-variable
// this doesn't belong here and will get moved to ResolvedType later in the refactoring
public static final String MISSING_NAME = "@missing@";
-
-
+ // OPTIMIZE I dont think you can ask something unresolved what kind of type it is, how can it always know? Push down into resolvedtype
+ // that will force references to resolvedtypes to be correct rather than relying on unresolvedtypes to answer questions
protected TypeKind typeKind = TypeKind.SIMPLE; // what kind of type am I?
/**
* that are type variable references are replaced by their matching type variable
* binding.
*/
+ // OPTIMIZE methods like this just allow callers to be lazy and not ensure they are working with the right (resolved) subtype
public UnresolvedType parameterize(Map typeBindings) {
throw new UnsupportedOperationException("unable to parameterize unresolved type: " + signature);
}
* @param name the java language type name in question.
* @return a type object representing that java language type.
*/
+ // OPTIMIZE change users of this to use forSignature, especially for simple cases
public static UnresolvedType forName(String name) {
return forSignature(nameToSignature(name));
}
/**
* Returns the name of this type in java language form (e.g. java.lang.Thread or boolean[]).
- * This produces a more esthetically pleasing string than {@link java.lang.Class#getName()}.
+ * This produces a more aesthetically pleasing string than {@link java.lang.Class#getName()}.
*
* @return the java language name of this type.
*/
// ---- helpers
- public static String signatureToName(String signature) {
+ private static String signatureToName(String signature) {
switch (signature.charAt(0)) {
case 'B': return "byte";
case 'C': return "char";
}
public UnresolvedType[] getTypeParameters() {
- return typeParameters == null ? new UnresolvedType[0] : typeParameters;
+ return typeParameters == null ? UnresolvedType.NONE : typeParameters;
}
/**
* from a generic method/ctor rather than a type variable from a generic type.
* Only subclasses know the answer...
*/
+ // OPTIMIZE don't allow this to be called, the caller must have a resolved entity
public boolean isParameterizedWithAMemberTypeVariable() {
throw new RuntimeException("I dont know - you should ask a resolved version of me: "+this);
}
public static final String INCORRECT_TARGET_FOR_DECLARE_ANNOTATION = "incorrectTargetForDeclareAnnotation";
public static final String NO_MATCH_BECAUSE_SOURCE_RETENTION = "noMatchBecauseSourceRetention";
+ // Annotation Value messages
+ public static final String INVALID_ANNOTATION_VALUE = "invalidAnnotationValue";
+ public static final String UNKNOWN_ANNOTATION_VALUE = "unknownAnnotationValue";
+
// < Java5 messages
public static final String ATANNOTATION_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "atannotationNeedsJava5";
public static final String ATWITHIN_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "atwithinNeedsJava5";
+++ /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 Eclipse Public License v1.0
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Andy Clement initial implementation
- * ******************************************************************/
-package org.aspectj.weaver;
-
-import org.aspectj.util.FuzzyBoolean;
-
-
-/**
- * Records stats about the weaver. Information like 'how many types are dismissed during fast match' that
- * may be useful for trying to tune pointcuts. Not publicised.
- */
-public class WeaverMetrics {
-
- // Level 1 of matching is at the type level, which types can be dismissed?
- public static int fastMatchOnTypeAttempted = 0;
- public static int fastMatchOnTypeTrue = 0;
- public static int fastMatchOnTypeFalse = 0;
-
- // Level 2 of matching is fast matching on the shadows in the remaining types
- public static int fastMatchOnShadowsAttempted = 0;
- public static int fastMatchOnShadowsTrue = 0;
- public static int fastMatchOnShadowsFalse = 0;
-
- // Level 3 of matching is slow matching on the shadows (more shadows than were fast matched on!)
- public static int matchTrue = 0;
- public static int matchAttempted = 0;
-
-
-
- public static void reset() {
-
- fastMatchOnShadowsAttempted = 0;
- fastMatchOnShadowsTrue = 0;
- fastMatchOnShadowsFalse = 0;
-
- fastMatchOnTypeAttempted = 0;
- fastMatchOnTypeTrue = 0;
- fastMatchOnTypeFalse = 0;
-
- matchTrue = 0;
- matchAttempted = 0;
- }
-
-
- public static void dumpInfo() {
- System.err.println("Match summary:");
- int fastMatchOnTypeMaybe = (fastMatchOnTypeAttempted-fastMatchOnTypeTrue-fastMatchOnTypeFalse);
- System.err.print("At the type level, we attempted #"+fastMatchOnTypeAttempted+" fast matches:");
- System.err.println(" YES/NO/MAYBE = "+fastMatchOnTypeTrue+"/"+fastMatchOnTypeFalse+"/"+fastMatchOnTypeMaybe);
- int fastMatchMaybe = (fastMatchOnShadowsAttempted-fastMatchOnShadowsFalse-fastMatchOnShadowsTrue);
- System.err.print("Within those #"+(fastMatchOnTypeTrue+fastMatchOnTypeMaybe)+" possible types, ");
- System.err.print("we fast matched on #"+fastMatchOnShadowsAttempted+" shadows:");
- System.err.println(" YES/NO/MAYBE = "+fastMatchOnShadowsTrue+"/"+fastMatchOnShadowsFalse+"/"+fastMatchMaybe);
- System.err.println("Shadow (non-fast) matches attempted #"+matchAttempted+" of which "+matchTrue+" successful");
- }
-
-
- public static void recordFastMatchTypeResult(FuzzyBoolean fb) {
- fastMatchOnTypeAttempted++;
- if (fb.alwaysTrue()) fastMatchOnTypeTrue++;
- if (fb.alwaysFalse()) fastMatchOnTypeFalse++;
- }
-
- public static void recordFastMatchResult(FuzzyBoolean fb) {
- fastMatchOnShadowsAttempted++;
- if (fb.alwaysTrue()) fastMatchOnShadowsTrue++;
- if (fb.alwaysFalse()) fastMatchOnShadowsFalse++;
- }
-
- public static void recordMatchResult(boolean b) {
- matchAttempted++;
- if (b) matchTrue++;
- }
-
-}
readAnyReweavableData(wsi,s);
return wsi;
}
- throw new RuntimeException("bad WeaverState.Kind: " + b);
+ throw new RuntimeException("bad WeaverState.Kind: " + b+". File was :"+(context==null?"unknown":context.makeSourceLocation(0,0).toString()));
}
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
+import java.util.AbstractMap;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.WeakHashMap;
import org.aspectj.asm.IHierarchy;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.weaver.patterns.PerClause;
import org.aspectj.weaver.patterns.Pointcut;
import org.aspectj.weaver.reflect.ReflectionBasedReferenceTypeDelegate;
+import org.aspectj.weaver.tools.PointcutDesignatorHandler;
import org.aspectj.weaver.tools.Trace;
import org.aspectj.weaver.tools.TraceFactory;
-import java.util.*;
/**
* A World is a collection of known types and crosscutting members.
/** The heart of the world, a map from type signatures to resolved types */
protected TypeMap typeMap = new TypeMap(this); // Signature to ResolvedType
+ /** New pointcut designators this world supports */
+ private Set pointcutDesignators;
+
// see pr145963
/** Should we create the hierarchy for binary classes and aspects*/
public static boolean createInjarHierarchy = true;
private boolean runMinimalMemory = false;
private boolean shouldPipelineCompilation = true;
protected boolean bcelRepositoryCaching = xsetBCEL_REPOSITORY_CACHING_DEFAULT.equalsIgnoreCase("true");
+ private boolean goforit = false; // TODO better name
private boolean completeBinaryTypes = false;
public boolean forDEBUG_structuralChangesCode = false;
public boolean forDEBUG_bridgingCode = false;
if (ty.isArray()) {
ResolvedType componentType = resolve(ty.getComponentType(),allowMissing);
//String brackets = signature.substring(0,signature.lastIndexOf("[")+1);
- ret = new ResolvedType.Array(signature, "["+componentType.getErasureSignature(),
+ ret = new ArrayReferenceType(signature, "["+componentType.getErasureSignature(),
this,
componentType);
} else {
public Properties getExtraConfiguration() {
return extraConfiguration;
}
+ public final static String xsetWEAVE_JAVA_PACKAGES = "weaveJavaPackages"; // default false - controls LTW
+ public final static String xsetWEAVE_JAVAX_PACKAGES = "weaveJavaxPackages"; // default false - controls LTW
public final static String xsetCAPTURE_ALL_CONTEXT = "captureAllContext"; // default false
public final static String xsetACTIVATE_LIGHTWEIGHT_DELEGATES = "activateLightweightDelegates"; // default true
public final static String xsetRUN_MINIMAL_MEMORY ="runMinimalMemory"; // default true
public final static String xsetCOMPLETE_BINARY_TYPES = "completeBinaryTypes";
public final static String xsetCOMPLETE_BINARY_TYPES_DEFAULT = "false";
public final static String xsetBCEL_REPOSITORY_CACHING_DEFAULT = "true";
+ public final static String xsetGO_FOR_IT = "goforit";
public boolean isInJava5Mode() {
return behaveInJava5Way;
public boolean isJoinpointArrayConstructionEnabled() {
return optionalJoinpoint_ArrayConstruction;
}
-
public boolean isJoinpointSynchronizationEnabled() {
return optionalJoinpoint_Synchronization;
}
private Map /* String -> ResolvedType */ tMap = new HashMap();
// Map of types that may be ejected from the cache if we need space
- private Map expendableMap = new SoftHashMap();
+ private Map expendableMap = Collections.synchronizedMap(new WeakHashMap());//new SoftHashMap();
public static class SoftHashMap extends AbstractMap {
private Map map;
String key = (String) iter.next();
ResolvedType type = (ResolvedType)tMap.get(key);
if (type==null) continue;//throw new RuntimeException("Unexpected!! "+key);
- if (type.isAspect() ) continue;
+ if (type.isAspect() || (type.getSuperclass()!=null && type.getSuperclass().isAspect())) continue;
if (type.equals(UnresolvedType.OBJECT)) continue;
if (type.isPrimitiveType()) continue;
List typeMungers = type.getInterTypeMungers();
if (typeMungers==null || typeMungers.size()==0) {
// demote - we can recover this
tMap.remove(key);
+
+ // didnt achieve anything...
+// // force the data out of memory - this may not happen if a bcel object type was loaded for
+// // something not necessarily being woven as that will never go through the lifecycle states
+// ReferenceTypeDelegate delly = ((ReferenceType)type).getDelegate();
+// if (delly instanceof BcelObjectType) {
+// ((BcelObjectType)delly).weavingCompleted();
+// // that shouldnt be weavingCompleted, but it will do for now...
+// }
// extreme demotion if you dont use these next two lines!
-// if (memoryProfiling) expendableMap.put(key,new SoftReference(type,rq));
-// else expendableMap.put(key,new SoftReference(type));
+ if (policy==USE_WEAK_REFS) {
+ if (memoryProfiling) expendableMap.put(key,new WeakReference(type,rq));
+ else expendableMap.put(key,new WeakReference(type));
+ } else if (policy==USE_SOFT_REFS) {
+ if (memoryProfiling) expendableMap.put(key,new SoftReference(type,rq));
+ else expendableMap.put(key,new SoftReference(type));
+ } else {
+ expendableMap.put(key,type);
+ }
count++;
}
}
public int hardSize() {
return tMap.size();
}
- }
-
+ }
+
public void demote() {
typeMap.demote();
- }
+ }
/** Reference types we don't intend to weave may be ejected from
* the cache if we need the space.
(!type.isPrimitiveType())
);
}
-
/**
* This class is used to compute and store precedence relationships between
if (!bcelRepositoryCaching) {
getMessageHandler().handleMessage(MessageUtil.info("[bcelRepositoryCaching=false] AspectJ will not use a bcel cache for class information"));
}
+
+ s = p.getProperty(xsetGO_FOR_IT,"false");
+ goforit = s.equalsIgnoreCase("true");
+
s = p.getProperty(xsetPIPELINE_COMPILATION,xsetPIPELINE_COMPILATION_DEFAULT);
shouldPipelineCompilation = s.equalsIgnoreCase("true");
ensureAdvancedConfigurationProcessed();
return runMinimalMemory;
}
+
+ public boolean shouldGoForIt() {
+ ensureAdvancedConfigurationProcessed();
+ return goforit;
+ }
public boolean shouldPipelineCompilation() {
ensureAdvancedConfigurationProcessed();
public boolean isASMAround() {
return isASMAround;
}
+//
+// public ResolvedType[] getAllTypes() {
+// return typeMap.getAllTypes();
+// }
+
+ /**
+ * Register a new pointcut designator handler with the world - this can be used by any pointcut parsers attached
+ * to the world.
+ *
+ * @param designatorHandler handler for the new pointcut
+ */
+ public void registerPointcutHandler(PointcutDesignatorHandler designatorHandler) {
+ if (pointcutDesignators == null) pointcutDesignators = new HashSet();
+ pointcutDesignators.add(designatorHandler);
+ }
+
+ public Set getRegisteredPointcutHandlers() {
+ if (pointcutDesignators == null) return Collections.EMPTY_SET;
+ return pointcutDesignators;
+ }
+
}
\ No newline at end of file
unorderedAdviceAtShadow=ignore
swallowedExceptionInCatchBlock=ignore
calculatingSerialVersionUID=ignore
-advisingSynchronizedMethods=warning
\ No newline at end of file
+advisingSynchronizedMethods=warning
+mustWeaveXmlDefinedAspects=warning
\ No newline at end of file
public class Not extends Test {
- Test body;
+ Test test;
- public Not(Test left) {
+ public Not(Test test) {
super();
- this.body = left;
+ this.test = test;
}
public void accept(ITestVisitor v) {
}
public Test getBody() {
- return body;
+ return test;
}
public String toString() {
- return "!" + body;
+ return "!" + test;
}
public boolean equals(Object other) {
if (other instanceof Not) {
Not o = (Not) other;
- return o.body.equals(body);
+ return o.test.equals(test);
} else {
return false;
}
import org.aspectj.weaver.ResolvedType;
-
public class Var extends Expr {
- ResolvedType type;
+ ResolvedType variableType;
- public Var(ResolvedType type) {
+ public Var(ResolvedType variableType) {
super();
- this.type = type;
+ this.variableType = variableType;
}
public ResolvedType getType() {
- return type;
+ return variableType;
}
public String toString() {
- return "(Var " + type + ")";
+ return "(Var " + variableType + ")";
}
public void accept(IExprVisitor v) {
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2005-2008 Contributors
+ * 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:
+ * Andy Clement initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver.bcel;
+
+import org.aspectj.apache.bcel.Constants;
+import org.aspectj.apache.bcel.generic.Instruction;
+import org.aspectj.apache.bcel.generic.InstructionConstants;
+import org.aspectj.apache.bcel.generic.InstructionFactory;
+import org.aspectj.apache.bcel.generic.InstructionList;
+import org.aspectj.apache.bcel.generic.ObjectType;
+import org.aspectj.apache.bcel.generic.Type;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.Shadow.Kind;
+
+/**
+ * Represents access to an annotation on an element, relating to some kinded pointcut.
+ * Depending on the kind of pointcut the element might be a field or a method and the code
+ * generators in here can retrieve the annotation from the element.
+ */
+public class AnnotationAccessVar extends BcelVar {
+
+ private Kind kind; // What kind of shadow are we at?
+ private UnresolvedType containingType; // The type upon which we want to ask for 'member'
+ private Member member; // Holds the member that has the annotations (for method/field join points)
+
+ public AnnotationAccessVar(Kind kind, ResolvedType annotationType, UnresolvedType theTargetIsStoredHere, Member sig) {
+ super(annotationType,0);
+ this.kind = kind;
+ this.containingType = theTargetIsStoredHere;
+ this.member = sig;
+ }
+
+ public String toString() {
+ return "AnnotationAccessVar(" + getType() +")";
+ }
+
+ public Instruction createLoad(InstructionFactory fact) {
+ throw new IllegalStateException("unimplemented");
+ }
+ public Instruction createStore(InstructionFactory fact) {
+ throw new IllegalStateException("unimplemented");
+ }
+
+ public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) {
+ throw new IllegalStateException("unimplemented");
+ }
+
+ public void appendLoad(InstructionList il, InstructionFactory fact) {
+ il.append(createLoadInstructions(getType(), fact));
+ }
+
+ public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) {
+ il.append(createLoadInstructions(toType, fact));
+ }
+
+ public void insertLoad(InstructionList il, InstructionFactory fact) {
+ il.insert(createLoadInstructions(getType(), fact));
+ }
+
+ private InstructionList createLoadInstructions(ResolvedType toType, InstructionFactory fact) {
+
+ InstructionList il = new InstructionList();
+
+ Type jlClass = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_CLASS);
+ Type jlString = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.String;"));
+ Type jlClassArray = BcelWorld.makeBcelType(UnresolvedType.forSignature("[Ljava.lang.Class;"));
+ Type jlaAnnotation = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.annotation.Annotation;"));
+
+ Instruction pushConstant = fact.createConstant(new ObjectType(toType.getName()));
+
+ if (kind==Shadow.MethodCall || kind==Shadow.MethodExecution ||
+ kind==Shadow.PreInitialization || kind==Shadow.Initialization ||
+ kind==Shadow.ConstructorCall || kind==Shadow.ConstructorExecution ||
+ kind==Shadow.AdviceExecution ||
+ // annotations for fieldset/fieldget when an ITD is involved are stored against a METHOD
+ ((kind==Shadow.FieldGet || kind==Shadow.FieldSet) && member.getKind()==Member.METHOD)) {
+
+ Type jlrMethod = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.reflect.Method;"));
+ Type[] paramTypes = BcelWorld.makeBcelTypes(member.getParameterTypes());
+
+ il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));
+
+ if (kind==Shadow.MethodCall || kind==Shadow.MethodExecution || kind==Shadow.AdviceExecution ||
+ // annotations for fieldset/fieldget when an ITD is involved are stored against a METHOD
+ ((kind==Shadow.FieldGet || kind==Shadow.FieldSet) && member.getKind()==Member.METHOD) ||
+ ((kind==Shadow.ConstructorCall || kind==Shadow.ConstructorExecution) && member.getKind()==Member.METHOD)) {
+
+ il.append(fact.createConstant(member.getName()));
+ buildArray(il,fact,jlClass,paramTypes,1);
+ // OPTIMIZE cache result of getDeclaredMethod and getAnnotation? Might be able to use it again if someone else needs the same annotations?
+ il.append(fact.createInvoke("java/lang/Class","getDeclaredMethod",jlrMethod,new Type[]{jlString,jlClassArray},Constants.INVOKEVIRTUAL));
+ il.append(pushConstant);//fact.createConstant(new ObjectType(toType.getName())));
+ il.append(fact.createInvoke("java/lang/reflect/Method","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL));
+ } else { // init/preinit/ctor-call/ctor-exec
+ buildArray(il,fact,jlClass,paramTypes,1);
+ Type jlrCtor = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.reflect.Constructor;"));
+ // OPTIMIZE cache result of getDeclaredConstructor and getAnnotation? Might be able to use it again if someone else needs the same annotations?
+ il.append(fact.createInvoke("java/lang/Class","getDeclaredConstructor",jlrCtor,new Type[]{jlClassArray},Constants.INVOKEVIRTUAL));
+ il.append(pushConstant);
+ il.append(fact.createInvoke("java/lang/reflect/Constructor","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL));
+ }
+ } else if (kind == Shadow.FieldSet || kind == Shadow.FieldGet) {
+ Type jlrField = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.reflect.Field;"));
+ il.append(fact.createConstant(BcelWorld.makeBcelType(containingType))); // Stick the target on the stack
+ il.append(fact.createConstant(member.getName())); // Stick what we are after on the stack
+ il.append(fact.createInvoke("java/lang/Class","getDeclaredField",jlrField,new Type[]{jlString},Constants.INVOKEVIRTUAL));
+ il.append(pushConstant);
+ il.append(fact.createInvoke("java/lang/reflect/Field","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL));
+ } else if (kind == Shadow.StaticInitialization || kind==Shadow.ExceptionHandler) {
+ il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));
+ il.append(pushConstant);
+ il.append(fact.createInvoke("java/lang/Class","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL));
+ } else {
+ throw new RuntimeException("Don't understand this kind "+kind);
+ }
+ il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType)));
+ return il;
+ }
+
+
+ private void buildArray(InstructionList il, InstructionFactory fact, Type arrayElementType, Type[] arrayEntries,int dim) {
+ il.append(fact.createConstant(Integer.valueOf(arrayEntries==null?0:arrayEntries.length)));
+ il.append(fact.createNewArray(arrayElementType,(short)dim));
+ if (arrayEntries == null) return;
+ for (int i = 0; i < arrayEntries.length; i++) {
+ il.append(InstructionFactory.createDup(1));
+ il.append(fact.createConstant(Integer.valueOf(i)));
+ switch (arrayEntries[i].getType()) {
+ case Constants.T_ARRAY:
+ il.append(fact.createConstant(new ObjectType(arrayEntries[i].getSignature())));
+ break;
+ case Constants.T_BOOLEAN: il.append(fact.createGetStatic("java/lang/Boolean","TYPE",arrayElementType)); break;
+ case Constants.T_BYTE:il.append(fact.createGetStatic("java/lang/Byte","TYPE",arrayElementType)); break;
+ case Constants.T_CHAR:il.append(fact.createGetStatic("java/lang/Character","TYPE",arrayElementType)); break;
+ case Constants.T_INT:il.append(fact.createGetStatic("java/lang/Integer","TYPE",arrayElementType)); break;
+ case Constants.T_LONG:il.append(fact.createGetStatic("java/lang/Long","TYPE",arrayElementType)); break;
+ case Constants.T_DOUBLE:il.append(fact.createGetStatic("java/lang/Double","TYPE",arrayElementType)); break;
+ case Constants.T_FLOAT:il.append(fact.createGetStatic("java/lang/Float","TYPE",arrayElementType)); break;
+ case Constants.T_SHORT:il.append(fact.createGetStatic("java/lang/Short","TYPE",arrayElementType)); break;
+ default:
+ il.append(fact.createConstant(arrayEntries[i]));
+ }
+ il.append(InstructionConstants.AASTORE);
+ }
+ }
+
+}
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+import java.util.StringTokenizer;
import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.weaver.patterns.TypePattern;
/**
- * Annotation defined aspect reader.
- * <p/>
- * It reads the Java 5 annotations and turns them into AjAttributes
+ * Annotation defined aspect reader. Reads the Java 5 annotations and turns them into AjAttributes
*
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
private final static List EMPTY_LIST = new ArrayList();
private final static String[] EMPTY_STRINGS = new String[0];
private final static String VALUE = "value";
+ private final static String ARGNAMES = "argNames";
private final static String POINTCUT = "pointcut";
private final static String THROWING = "throwing";
private final static String RETURNING = "returning";
/**
* A struct that allows to add extra arguments without always breaking the API
- *
- * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
private static class AjAttributeStruct {
*/
private static class AjAttributeMethodStruct extends AjAttributeStruct {
- /**
- * Argument names as they appear in the SOURCE code, ordered, and lazyly populated
- * Used to do formal binding
- */
+ // argument names used for formal binding
private String[] m_argumentNamesLazy = null;
+ public String unparsedArgumentNames = null; // Set only if discovered as argNames attribute of annotation
final Method method;
final BcelMethod bMethod;
public String[] getArgumentNames() {
if (m_argumentNamesLazy == null) {
- m_argumentNamesLazy = getMethodArgumentNamesAsInSource(method);
+ m_argumentNamesLazy = getMethodArgumentNames(method,unparsedArgumentNames,this);
}
return m_argumentNamesLazy;
}
/**
* A struct when we read @AJ on field
- *
- * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
private static class AjAttributeFieldStruct extends AjAttributeStruct {
* @return list of AjAttributes
*/
public static List readAj5ClassAttributes(JavaClass javaClass, ReferenceType type, ISourceContext context, IMessageHandler msgHandler, boolean isCodeStyleAspect) {
- //FIXME AV - 1.5 feature limitation, kick after implemented
- try {
- Constant[] cpool = javaClass.getConstantPool().getConstantPool();
- for (int i = 0; i < cpool.length; i++) {
- Constant constant = cpool[i];
- if (constant != null && constant.getTag() == Constants.CONSTANT_Utf8) {
- if (!javaClass.getClassName().startsWith("org.aspectj.lang.annotation")) {
- ConstantUtf8 constantUtf8 = (ConstantUtf8) constant;
- if ("Lorg/aspectj/lang/annotation/DeclareAnnotation;".equals(constantUtf8.getBytes())) {
+ boolean ignoreThisClass = javaClass.getClassName().charAt(0)=='o' && javaClass.getClassName().startsWith("org.aspectj.lang.annotation");
+ if (ignoreThisClass) return EMPTY_LIST;
+ boolean containsPointcut = false;
+ boolean containsAnnotationClassReference = false;
+ Constant[] cpool = javaClass.getConstantPool().getConstantPool();
+ for (int i = 0; i < cpool.length; i++) {
+ Constant constant = cpool[i];
+ if (constant != null && constant.getTag() == Constants.CONSTANT_Utf8) {
+ String constantValue = ((ConstantUtf8)constant).getBytes();
+ if (constantValue.length()>28 && constantValue.charAt(1)=='o') {
+ if (constantValue.startsWith("Lorg/aspectj/lang/annotation")) {
+ containsAnnotationClassReference=true;
+ if ("Lorg/aspectj/lang/annotation/DeclareAnnotation;".equals(constantValue)) {
msgHandler.handleMessage(
new Message(
"Found @DeclareAnnotation while current release does not support it (see '" + type.getName() + "')",
)
);
}
- }
+ if ("Lorg/aspectj/lang/annotation/Pointcut;".equals(constantValue)) {
+ containsPointcut=true;
+ }
+ }
}
}
- } catch (Throwable t) {
- ;
}
-
+ if (!containsAnnotationClassReference) return EMPTY_LIST;
AjAttributeStruct struct = new AjAttributeStruct(type, context, msgHandler);
Attribute[] attributes = javaClass.getAttributes();
Attribute attribute = attributes[i];
if (acceptAttribute(attribute)) {
RuntimeAnnotations rvs = (RuntimeAnnotations) attribute;
- // we don't need to look for several attribute occurence since it cannot happen as per JSR175
+ // we don't need to look for several attribute occurrences since it cannot happen as per JSR175
if (!isCodeStyleAspect && !javaClass.isInterface()) {
hasAtAspectAnnotation = handleAspectAnnotation(rvs, struct);
//TODO AV - if put outside the if isCodeStyleAspect then we would enable mix style
}
// the following block will not detect @Pointcut in non @Aspect types for optimization purpose
- if (!hasAtAspectAnnotation) {
+ if (!hasAtAspectAnnotation && !containsPointcut) {
return EMPTY_LIST;
}
-
//FIXME AV - turn on when ajcMightHaveAspect
// if (hasAtAspectAnnotation && type.isInterface()) {
// msgHandler.handleMessage(
// we need to gather the @AJ pointcut right now and not at method level annotation extraction time
// in order to be able to resolve the pointcut references later on
// we don't need to look in super class, the pointcut reference in the grammar will do it
+
for (int i = 0; i < javaClass.getMethods().length; i++) {
Method method = javaClass.getMethods()[i];
if (method.getName().startsWith(NameMangler.PREFIX)) continue; // already dealt with by ajc...
//FIXME alex optimize, this method struct will gets recreated for advice extraction
- AjAttributeMethodStruct mstruct = new AjAttributeMethodStruct(method, null, type, context, msgHandler);//FIXME AVASM
+ AjAttributeMethodStruct mstruct = null;
+ boolean processedPointcut = false;
Attribute[] mattributes = method.getAttributes();
-
for (int j = 0; j < mattributes.length; j++) {
Attribute mattribute = mattributes[j];
if (acceptAttribute(mattribute)) {
- RuntimeAnnotations mrvs = (RuntimeAnnotations) mattribute;
- handlePointcutAnnotation(mrvs, mstruct);
+ if (mstruct==null) mstruct = new AjAttributeMethodStruct(method, null, type, context, msgHandler);//FIXME AVASM
+ processedPointcut = handlePointcutAnnotation((RuntimeAnnotations) mattribute, mstruct);
// there can only be one RuntimeVisible bytecode attribute
break;
}
}
- // FIXME asc should check we aren't adding multiple versions... will do once I get the tests passing again...
- struct.ajAttributes.add(new AjAttribute.WeaverVersionInfo());
- struct.ajAttributes.addAll(mstruct.ajAttributes);
+ if (processedPointcut) {
+ // FIXME asc should check we aren't adding multiple versions... will do once I get the tests passing again...
+ struct.ajAttributes.add(new AjAttribute.WeaverVersionInfo());
+ struct.ajAttributes.addAll(mstruct.ajAttributes);
+ }
}
// code style declare error / warning / implements / parents are field attributes
- for (int i = 0; i < javaClass.getFields().length; i++) {
- Field field = javaClass.getFields()[i];
+ Field[] fs = javaClass.getFields();
+ for (int i = 0; i < fs.length; i++) {
+ Field field = fs[i];
if (field.getName().startsWith(NameMangler.PREFIX)) continue; // already dealt with by ajc...
//FIXME alex optimize, this method struct will gets recreated for advice extraction
AjAttributeFieldStruct fstruct = new AjAttributeFieldStruct(field, null, type, context, msgHandler);
for (int i = 0; i < methods.length; i++) {
ResolvedMember method = (ResolvedMember)methods[i];
if (method.isAbstract()) {
- if (defaultImplClassName == null) {
- // non marker interface with no default impl provided
- reportError("@DeclareParents: used with a non marker interface and no defaultImpl=\"...\" provided", struct);
- return false;
- }
+ // moved to be detected at weave time if the target doesnt implement the methods
+// if (defaultImplClassName == null) {
+// // non marker interface with no default impl provided
+// reportError("@DeclareParents: used with a non marker interface and no defaultImpl=\"...\" provided", struct);
+// return false;
+// }
hasAtLeastOneMethod = true;
-
- struct.ajAttributes.add(
- new AjAttribute.TypeMunger(
- new MethodDelegateTypeMunger(
- method,
- struct.enclosingType,
- defaultImplClassName,
- typePattern
- )
- )
- );
+ MethodDelegateTypeMunger mdtm =
+ new MethodDelegateTypeMunger(
+ method,
+ struct.enclosingType,
+ defaultImplClassName,
+ typePattern
+ );
+ mdtm.setSourceLocation(struct.enclosingType.getSourceLocation());
+ struct.ajAttributes.add(new AjAttribute.TypeMunger(mdtm));
}
}
// successfull so far, we thus need a bcel type munger to have
// a field hosting the mixin in the target type
- if (hasAtLeastOneMethod) {
+ if (hasAtLeastOneMethod && defaultImplClassName!=null) {
struct.ajAttributes.add(
new AjAttribute.TypeMunger(
new MethodDelegateTypeMunger.FieldHostTypeMunger(
ElementNameValuePairGen beforeAdvice = getAnnotationElement(before, VALUE);
if (beforeAdvice != null) {
// this/target/args binding
+ String argumentNames = getArgNamesValue(before);
+ if (argumentNames!=null) {
+ struct.unparsedArgumentNames = argumentNames;
+ }
FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
try {
bindings = extractBindings(struct);
if (afterAdvice != null) {
// this/target/args binding
FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
+ String argumentNames = getArgNamesValue(after);
+ if (argumentNames!=null) {
+ struct.unparsedArgumentNames = argumentNames;
+ }
try {
bindings = extractBindings(struct);
} catch (UnreadableDebugInfoException unreadableDebugInfoException) {
}
}
}
-
+ String argumentNames = getArgNamesValue(after);
+ if (argumentNames!=null) {
+ struct.unparsedArgumentNames = argumentNames;
+ }
// this/target/args binding
// exclude the return binding from the pointcut binding since it is an extraArg binding
FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
}
}
}
-
+ String argumentNames = getArgNamesValue(after);
+ if (argumentNames!=null) {
+ struct.unparsedArgumentNames = argumentNames;
+ }
// this/target/args binding
// exclude the throwned binding from the pointcut binding since it is an extraArg binding
FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
if (around != null) {
ElementNameValuePairGen aroundAdvice = getAnnotationElement(around, VALUE);
if (aroundAdvice != null) {
- // this/target/args binding
+ // this/target/args binding
+ String argumentNames = getArgNamesValue(around);
+ if (argumentNames!=null) {
+ struct.unparsedArgumentNames = argumentNames;
+ }
FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
try {
bindings = extractBindings(struct);
*
* @param runtimeAnnotations
* @param struct
+ * @return true if a pointcut was handled
*/
- private static void handlePointcutAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct) {
+ private static boolean handlePointcutAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct) {
AnnotationGen pointcut = getAnnotation(runtimeAnnotations, AjcMemberMaker.POINTCUT_ANNOTATION);
- if (pointcut != null) {
- ElementNameValuePairGen pointcutExpr = getAnnotationElement(pointcut, VALUE);
-
- // semantic check: the method must return void, or be "public static boolean" for if() support
- if (!(Type.VOID.equals(struct.method.getReturnType())
- || (Type.BOOLEAN.equals(struct.method.getReturnType()) && struct.method.isStatic() && struct.method.isPublic()))) {
- reportWarning("Found @Pointcut on a method not returning 'void' or not 'public static boolean'", struct);
- ;//no need to stop
- }
+ if (pointcut==null) return false;
+ ElementNameValuePairGen pointcutExpr = getAnnotationElement(pointcut, VALUE);
- // semantic check: the method must not throw anything
- if (struct.method.getExceptionTable() != null) {
- reportWarning("Found @Pointcut on a method throwing exception", struct);
- ;// no need to stop
- }
+
+ // semantic check: the method must return void, or be "public static boolean" for if() support
+ if (!(Type.VOID.equals(struct.method.getReturnType())
+ || (Type.BOOLEAN.equals(struct.method.getReturnType()) && struct.method.isStatic() && struct.method.isPublic()))) {
+ reportWarning("Found @Pointcut on a method not returning 'void' or not 'public static boolean'", struct);
+ ;//no need to stop
+ }
- // this/target/args binding
- final IScope binding;
- try {
+ // semantic check: the method must not throw anything
+ if (struct.method.getExceptionTable() != null) {
+ reportWarning("Found @Pointcut on a method throwing exception", struct);
+ ;// no need to stop
+ }
+
+ String argumentNames = getArgNamesValue(pointcut);
+ if (argumentNames!=null) {
+ struct.unparsedArgumentNames = argumentNames;
+ }
+ // this/target/args binding
+ final IScope binding;
+ try {
+ if (struct.method.isAbstract()) {
+ binding = null;
+ } else {
binding = new BindingScope(
- struct.enclosingType,
- struct.context,
- extractBindings(struct)
+ struct.enclosingType,
+ struct.context,
+ extractBindings(struct)
);
- } catch (UnreadableDebugInfoException e) {
- return;
- }
+ }
+ } catch (UnreadableDebugInfoException e) {
+ return false;
+ }
- UnresolvedType[] argumentTypes = new UnresolvedType[struct.method.getArgumentTypes().length];
- for (int i = 0; i < argumentTypes.length; i++) {
- argumentTypes[i] = UnresolvedType.forSignature(struct.method.getArgumentTypes()[i].getSignature());
- }
+ UnresolvedType[] argumentTypes = new UnresolvedType[struct.method.getArgumentTypes().length];
+ for (int i = 0; i < argumentTypes.length; i++) {
+ argumentTypes[i] = UnresolvedType.forSignature(struct.method.getArgumentTypes()[i].getSignature());
+ }
- Pointcut pc = null;
- if (struct.method.isAbstract()) {
- if ((pointcutExpr != null && isNullOrEmpty(pointcutExpr.getValue().stringifyValue()))
- || pointcutExpr == null) {
- // abstract pointcut
- // leave pc = null
- } else {
- reportError("Found defined @Pointcut on an abstract method", struct);
- return;//stop
- }
+ Pointcut pc = null;
+ if (struct.method.isAbstract()) {
+ if ((pointcutExpr != null && isNullOrEmpty(pointcutExpr.getValue().stringifyValue()))
+ || pointcutExpr == null) {
+ // abstract pointcut
+ // leave pc = null
} else {
- if (pointcutExpr==null || (pointcutExpr != null && isNullOrEmpty(pointcutExpr.getValue().stringifyValue()))) {
- // the matches nothing pointcut (125475/125480) - perhaps not as cleanly supported as it could be.
- } else {
- if (pointcutExpr != null) {
- // use a LazyResolvedPointcutDefinition so that the pointcut is resolved lazily
- // since for it to be resolved, we will need other pointcuts to be registered as well
- pc = parsePointcut(pointcutExpr.getValue().stringifyValue(), struct, true);
- if (pc == null) return;//parse error
- pc.setLocation(struct.context, -1, -1);//FIXME AVASM !! bMethod is null here..
- } else {
- reportError("Found undefined @Pointcut on a non-abstract method", struct);
- return;
- }
- }
+ reportError("Found defined @Pointcut on an abstract method", struct);
+ return false;//stop
}
- // do not resolve binding now but lazily
- struct.ajAttributes.add(
- new AjAttribute.PointcutDeclarationAttribute(
- new LazyResolvedPointcutDefinition(
- struct.enclosingType,
- struct.method.getModifiers(),
- struct.method.getName(),
- argumentTypes,
- UnresolvedType.forSignature(struct.method.getReturnType().getSignature()),
- pc,//can be null for abstract pointcut
- binding
- )
- )
- );
+ } else {
+ if (pointcutExpr==null || (pointcutExpr != null && isNullOrEmpty(pointcutExpr.getValue().stringifyValue()))) {
+ // the matches nothing pointcut (125475/125480) - perhaps not as cleanly supported as it could be.
+ } else {
+ if (pointcutExpr != null) {
+ // use a LazyResolvedPointcutDefinition so that the pointcut is resolved lazily
+ // since for it to be resolved, we will need other pointcuts to be registered as well
+ pc = parsePointcut(pointcutExpr.getValue().stringifyValue(), struct, true);
+ if (pc == null) return false;//parse error
+ pc.setLocation(struct.context, -1, -1);//FIXME AVASM !! bMethod is null here..
+ } else {
+ reportError("Found undefined @Pointcut on a non-abstract method", struct);
+ return false;
+ }
+ }
}
+ // do not resolve binding now but lazily
+ struct.ajAttributes.add(
+ new AjAttribute.PointcutDeclarationAttribute(
+ new LazyResolvedPointcutDefinition(
+ struct.enclosingType,
+ struct.method.getModifiers(),
+ struct.method.getName(),
+ argumentTypes,
+ UnresolvedType.forSignature(struct.method.getReturnType().getSignature()),
+ pc,//can be null for abstract pointcut
+ binding // can be null for abstract pointcut
+ )
+ )
+ );
+ return true;
}
/**
}
return null;
}
+
+ /**
+ * Return the argNames set for an annotation or null if it is not specified.
+ */
+ private static String getArgNamesValue(AnnotationGen anno) {
+ for (Iterator iterator1 = anno.getValues().iterator(); iterator1.hasNext();) {
+ ElementNameValuePairGen element = (ElementNameValuePairGen) iterator1.next();
+ if (ARGNAMES.equals(element.getNameString())) {
+ return element.getValue().stringifyValue();
+ }
+ }
+ return null;
+ }
+
+ private static String lastbit(String fqname) {
+ int i = fqname.lastIndexOf(".");
+ if (i==-1) return fqname; else return fqname.substring(i+1);
+ }
/**
- * Extract the method argument names as in source from debug info
- * returns an empty array upon inconsistency
+ * Extract the method argument names. First we try the debug info attached
+ * to the method (the LocalVariableTable) - if we cannot find that we look
+ * to use the argNames value that may have been supplied on the associated
+ * annotation. If that fails we just don't know and return an empty string.
*
* @param method
- * @return method arg names as in source
+ * @param argNamesFromAnnotation
+ * @param methodStruct
+ * @return method argument names
*/
- private static String[] getMethodArgumentNamesAsInSource(Method method) {
+ private static String[] getMethodArgumentNames(Method method, String argNamesFromAnnotation, AjAttributeMethodStruct methodStruct) {
if (method.getArgumentTypes().length == 0) {
return EMPTY_STRINGS;
}
}
}
}
+ } else {
+ // No debug info, do we have an annotation value we can rely on?
+ if (argNamesFromAnnotation!=null) {
+ StringTokenizer st = new StringTokenizer(argNamesFromAnnotation," ,");
+ List args = new ArrayList();
+ while (st.hasMoreTokens()) { args.add(st.nextToken());}
+ if (args.size()!=method.getArgumentTypes().length) {
+ StringBuffer shortString = new StringBuffer().append(lastbit(method.getReturnType().toString())).append(" ").append(method.getName());
+ if (method.getArgumentTypes().length>0) {
+ shortString.append("(");
+ for (int i =0; i<method.getArgumentTypes().length;i++) {
+ shortString.append(lastbit(method.getArgumentTypes()[i].toString()));
+ if ((i+1)<method.getArgumentTypes().length) shortString.append(",");
+
+ }
+ shortString.append(")");
+ }
+ reportError("argNames annotation value does not specify the right number of argument names for the method '"+shortString.toString()+"'",methodStruct);
+ return EMPTY_STRINGS;
+ }
+ return (String[])args.toArray(new String[]{});
+ }
}
if (arguments.size() != method.getArgumentTypes().length) {
private Pointcut m_lazyPointcut = null;
- public LazyResolvedPointcutDefinition(ResolvedType declaringType, int modifiers, String name,
+ public LazyResolvedPointcutDefinition(UnresolvedType declaringType, int modifiers, String name,
UnresolvedType[] parameterTypes, UnresolvedType returnType,
Pointcut pointcut, IScope binding) {
super(declaringType, modifiers, name, parameterTypes, returnType, null);
*******************************************************************************/
package org.aspectj.weaver.bcel;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import org.aspectj.apache.bcel.Constants;
+import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.generic.FieldInstruction;
import org.aspectj.apache.bcel.generic.Instruction;
import org.aspectj.apache.bcel.generic.InstructionConstants;
import org.aspectj.apache.bcel.generic.InstructionHandle;
import org.aspectj.apache.bcel.generic.InstructionList;
import org.aspectj.apache.bcel.generic.InvokeInstruction;
-import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.UnresolvedType;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.List;
+
/**
* Looks for all access to method or field that are not public within the body of the around advices and replace
* the invocations to a wrapper call so that the around advice can further be inlined.
// flag it synthetic, AjSynthetic
method.makeSynthetic();
method.addAttribute(
- BcelAttributes.bcelAttribute(new AjAttribute.AjSynthetic(), m_aspectGen.getConstantPool())
+ Utility.bcelAttribute(new AjAttribute.AjSynthetic(), m_aspectGen.getConstantPool())
);
// flag the effective signature, so that we can deobfuscate the signature to apply method call pointcut
method.addAttribute(
- BcelAttributes.bcelAttribute(
+ Utility.bcelAttribute(
new AjAttribute.EffectiveSignatureAttribute(resolvedMember, Shadow.MethodCall, false),
m_aspectGen.getConstantPool()
)
// flag it synthetic, AjSynthetic
method.makeSynthetic();
method.addAttribute(
- BcelAttributes.bcelAttribute(new AjAttribute.AjSynthetic(), m_aspectGen.getConstantPool())
+ Utility.bcelAttribute(new AjAttribute.AjSynthetic(), m_aspectGen.getConstantPool())
);
// flag the effective signature, so that we can deobfuscate the signature to apply method call pointcut
method.addAttribute(
- BcelAttributes.bcelAttribute(
+ Utility.bcelAttribute(
new AjAttribute.EffectiveSignatureAttribute(resolvedMember, Shadow.MethodCall, false),
m_aspectGen.getConstantPool()
)
// flag it synthetic, AjSynthetic
method.makeSynthetic();
method.addAttribute(
- BcelAttributes.bcelAttribute(new AjAttribute.AjSynthetic(), m_aspectGen.getConstantPool())
+ Utility.bcelAttribute(new AjAttribute.AjSynthetic(), m_aspectGen.getConstantPool())
);
// flag the effective signature, so that we can deobfuscate the signature to apply method call pointcut
method.addAttribute(
- BcelAttributes.bcelAttribute(
+ Utility.bcelAttribute(
new AjAttribute.EffectiveSignatureAttribute(resolvedMember, Shadow.FieldGet, false),
m_aspectGen.getConstantPool()
)
// flag it synthetic, AjSynthetic
method.makeSynthetic();
method.addAttribute(
- BcelAttributes.bcelAttribute(new AjAttribute.AjSynthetic(), m_aspectGen.getConstantPool())
+ Utility.bcelAttribute(new AjAttribute.AjSynthetic(), m_aspectGen.getConstantPool())
);
// flag the effective signature, so that we can deobfuscate the signature to apply method call pointcut
method.addAttribute(
- BcelAttributes.bcelAttribute(
+ Utility.bcelAttribute(
new AjAttribute.EffectiveSignatureAttribute(resolvedMember, Shadow.FieldSet, false),
m_aspectGen.getConstantPool()
)
Member signature,
ResolvedType concreteAspect)
{
- super(attribute, pointcut, (signature==null?null:signature.slimline()));
+ super(attribute, pointcut,shrink(attribute.getKind(),concreteAspect,signature));// (signature==null?null:signature.slimline()));
this.concreteAspect = concreteAspect;
}
-
- // !!! must only be used for testing
- public BcelAdvice(AdviceKind kind, Pointcut pointcut, Member signature,
- int extraArgumentFlags,
- int start, int end, ISourceContext sourceContext, ResolvedType concreteAspect)
- {
- this(new AjAttribute.AdviceAttribute(kind, pointcut, extraArgumentFlags, start, end, sourceContext),
- pointcut, (signature==null?null:signature.slimline()), concreteAspect);
- thrownExceptions = Collections.EMPTY_LIST; //!!! interaction with unit tests
- }
-
/**
* We don't always need to represent the signature with a heavyweight BcelMethod object - only if its around advice
* and inlining is active
}
return m;
}
+ // !!! must only be used for testing
+ public BcelAdvice(AdviceKind kind, Pointcut pointcut, Member signature,
+ int extraArgumentFlags,
+ int start, int end, ISourceContext sourceContext, ResolvedType concreteAspect)
+ {
+ this(new AjAttribute.AdviceAttribute(kind, pointcut, extraArgumentFlags, start, end, sourceContext),
+ pointcut, signature, concreteAspect);
+ thrownExceptions = Collections.EMPTY_LIST; //!!! interaction with unit tests
+ }
// ---- implementations of ShadowMunger's methods
if (concreteAspect.getWorld().isXnoInline()) return false;
//System.err.println("isWoven? " + ((BcelObjectType)concreteAspect).getLazyClassGen().getWeaverState());
- // if (BcelWorld.getBcelObjectType(concreteAspect).getJavaClass()==null) return true; // been evicted... CUSTARD
return BcelWorld.getBcelObjectType(concreteAspect).getLazyClassGen().isWoven();
}
protected void suppressLintWarnings(World inWorld) {
if (suppressedLintKinds == null) {
if (signature instanceof BcelMethod) {
- this.suppressedLintKinds = Utility.getSuppressedWarnings(signature.getAnnotations(), inWorld.getLint());
+ this.suppressedLintKinds = Utility.getSuppressedWarnings(((BcelMethod)signature).getAnnotations(), inWorld.getLint());
} else {
this.suppressedLintKinds = Collections.EMPTY_LIST;
}
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.Unknown;
-import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;
// this is a class o' static methods for reading attributes. It's pretty much a bridge from
// bcel to AjAttribute.
+// OPTIMIZE move the contents of this class to bcel Utility
class BcelAttributes {
/**
* Process an array of Bcel attributes - looking for those with the name prefix org.aspectj.weaver. The returned
* list contains the AspectJ attributes identified and unpacked to 'AjAttribute' objects.
*/
- public static List readAjAttributes(String classname,Attribute[] as, ISourceContext context,
- World w,AjAttribute.WeaverVersionInfo version) {
+// public static List readAjAttributes(String classname,List as, ISourceContext context,
+// World w, AjAttribute.WeaverVersionInfo version) {
+// List l = new ArrayList();
+//
+// // first pass, look for version
+// List forSecondPass = new ArrayList();
+// for (int i = as.size() - 1; i >= 0; i--) {
+// Attribute a = (Attribute)as.get(i);
+// if (a instanceof Unknown) {
+// Unknown u = (Unknown) a;
+// String name = u.getName();
+// if (name.charAt(0)=='o') { // 'o'rg.aspectj
+// if (name.startsWith(AjAttribute.AttributePrefix)) {
+// if (name.endsWith(WeaverVersionInfo.AttributeName)) {
+// version = (AjAttribute.WeaverVersionInfo)AjAttribute.read(version,name,u.getBytes(),context,w);
+// if (version.getMajorVersion() > WeaverVersionInfo.getCurrentWeaverMajorVersion()) {
+// throw new BCException("Unable to continue, this version of AspectJ supports classes built with weaver version "+
+// WeaverVersionInfo.toCurrentVersionString()+" but the class "+classname+" is version "+version.toString());
+// }
+// }
+// forSecondPass.add(a);
+// }
+// }
+// }
+// }
+
+// for (int i = forSecondPass.size()-1; i >= 0; i--) {
+// Unknown a = (Unknown)forSecondPass.get(i);
+// String name = a.getName();
+// AjAttribute attr = AjAttribute.read(version,name,a.getBytes(),context,w);
+// if (attr!=null) l.add(attr);
+// }
+// return l;
+// }
+ public static List readAjAttributes(String classname, Attribute[] as, ISourceContext context, World w, AjAttribute.WeaverVersionInfo version) {
List l = new ArrayList();
-
+
// first pass, look for version
List forSecondPass = new ArrayList();
for (int i = as.length - 1; i >= 0; i--) {
if (a instanceof Unknown) {
Unknown u = (Unknown) a;
String name = u.getName();
- if (name.charAt(0)=='o') { // 'o'rg.aspectj
+ if (name.charAt(0) == 'o') { // 'o'rg.aspectj
if (name.startsWith(AjAttribute.AttributePrefix)) {
if (name.endsWith(WeaverVersionInfo.AttributeName)) {
- version = (AjAttribute.WeaverVersionInfo)AjAttribute.read(version,name,u.getBytes(),context,w);
- if (version.getMajorVersion() > WeaverVersionInfo.getCurrentWeaverMajorVersion()) {
- throw new BCException("Unable to continue, this version of AspectJ supports classes built with weaver version "+
- WeaverVersionInfo.toCurrentVersionString()+" but the class "+classname+" is version "+version.toString());
+ version = (AjAttribute.WeaverVersionInfo) AjAttribute.read(version, name, u.getBytes(), context, w);
+ if (version.getMajorVersion() > WeaverVersionInfo
+ .getCurrentWeaverMajorVersion()) {
+ throw new BCException(
+ "Unable to continue, this version of AspectJ supports classes built with weaver version "
+ + WeaverVersionInfo
+ .toCurrentVersionString()
+ + " but the class "
+ + classname
+ + " is version "
+ + version.toString());
}
- }
+ }
forSecondPass.add(a);
}
}
}
}
-
- for (int i = forSecondPass.size()-1; i >= 0; i--) {
- Unknown a = (Unknown)forSecondPass.get(i);
+
+ for (int i = forSecondPass.size() - 1; i >= 0; i--) {
+ Unknown a = (Unknown) forSecondPass.get(i);
String name = a.getName();
- AjAttribute attr = AjAttribute.read(version,name,a.getBytes(),context,w);
- if (attr!=null) l.add(attr);
+ AjAttribute attr = AjAttribute.read(version, name, a.getBytes(), context, w);
+ if (attr != null) l.add(attr);
}
return l;
}
-
- public static Attribute bcelAttribute(AjAttribute a, ConstantPool pool) {
- int nameIndex = pool.addUtf8(a.getNameString());
- byte[] bytes = a.getBytes();
- int length = bytes.length;
-
- return new Unknown(nameIndex, length, bytes, pool);
-
- }
-
}
\ No newline at end of file
return true;
}
+ public String toString() {
+ return "(BcelTypeMunger: CflowField "+cflowCounterField.getDeclaringType().getName()+" "+cflowCounterField.getName()+")";
+ }
+
}
import org.aspectj.weaver.ShadowMunger;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.WeaverMessages;
-import org.aspectj.weaver.WeaverMetrics;
import org.aspectj.weaver.WeaverStateInfo;
import org.aspectj.weaver.World;
import org.aspectj.weaver.patterns.DeclareAnnotation;
import org.aspectj.weaver.tools.Trace;
import org.aspectj.weaver.tools.TraceFactory;
-import com.sun.org.apache.bcel.internal.generic.BranchInstruction;
-import com.sun.org.apache.bcel.internal.generic.GOTO;
-import com.sun.org.apache.bcel.internal.generic.GOTO_W;
class BcelClassWeaver implements IClassWeaver {
if (annotationsToAdd==null) annotationsToAdd = new ArrayList();
AnnotationGen a = decaM.getAnnotationX().getBcelAnnotation();
- AnnotationGen ag = new AnnotationGen(a,clazz.getConstantPool(),true);
- annotationsToAdd.add(ag);
+ //CUSTARD superfluous?
+ //AnnotationGen ag = new AnnotationGen(a,clazz.getConstantPool(),true);
+ annotationsToAdd.add(a);
mg.addAnnotation(decaM.getAnnotationX());
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaM.getSourceLocation(),clazz.getName(),mg.getMethod());
while (!worthRetrying.isEmpty() && modificationOccured) {
modificationOccured = false;
List forRemoval = new ArrayList();
- for (Iterator iter2 = worthRetrying.iterator(); iter.hasNext();) {
+ for (Iterator iter2 = worthRetrying.iterator(); iter2.hasNext();) {
DeclareAnnotation decaF = (DeclareAnnotation) iter2.next();
if (decaF.matches(itdIsActually,world)) {
LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz,fieldMunger);
while (!worthRetrying.isEmpty() && modificationOccured) {
modificationOccured = false;
List forRemoval = new ArrayList();
- for (Iterator iter2 = worthRetrying.iterator(); iter.hasNext();) {
+ for (Iterator iter2 = worthRetrying.iterator(); iter2.hasNext();) {
DeclareAnnotation decaMC = (DeclareAnnotation) iter2.next();
if (decaMC.matches(unMangledInterMethod,world)) {
LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz,methodctorMunger);
return isChanged;
}
- private boolean dontAddTwice(DeclareAnnotation decaF, AnnotationX[] dontAddMeTwice){
+ private boolean dontAddTwice(DeclareAnnotation decaF, AnnotationX [] dontAddMeTwice){
for (int i = 0; i < dontAddMeTwice.length; i++){
AnnotationX ann = dontAddMeTwice[i];
if (ann != null && decaF.getAnnotationX().getTypeName().equals(ann.getTypeName())){
}
}
- AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),aBcelField.getName());
+ AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),aBcelField.getFieldAsIs());
reportFieldAnnotationWeavingMessage(clazz, fields, fieldCounter, decaF);
isChanged = true;
modificationOccured = true;
continue; // skip this one...
}
aBcelField.addAnnotation(decaF.getAnnotationX());
- AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),aBcelField.getName());
+ AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),aBcelField.getFieldAsIs());
isChanged = true;
modificationOccured = true;
forRemoval.add(decaF);
reportedProblems.add(uniqueID);
reportedProblems.add(new Integer(itdfieldsig.hashCode()*deca.hashCode()));
world.getLint().elementAlreadyAnnotated.signal(
- new String[]{rm.toString(),deca.getAnnotationTypeX().toString()},
+ new String[]{itdfieldsig.toString(),deca.getAnnotationTypeX().toString()},
rm.getSourceLocation(),new ISourceLocation[]{deca.getSourceLocation()});
}
}
// ignore
} else if (targeter instanceof LineNumberTag) {
// ignore
- } else if (targeter instanceof InstructionBranch && ((InstructionBranch)targeter).isGoto()) {
- // move it...
- targeter.updateTarget(element, monitorExitBlockStart);
- } else if (targeter instanceof BranchInstruction) {
+// } else if (targeter instanceof InstructionBranch && ((InstructionBranch)targeter).isGoto()) {
+// // move it...
+// targeter.updateTarget(element, monitorExitBlockStart);
+ } else if (targeter instanceof InstructionBranch) {
// move it
targeter.updateTarget(element, monitorExitBlockStart);
} else {
// ignore
} else if (targeter instanceof LineNumberTag) {
// ignore
- } else if (targeter instanceof GOTO || targeter instanceof GOTO_W) {
- // move it...
- targeter.updateTarget(element, monitorExitBlockStart);
- } else if (targeter instanceof BranchInstruction) {
+// } else if (targeter instanceof GOTO || targeter instanceof GOTO_W) {
+// // move it...
+// targeter.updateTarget(element, monitorExitBlockStart);
+ } else if (targeter instanceof InstructionBranch) {
// move it
targeter.updateTarget(element, monitorExitBlockStart);
} else {
// ignore
} else if (targeter instanceof LineNumberTag) {
// ignore
- } else if (targeter instanceof InstructionBranch && ((InstructionBranch)targeter).isGoto()) {
- // move it...
- targeter.updateTarget(element, monitorExitBlockStart);
+// } else if (targeter instanceof GOTO || targeter instanceof GOTO_W) {
+// // move it...
+// targeter.updateTarget(element, monitorExitBlockStart);
} else if (targeter instanceof InstructionBranch) {
// move it
targeter.updateTarget(element, monitorExitBlockStart);
{
Instruction fresh = Utility.copyInstruction(src.getInstruction());
InstructionHandle dest;
+
+ // OPTIMIZE optimize this stuff?
if (fresh.isConstantPoolInstruction()) {
// need to reset index to go to new constant pool. This is totally
// a computation leak... we're testing this LOTS of times. Sigh.
// sets of synthetics aren't join points in 1.1
return;
} else {
- match(
- BcelShadow.makeFieldSet(world, mg, ih, enclosingShadow),
- shadowAccumulator);
+ // Fix for bug 172107 (similar the "get" fix for bug 109728)
+ BcelShadow bs=
+ BcelShadow.makeFieldSet(world, resolvedField, mg, ih, enclosingShadow);
+ String cname = fi.getClassName(cpg);
+ if (!resolvedField.getDeclaringType().getName().equals(cname)) {
+ bs.setActualTargetType(cname);
+ }
+ match(bs, shadowAccumulator);
}
}
ShadowMunger munger = (ShadowMunger)i.next();
ContextToken mungerMatchToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.MATCHING_POINTCUT, munger.getPointcut());
if (munger.match(shadow, world)) {
- WeaverMetrics.recordMatchResult(true);// Could pass: munger
shadow.addMunger(munger);
isMatched = true;
if (shadow.getKind() == Shadow.StaticInitialization) {
clazz.warnOnAddedStaticInitializer(shadow,munger.getSourceLocation());
}
- } else {
- WeaverMetrics.recordMatchResult(false); // Could pass: munger
}
CompilationAndWeavingContext.leavingPhase(mungerMatchToken);
}
* PARC initial implementation
* ******************************************************************/
-
package org.aspectj.weaver.bcel;
import java.util.Collections;
import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException;
-
final class BcelField extends ResolvedMemberImpl {
private static int AccSynthetic = 0x1000;
super(
FIELD,
declaringType.getResolvedTypeX(),
- field.getAccessFlags(),
+ field.getModifiers(),
field.getName(),
field.getSignature());
this.field = field;
* constructed at runtime (so there is no .class file to retrieve).
*/
BcelField(String declaringTypeName, Field field,World world) {
- super(FIELD,UnresolvedType.forName(declaringTypeName),field.getAccessFlags(),field.getName(),field.getSignature());
+ super(FIELD,UnresolvedType.forName(declaringTypeName),field.getModifiers(),field.getName(),field.getSignature());
this.field = field;
this.world = world;
this.bcelObjectType = null;
ReferenceType rt = (ReferenceType) aTypeX;
TypeVariable[] typeVars = rt.getTypeVariables();
- for (int i = 0; i < typeVars.length; i++) {
- if (typeVars[i].getUpperBound() instanceof FTPHolder) {
- Signature.FormalTypeParameter key = ((FTPHolder) typeVars[i].getUpperBound()).ftpToBeSubstituted;
- typeVars[i].setUpperBound((UnresolvedType)typeVariableResolutions.get(key));
- }
+ if (typeVars != null) {
+ for (int i = 0; i < typeVars.length; i++) {
+ if (typeVars[i].getUpperBound() instanceof FTPHolder) {
+ Signature.FormalTypeParameter key = ((FTPHolder) typeVars[i].getUpperBound()).ftpToBeSubstituted;
+ typeVars[i].setUpperBound((UnresolvedType) typeVariableResolutions.get(key));
+ }
+ }
}
}
* PARC initial implementation
* ******************************************************************/
-
package org.aspectj.weaver.bcel;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
+import org.aspectj.apache.bcel.classfile.AnnotationDefault;
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ExceptionTable;
import org.aspectj.apache.bcel.classfile.GenericSignatureParser;
import org.aspectj.apache.bcel.classfile.Signature;
import org.aspectj.apache.bcel.classfile.Signature.TypeVariableSignature;
import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
+import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePairGen;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.SourceLocation;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AnnotationX;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;
-import org.aspectj.weaver.Member;
+import org.aspectj.weaver.MemberKind;
import org.aspectj.weaver.ResolvedMemberImpl;
import org.aspectj.weaver.ResolvedPointcutDefinition;
import org.aspectj.weaver.ResolvedType;
private Method method;
// private AjAttribute.MethodDeclarationLineNumberAttribute declarationLineNumber;
-// private World world;
private BcelObjectType bcelObjectType;
- public Member slimline() {
- if (!bcelObjectType.getWorld().isXnoInline()) return this;
- ResolvedMemberImpl mi = new ResolvedMemberImpl(kind,declaringType,modifiers,returnType,name,parameterTypes);
- mi.setParameterNames(getParameterNames());
- return mi;
- }
+// public Member slimline() {
+// if (!bcelObjectType.getWorld().isXnoInline()) return this;
+// ResolvedMemberImpl mi = new ResolvedMemberImpl(kind,declaringType,modifiers,returnType,name,parameterTypes);
+// mi.setParameterNames(getParameterNames());
+// return mi;
+// }
// private AnnotationX[] annotations = null;
// private UnresolvedType genericReturnType = null;
private static final String MAPKEY_GENERIC_PARAM_TYPES ="genericParameterTypes";
private static final String MAPKEY_ANNOTATIONS ="annotations";
private static final String MAPKEY_MD_LINE_NUMBER_ATTRIBUTE="mdLineNumberAttribute";
+ private AnnotationX[][] parameterAnnotations = null;
// private AjAttribute.EffectiveSignatureAttribute effectiveSignature;
// private ShadowMunger associatedShadowMunger;
(method.getName().equals("<clinit>") ? STATIC_INITIALIZATION : METHOD),
declaringType.getResolvedTypeX(),
declaringType.isInterface()
- ? method.getAccessFlags() | Modifier.INTERFACE
- : method.getAccessFlags(),
- method.getName(),
+ ? method.getModifiers() | Modifier.INTERFACE
+ : method.getModifiers(),
+ method.getName(),
method.getSignature());
this.method = method;
this.sourceContext = declaringType.getResolvedTypeX().getSourceContext();
- //this.world = declaringType.getResolvedTypeX().getWorld();
this.bcelObjectType = declaringType;
unpackJavaAttributes();
unpackAjAttributes(bcelObjectType.getWorld());
LocalVariableTable varTable = method.getLocalVariableTable();
int len = getArity();
if (varTable == null) {
+ // do we have an annotation with the argNames value specified...
+ if (hasAnnotations()) {
+ AnnotationX[] axs = getAnnotations();
+ for (int i = 0; i < axs.length; i++) {
+ AnnotationX annotationX = axs[i];
+ String typename = annotationX.getTypeName();
+ if (typename.equals("org.aspectj.lang.annotation.Pointcut") ||
+ typename.equals("org.aspectj.lang.annotation.Before") ||
+ typename.equals("org.aspectj.lang.annotation.Around") ||
+ typename.startsWith("org.aspectj.lang.annotation.After")) {
+ AnnotationGen a = annotationX.getBcelAnnotation();
+ if (a!=null) {
+ List values = a.getValues();
+ for (Iterator iterator = values.iterator(); iterator
+ .hasNext();) {
+ ElementNameValuePairGen nvPair = (ElementNameValuePairGen) iterator.next();
+ if (nvPair.getNameString().equals("argNames")) {
+ String argNames = nvPair.getValue().stringifyValue();
+ StringTokenizer argNameTokenizer = new StringTokenizer(argNames," ,");
+ List argsList = new ArrayList();
+ while (argNameTokenizer.hasMoreTokens()) {
+ argsList.add(argNameTokenizer.nextToken());
+ }
+ int requiredCount = getParameterTypes().length;
+ while (argsList.size()<requiredCount) {
+ argsList.add("arg"+argsList.size());
+ }
+ setParameterNames((String[])argsList.toArray(new String[]{}));
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
setParameterNames(Utility.makeArgNames(len));
} else {
UnresolvedType[] paramTypes = getParameterTypes();
return null;
}
+ public String getAnnotationDefaultValue() {
+ Attribute[] attrs = method.getAttributes();
+ for (int i = 0; i < attrs.length; i++) {
+ Attribute attribute = attrs[i];
+ if (attribute.getName().equals("AnnotationDefault")) {
+ AnnotationDefault def = (AnnotationDefault)attribute;
+ return def.getElementValue().stringifyValue();
+ }
+ }
+ return null;
+ }
+
// for testing - use with the method above
public String[] getAttributeNames(boolean onlyIncludeAjOnes) {
Attribute[] as = method.getAttributes();
return ret;
}
- public Kind getKind() {
+ public MemberKind getKind() {
if ((bitflags&HAS_ASSOCIATED_SHADOWMUNGER)!=0) {
return ADVICE;
} else {
}
public boolean hasAnnotation(UnresolvedType ofType) {
- ensureAnnotationTypesRetrieved();
+ ensureAnnotationsRetrieved();
for (Iterator iter = annotationTypes.iterator(); iter.hasNext();) {
ResolvedType aType = (ResolvedType) iter.next();
if (aType.equals(ofType)) return true;
}
public AnnotationX[] getAnnotations() {
- ensureAnnotationTypesRetrieved();
+ ensureAnnotationsRetrieved();
if ((bitflags&HAS_ANNOTATIONS)!=0) {
return (AnnotationX[])metaData.get(MAPKEY_ANNOTATIONS);
} else {
}
public ResolvedType[] getAnnotationTypes() {
- ensureAnnotationTypesRetrieved();
+ ensureAnnotationsRetrieved();
ResolvedType[] ret = new ResolvedType[annotationTypes.size()];
annotationTypes.toArray(ret);
return ret;
}
+ public AnnotationX getAnnotationOfType(UnresolvedType ofType) {
+ ensureAnnotationsRetrieved();
+ if ((bitflags&HAS_ANNOTATIONS)==0) return null;
+ AnnotationX[] annos = (AnnotationX[])metaData.get(MAPKEY_ANNOTATIONS);
+ for (int i=0; i<annos.length; i++) {
+ if (annos[i].getTypeName().equals(ofType.getName())) return annos[i];
+ }
+ return null;
+ }
+
public void addAnnotation(AnnotationX annotation) {
- ensureAnnotationTypesRetrieved();
+ ensureAnnotationsRetrieved();
if ((bitflags&HAS_ANNOTATIONS)==0) {
AnnotationX[] ret = new AnnotationX[1];
ret[0]=annotation;
// FIXME CUSTARD
}
- private void ensureAnnotationTypesRetrieved() {
+ private void ensureAnnotationsRetrieved() {
if (method == null) return; // must be ok, we have evicted it
if ((bitflags&HAVE_DETERMINED_ANNOTATIONS)!=0) return;
bitflags|=HAVE_DETERMINED_ANNOTATIONS;
// }
}
+ private void ensureParameterAnnotationsRetrieved() {
+ if (method == null) return; // must be ok, we have evicted it
+ AnnotationGen[][] pAnns = method.getParameterAnnotations();
+ if (parameterAnnotationTypes==null || pAnns.length!=parameterAnnotationTypes.length) {
+ if (pAnns == Method.NO_PARAMETER_ANNOTATIONS) {
+ parameterAnnotationTypes = BcelMethod.NO_PARAMETER_ANNOTATION_TYPES;
+ parameterAnnotations = BcelMethod.NO_PARAMETER_ANNOTATIONXS;
+ } else {
+ AnnotationGen annos[][] = method.getParameterAnnotations();
+ parameterAnnotations = new AnnotationX[annos.length][];
+ parameterAnnotationTypes = new ResolvedType[annos.length][];
+ for (int i=0;i<annos.length;i++) {
+ parameterAnnotations[i] = new AnnotationX[annos[i].length];
+ parameterAnnotationTypes[i] = new ResolvedType[annos[i].length];
+ for (int j=0;j<annos[i].length;j++) {
+ parameterAnnotations[i][j] = new AnnotationX(annos[i][j],bcelObjectType.getWorld());
+ parameterAnnotationTypes[i][j] = bcelObjectType.getWorld().resolve(UnresolvedType.forSignature(annos[i][j].getTypeSignature()));
+ }
+ }
+ }
+ }
+ }
+
+ public AnnotationX[][] getParameterAnnotations() {
+ ensureParameterAnnotationsRetrieved();
+ return parameterAnnotations;
+ }
+
+ public ResolvedType[][] getParameterAnnotationTypes() {
+ ensureParameterAnnotationsRetrieved();
+ return parameterAnnotationTypes;
+ }
+
/**
* A method can be parameterized if it has one or more generic
// return genericParameterTypes;
}
+ /**
+ * Return the parameterized/generic return type or the normal return type if the method is not generic.
+ */
public UnresolvedType getGenericReturnType() {
unpackGenericSignature();
if ((bitflags&HAS_GENERIC_RETPARAM_TYPES)==0) return getReturnType();
if (method != null) {
unpackGenericSignature();
unpackJavaAttributes();
- ensureAnnotationTypesRetrieved();
+ ensureAnnotationsRetrieved();
+ ensureParameterAnnotationsRetrieved();
determineParameterNames();
// this.sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT;
method = null;
o.getMethod().getCode().getCodeString());
}
-}
+}
\ No newline at end of file
import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValueGen;
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePairGen;
import org.aspectj.apache.bcel.classfile.annotation.ElementValueGen;
+import org.aspectj.apache.bcel.classfile.annotation.EnumElementValueGen;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.weaver.AbstractReferenceTypeDelegate;
import org.aspectj.weaver.AjAttribute;
// ((SourceContextImpl)sourceContext).setSourceFileName(javaClass.getSourceFileName());
// }
setSourcefilename(javaClass.getSourceFileName());
-
}
// repeat initialization
public void setJavaClass(JavaClass newclass) {
-// if (this.getResolvedTypeX().isAspect())
-// new RuntimeException("bcot: "+this.hashCode()+" Set javaclass for aspect").printStackTrace();
this.javaClass = newclass;
resetState();
initializeFromJavaclass();
isAnnotation = javaClass.isAnnotation();
isAnonymous = javaClass.isAnonymous();
isNested = javaClass.isNested();
- modifiers = javaClass.getAccessFlags();
+ modifiers = javaClass.getModifiers();
superclassName = javaClass.getSuperclassName();
className = javaClass.getClassName();
cachedGenericClassTypeSignature = null;
ResolvedType res = getResolvedTypeX().getWorld().resolve(UnresolvedType.forSignature(superclassSignature));
return res;
}
-
+
public World getWorld() {
return getResolvedTypeX().getWorld();
}
public LazyClassGen getLazyClassGen() {
LazyClassGen ret = lazyClassGen;
if (ret == null) {
-// System.err.println("creating lazy class gen for: " + this);
+ //System.err.println("creating lazy class gen for: " + this);
ret = new LazyClassGen(this);
//ret.print(System.err);
//System.err.println("made LCG from : " + this.getJavaClass().getSuperclassName );
List values = ax.getBcelAnnotation().getValues();
for (Iterator it = values.iterator(); it.hasNext();) {
ElementNameValuePairGen element = (ElementNameValuePairGen) it.next();
- ElementValueGen v = element.getValue();
- retentionPolicy = v.stringifyValue();
+ EnumElementValueGen v = (EnumElementValueGen)element.getValue();
+ retentionPolicy = v.getEnumValueString();
return retentionPolicy;
}
}
ElementValueGen[] evs = arrayValue.getElementValuesArray();
if (evs!=null) {
for (int j = 0; j < evs.length; j++) {
- String targetKind = evs[j].stringifyValue();
+ String targetKind = ((EnumElementValueGen)evs[j]).getEnumValueString();
if (targetKind.equals("ANNOTATION_TYPE")) { targetKinds.add(AnnotationTargetKind.ANNOTATION_TYPE);
} else if (targetKind.equals("CONSTRUCTOR")) { targetKinds.add(AnnotationTargetKind.CONSTRUCTOR);
} else if (targetKind.equals("FIELD")) { targetKinds.add(AnnotationTargetKind.FIELD);
public void evictWeavingState() {
// Can't chuck all this away
-// if (getResolvedTypeX().isAspect()) System.err.println("Eviction of "+getResolvedTypeX().getName());
if (getResolvedTypeX().getWorld().couldIncrementalCompileFollow()) return;
if (javaClass != null) {
weaverState.setReweavable(false);
weaverState.setUnwovenClassFileData(null);
}
-
- for (int i = methods.length - 1; i >= 0; i--) { methods[i].evictWeavingState();}
+ for (int i = methods.length - 1; i >= 0; i--) methods[i].evictWeavingState();
for (int i = fields.length - 1; i >= 0; i--) fields[i].evictWeavingState();
-// if (getResolvedTypeX().isAspect()) System.err.println("nulling jc for "+getResolvedTypeX().getName());
javaClass = null;
// setSourceContext(SourceContextImpl.UNKNOWN_SOURCE_CONTEXT); // bit naughty
// interfaces=null; // force reinit - may get us the right instances!
// superClass=null;
- // if this is a class, make sure aspects are re-evicted if necessary
-// if (!getResolvedTypeX().isAspect()) getWorld().ensureAspectsEvicted();
}
}
methodGen.makeSynthetic();
}
methodGen.addAttribute(
- BcelAttributes.bcelAttribute(
+ Utility.bcelAttribute(
new AjAttribute.AjSynthetic(),
methodGen.getEnclosingClass().getConstantPool()
)
import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.TargetLostException;
import org.aspectj.apache.bcel.generic.Type;
+import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.MessageUtil;
import org.aspectj.weaver.Advice;
import org.aspectj.weaver.AdviceKind;
import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.IntMap;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.MemberImpl;
+import org.aspectj.weaver.MemberKind;
import org.aspectj.weaver.NameMangler;
import org.aspectj.weaver.NewConstructorTypeMunger;
import org.aspectj.weaver.NewFieldTypeMunger;
private ShadowRange range;
private final BcelWorld world;
private final LazyMethodGen enclosingMethod;
-// private boolean fallsThrough; //XXX not used anymore
// SECRETAPI - for testing, this will tell us if the optimization succeeded *on the last shadow processed*
public static boolean appliedLazyTjpOptimization;
// from the signature (pr109728) (1.4 declaring type issue)
private String actualInstructionTargetType;
- // ---- initialization
-
/**
- * This generates an unassociated shadow, rooted in a particular method but not rooted
+ * This generates an unassociated shadow, rooted in a particular method but not rooted
* to any particular point in the code. It should be given to a rooted ShadowRange
* in the {@link ShadowRange#associateWithShadow(BcelShadow)} method.
*/
- public BcelShadow(
- BcelWorld world,
- Kind kind,
- Member signature,
- LazyMethodGen enclosingMethod,
- BcelShadow enclosingShadow)
- {
+ public BcelShadow(BcelWorld world, Kind kind, Member signature, LazyMethodGen enclosingMethod, BcelShadow enclosingShadow) {
super(kind, signature, enclosingShadow);
this.world = world;
this.enclosingMethod = enclosingMethod;
-// fallsThrough = kind.argsOnStack();
}
// ---- copies all state, including Shadow's mungers...
return world;
}
-
-
private void deleteNewAndDup() {
final ConstantPool cpg = getEnclosingClass().getConstantPool();
int depth = 1;
public static BcelShadow makeFieldSet(
BcelWorld world,
+ ResolvedMember field,
LazyMethodGen enclosingMethod,
InstructionHandle setHandle,
BcelShadow enclosingShadow)
new BcelShadow(
world,
FieldSet,
- BcelWorld.makeFieldJoinPointSignature(
- enclosingMethod.getEnclosingClass(),
- (FieldInstruction) setHandle.getInstruction()),
+ field,
+// BcelWorld.makeFieldJoinPointSignature(
+// enclosingMethod.getEnclosingClass(),
+// (FieldInstruction) setHandle.getInstruction()),
enclosingMethod,
enclosingShadow);
ShadowRange r = new ShadowRange(body);
}
}
- protected Member getRelevantMember(Member foundMember, Member relevantMember, ResolvedType relevantType){
+ protected ResolvedMember getRelevantMember(ResolvedMember foundMember, Member relevantMember, ResolvedType relevantType){
if (foundMember != null){
return foundMember;
}
return foundMember;
}
- protected ResolvedType [] getAnnotations(Member foundMember, Member relevantMember, ResolvedType relevantType){
+ protected ResolvedType [] getAnnotations(ResolvedMember foundMember, Member relevantMember, ResolvedType relevantType){
if (foundMember == null){
// check the ITD'd dooberries
List mungers = relevantType.resolve(world).getInterTypeMungers();
// by determining what "kind" of shadow we are, we can find out the
// annotations on the appropriate element (method, field, constructor, type).
// Then create one BcelVar entry in the map for each annotation, keyed by
- // annotation type (UnresolvedType).
+ // annotation type.
// FIXME asc Refactor this code, there is duplication
ResolvedType[] annotations = null;
- Member relevantMember = getSignature();
- ResolvedType relevantType = relevantMember.getDeclaringType().resolve(world);
- if (relevantType.isRawType() || relevantType.isParameterizedType()) relevantType = relevantType.getGenericType();
+// Member relevantMember = getSignature();
+ Member shadowSignature = getSignature();
+ Member annotationHolder = getSignature();
+ ResolvedType relevantType = shadowSignature.getDeclaringType().resolve(world);
+
+ if (relevantType.isRawType() || relevantType.isParameterizedType()) relevantType = relevantType.getGenericType();
if (getKind() == Shadow.StaticInitialization) {
annotations = relevantType.resolve(world).getAnnotationTypes();
} else if (getKind() == Shadow.MethodCall || getKind() == Shadow.ConstructorCall) {
- Member foundMember = findMethod2(relevantType.resolve(world).getDeclaredMethods(),getSignature());
- annotations = getAnnotations(foundMember, relevantMember, relevantType);
- relevantMember = getRelevantMember(foundMember,relevantMember,relevantType);
- relevantType = relevantMember.getDeclaringType().resolve(world);
+ ResolvedMember foundMember = findMethod2(relevantType.resolve(world).getDeclaredMethods(),getSignature());
+ annotations = getAnnotations(foundMember, shadowSignature, relevantType);
+ annotationHolder = getRelevantMember(foundMember,shadowSignature,relevantType);
+ relevantType = annotationHolder.getDeclaringType().resolve(world);
} else if (getKind() == Shadow.FieldSet || getKind() == Shadow.FieldGet) {
- relevantMember = findField(relevantType.getDeclaredFields(),getSignature());
+ annotationHolder = findField(relevantType.getDeclaredFields(),getSignature());
- if (relevantMember==null) {
+ if (annotationHolder==null) {
// check the ITD'd dooberries
List mungers = relevantType.resolve(world).getInterTypeMungers();
for (Iterator iter = mungers.iterator(); iter.hasNext();) {
ResolvedMember rmm = findMethod(typeMunger.getAspectType(),ajcMethod);
if (fakerm.equals(getSignature())) {
relevantType = typeMunger.getAspectType();
- relevantMember = rmm;
+ annotationHolder = rmm;
}
}
}
}
- annotations = relevantMember.getAnnotationTypes();
+ annotations = ((ResolvedMember)annotationHolder).getAnnotationTypes();
} else if (getKind() == Shadow.MethodExecution || getKind() == Shadow.ConstructorExecution ||
getKind() == Shadow.AdviceExecution) {
//ResolvedMember rm[] = relevantType.getDeclaredMethods();
- Member foundMember = findMethod2(relevantType.getDeclaredMethods(),getSignature());
+ ResolvedMember foundMember = findMethod2(relevantType.getDeclaredMethods(),getSignature());
- annotations = getAnnotations(foundMember, relevantMember, relevantType);
- relevantMember = foundMember;
- relevantMember = getRelevantMember(foundMember, relevantMember,relevantType);
+ annotations = getAnnotations(foundMember, shadowSignature, relevantType);
+ annotationHolder = foundMember;
+ annotationHolder = getRelevantMember(foundMember, annotationHolder,relevantType);
} else if (getKind() == Shadow.ExceptionHandler) {
relevantType = getSignature().getParameterTypes()[0].resolve(world);
for (int i = 0; i < annotations.length; i++) {
ResolvedType aTX = annotations[i];
- KindedAnnotationAccessVar kaav = new KindedAnnotationAccessVar(getKind(),aTX.resolve(world),relevantType,relevantMember);
+ AnnotationAccessVar kaav = new AnnotationAccessVar(getKind(),aTX.resolve(world),relevantType,annotationHolder);
kindedAnnotationVars.put(aTX,kaav);
}
}
for (int i = 0; i < annotations.length; i++) {
ResolvedType ann = annotations[i];
Kind k = Shadow.StaticInitialization;
- withinAnnotationVars.put(ann,new KindedAnnotationAccessVar(k,ann,getEnclosingType(),null));
+ withinAnnotationVars.put(ann,new AnnotationAccessVar(k,ann,getEnclosingType(),null));
}
}
Kind k = (getEnclosingMethod().getMemberView().getKind()==Member.CONSTRUCTOR?
Shadow.ConstructorExecution:Shadow.MethodExecution);
withincodeAnnotationVars.put(ann,
- new KindedAnnotationAccessVar(k,ann,getEnclosingType(),getEnclosingCodeSignature()));
+ new AnnotationAccessVar(k,ann,getEnclosingType(),getEnclosingCodeSignature()));
}
}
* advice specified one.
*/
public void weaveAfterReturning(BcelAdvice munger) {
- List returns = findReturnInstructions();
- boolean hasReturnInstructions = !returns.isEmpty();
-
- // list of instructions that handle the actual return from the join point
- InstructionList retList = new InstructionList();
-
- // variable that holds the return value
- BcelVar returnValueVar = null;
-
- if (hasReturnInstructions) {
- returnValueVar = generateReturnInstructions(returns,retList);
- } else {
- // we need at least one instruction, as the target for jumps
- retList.append(InstructionConstants.NOP);
- }
-
- // list of instructions for dispatching to the advice itself
- InstructionList advice = getAfterReturningAdviceDispatchInstructions(
- munger, retList.getStart());
-
- if (hasReturnInstructions) {
- InstructionHandle gotoTarget = advice.getStart();
- for (Iterator i = returns.iterator(); i.hasNext();) {
- InstructionHandle ih = (InstructionHandle) i.next();
- retargetReturnInstruction(munger.hasExtraParameter(), returnValueVar, gotoTarget, ih);
- }
- }
-
- range.append(advice);
- range.append(retList);
+ try {
+ List returns = findReturnInstructions();
+ boolean hasReturnInstructions = !returns.isEmpty();
+
+ // list of instructions that handle the actual return from the join point
+ InstructionList retList = new InstructionList();
+
+ // variable that holds the return value
+ BcelVar returnValueVar = null;
+
+ if (hasReturnInstructions) {
+ returnValueVar = generateReturnInstructions(returns,retList);
+ } else {
+ // we need at least one instruction, as the target for jumps
+ retList.append(InstructionConstants.NOP);
+ }
+
+ // list of instructions for dispatching to the advice itself
+ InstructionList advice = getAfterReturningAdviceDispatchInstructions(
+ munger, retList.getStart());
+
+ if (hasReturnInstructions) {
+ InstructionHandle gotoTarget = advice.getStart();
+ for (Iterator i = returns.iterator(); i.hasNext();) {
+ InstructionHandle ih = (InstructionHandle) i.next();
+ retargetReturnInstruction(munger.hasExtraParameter(), returnValueVar, gotoTarget, ih);
+ }
+ }
+
+ range.append(advice);
+ range.append(retList);
+ } catch (RuntimeException e) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Unexpected runtime exception occurred in BcelShadow.weaveAfterReturning()\n");
+ sb.append("shadow is '"+toString()+"'\n");
+ sb.append("method is '"+enclosingMethod+"'\n");
+ sb.append("enclosing shadow is '"+enclosingShadow+"'\n");
+ sb.append("range is '"+range+"'\n");
+ sb.append("munger is '"+munger+"'\n");
+ IMessage m = MessageUtil.abort(sb.toString(), e);
+ world.getMessageHandler().handleMessage(m);
+ throw e;
+ }
}
/**
extraParamOffset += thisJoinPointVar.getType().getSize();
}
- Type[] adviceParameterTypes = adviceMethod.getArgumentTypes();
+ // We use the munger signature here because it allows for any parameterization of the mungers pointcut that
+ // may have occurred ie. if the pointcut is p(T t) in the super aspect and that has become p(Foo t) in the sub aspect
+ // then here the munger signature will have 'Foo' as an argument in it whilst the adviceMethod argument type will be 'Object' - since
+ // it represents the advice method in the superaspect which uses the erasure of the type variable p(Object t) - see pr174449.
+
+ Type[] adviceParameterTypes =
+ BcelWorld.makeBcelTypes(munger.getSignature().getParameterTypes());
+// adviceMethod.getArgumentTypes();
+ adviceMethod.getArgumentTypes(); // forces initialization ... dont like this but seems to be required for some tests to pass, I think that means
+ // there is a LazyMethodGen method that is not correctly setup to call initialize() when it is invoked - but I dont have
+ // time right now to discover which
Type[] extractedMethodParameterTypes = extractedMethod.getArgumentTypes();
Type[] parameterTypes =
new Type[extractedMethodParameterTypes.length
// call to the extracted method.
// inlining support for code style aspects
- if (!munger.getConcreteAspect().isAnnotationStyleAspect()) {
+ if (!munger.getDeclaringType().isAnnotationStyleAspect()) {
String proceedName =
NameMangler.proceedMethodName(munger.getSignature().getName());
if (munger.getConcreteAspect()!=null && munger.getConcreteAspect().isAnnotationStyleAspect()
&& munger.getDeclaringAspect()!=null && munger.getDeclaringAspect().resolve(world).isAnnotationStyleAspect()) {
// stick the bitflags on the stack and call the variant of linkClosureAndJoinPoint that takes an int
- closureInstantiation.append(fact.createConstant(new Integer(bitflags)));
+ closureInstantiation.append(fact.createConstant(Integer.valueOf(bitflags)));
closureInstantiation.append(Utility.createInvoke(
getFactory(),
getWorld(),
if (targetVar != null && targetVar != thisVar) {
UnresolvedType targetType = getTargetType();
targetType = ensureTargetTypeIsCorrect(targetType);
- // see pr109728 - this fixes the case when the declaring class is sometype 'X' but the getfield
+ // see pr109728,pr229910 - this fixes the case when the declaring class is sometype 'X' but the (gs)etfield
// in the bytecode refers to a subtype of 'X'. This makes sure we use the type originally
// mentioned in the fieldget instruction as the method parameter and *not* the type upon which the
// field is declared because when the instructions are extracted into the new around body,
// they will still refer to the subtype.
- if (getKind()==FieldGet && getActualTargetType()!=null &&
+ if ((getKind()==FieldGet || getKind()==FieldSet) && getActualTargetType()!=null &&
!getActualTargetType().equals(targetType.getName())) {
targetType = UnresolvedType.forName(getActualTargetType()).resolve(world);
}
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.aspectj.apache.bcel.Constants;
*/
private boolean enforceDecpRule4_compatibleReturnTypes(BcelClassWeaver weaver, ResolvedMember superMethod, LazyMethodGen subMethod) {
boolean cont = true;
- String superReturnTypeSig = superMethod.getReturnType().getSignature();
- String subReturnTypeSig = subMethod.getReturnType().getSignature();
- superReturnTypeSig = superReturnTypeSig.replace('.','/');
- subReturnTypeSig = subReturnTypeSig.replace('.','/');
- if (!superReturnTypeSig.equals(subReturnTypeSig)) {
- // Allow for covariance - wish I could test this (need Java5...)
+ String superReturnTypeSig = superMethod.getGenericReturnType().getSignature(); // eg. Pjava/util/Collection<LFoo;>
+ String subReturnTypeSig = subMethod.getGenericReturnTypeSignature();
+ superReturnTypeSig = superReturnTypeSig.replace('.', '/');
+ subReturnTypeSig = subReturnTypeSig.replace('.', '/');
+ if (!superReturnTypeSig.equals(subReturnTypeSig)) {
+ // Check for covariance
ResolvedType subType = weaver.getWorld().resolve(subMethod.getReturnType());
ResolvedType superType = weaver.getWorld().resolve(superMethod.getReturnType());
if (!superType.isAssignableFrom(subType)) {
- ISourceLocation sloc = subMethod.getSourceLocation();
weaver.getWorld().getMessageHandler().handleMessage(MessageUtil.error(
- "The return type is incompatible with "+superMethod.getDeclaringType()+"."+superMethod.getName()+superMethod.getParameterSignature(),
- subMethod.getSourceLocation()));
+ "The return type is incompatible with " + superMethod.getDeclaringType() + "." + superMethod.getName()
+ + superMethod.getParameterSignature(), subMethod.getSourceLocation()));
// this just might be a better error message...
// "The return type '"+subReturnTypeSig+"' is incompatible with the overridden method "+superMethod.getDeclaringType()+"."+
// superMethod.getName()+superMethod.getParameterSignature()+" which returns '"+superReturnTypeSig+"'",
cont=false;
}
- }
+ }
return cont;
}
}
+ /**
+ * Search the specified type for a particular method - do not use the return value in the comparison as it is not
+ * considered for overriding.
+ */
private LazyMethodGen findMatchingMethod(LazyClassGen newParentTarget, ResolvedMember m) {
LazyMethodGen found = null;
- // Search the type for methods overriding super methods (methods that come from the new parent)
- // Don't use the return value in the comparison as overriding doesnt
- for (Iterator i = newParentTarget.getMethodGens().iterator(); i.hasNext() && found==null;) {
+ List methodGens = newParentTarget.getMethodGens();
+ for (Iterator i = methodGens.iterator(); i.hasNext() && found == null;) {
LazyMethodGen gen = (LazyMethodGen) i.next();
if (gen.getName().equals(m.getName()) &&
gen.getParameterSignature().equals(m.getParameterSignature())) {
clazz.addMethodGen(bridgeMethod);
}
+ // Unlike toString() on a member, this does not include the declaring type
+ private String stringifyMember(ResolvedMember member) {
+ StringBuffer buf = new StringBuffer();
+ buf.append(member.getReturnType().getName());
+ buf.append(' ');
+ buf.append(member.getName());
+ if (member.getKind() != Member.FIELD) {
+ buf.append("(");
+ UnresolvedType[] params = member.getParameterTypes();
+ if (params.length != 0) {
+ buf.append(params[0]);
+ for (int i=1, len = params.length; i < len; i++) {
+ buf.append(", ");
+ buf.append(params[i].getName());
+ }
+ }
+ buf.append(")");
+ }
+ return buf.toString();
+ }
+
private boolean mungeMethodDelegate(BcelClassWeaver weaver, MethodDelegateTypeMunger munger) {
ResolvedMember introduced = munger.getSignature();
boolean shouldApply = munger.matches(weaver.getLazyClassGen().getType(), aspectType);
if (shouldApply) {
+
+ // If no implementation class was specified, the intention was that the types matching the pattern
+ // already implemented the interface, let's check that now!
+ if (munger.getImplClassName()==null) {
+ boolean isOK = false;
+ List/*LazyMethodGen*/ existingMethods = gen.getMethodGens();
+ for (Iterator i = existingMethods.iterator(); i.hasNext() && !isOK;) {
+ LazyMethodGen m = (LazyMethodGen) i.next();
+ if (m.getName().equals(introduced.getName()) &&
+ m.getParameterSignature().equals(introduced.getParameterSignature()) &&
+ m.getReturnType().equals(introduced.getReturnType())) {
+ isOK = true;
+ }
+ }
+ if (!isOK) {
+ // the class does not implement this method, they needed to supply a default impl class
+ IMessage msg = new Message("@DeclareParents: No defaultImpl was specified but the type '"+gen.getName()+
+ "' does not implement the method '"+stringifyMember(introduced)+"' defined on the interface '"+introduced.getDeclaringType()+"'",
+ weaver.getLazyClassGen().getType().getSourceLocation(),true,new ISourceLocation[]{munger.getSourceLocation()});
+ weaver.getWorld().getMessageHandler().handleMessage(msg);
+ return false;
+ }
+
+ return true;
+ }
+
+
+
LazyMethodGen mg = new LazyMethodGen(
introduced.getModifiers() - Modifier.ABSTRACT,
BcelWorld.makeBcelType(introduced.getReturnType()),
return new BcelTypeMunger(munger.parameterizedFor(target),aspectType);
}
+ public ConcreteTypeMunger parameterizeWith(Map m, World w) {
+ return new BcelTypeMunger(munger.parameterizeWith(m,w),aspectType);
+ }
+
/**
* Returns a list of type variable aliases used in this munger. For example, if the
* ITD is 'int I<A,B>.m(List<A> las,List<B> lbs) {}' then this returns a list containing
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.CrosscuttingMembersSet;
+import org.aspectj.weaver.CustomMungerFactory;
import org.aspectj.weaver.IClassFileProvider;
import org.aspectj.weaver.IWeaveRequestor;
import org.aspectj.weaver.IWeaver;
import org.aspectj.weaver.NewParentTypeMunger;
import org.aspectj.weaver.ReferenceType;
import org.aspectj.weaver.ReferenceTypeDelegate;
-import org.aspectj.weaver.ResolvedTypeMunger;
import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.ResolvedTypeMunger;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.ShadowMunger;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.WeaverMessages;
-import org.aspectj.weaver.WeaverMetrics;
import org.aspectj.weaver.WeaverStateInfo;
import org.aspectj.weaver.World;
import org.aspectj.weaver.patterns.AndPointcut;
import org.aspectj.weaver.patterns.BindingAnnotationTypePattern;
import org.aspectj.weaver.patterns.BindingTypePattern;
-import org.aspectj.weaver.patterns.CflowPointcut;
import org.aspectj.weaver.patterns.ConcreteCflowPointcut;
import org.aspectj.weaver.patterns.DeclareAnnotation;
import org.aspectj.weaver.patterns.DeclareParents;
public BcelWeaver(BcelWorld world) {
super();
if (trace.isTraceEnabled()) trace.enter("<init>",this,world);
- WeaverMetrics.reset();
this.world = world;
this.xcutSet = world.getCrosscuttingMembersSet();
if (trace.isTraceEnabled()) trace.exit("<init>");
private List declareParentsList = null; // setup by prepareForWeave
private ZipOutputStream zipOutputStream;
+ private CustomMungerFactory customMungerFactory;
// ----
wsi.getUnwovenClassFileData(wovenJavaClass.getBytes()));
world.storeClass(unwovenJavaClass);
classType.setJavaClass(unwovenJavaClass);
- if (world.isRunMinimalMemory() && world.isXnoInline())
- classType.evictWeavingState(); // CUSTARD
// classType.setJavaClass(Utility.makeJavaClass(classType.getJavaClass().getFileName(), wsi.getUnwovenClassFileData(classType.getJavaClass().getBytes())));
}
//=> mainly for nothing for LTW - pbly for something in incremental build...
xcutSet.addOrReplaceAspect(type);
if (trace.isTraceEnabled()) trace.exit("addLibraryAspect",type);
+ if (type.getSuperclass().isAspect()) {
+ // If the supertype includes ITDs and the user has not included that aspect in the aop.xml, they will
+ // not get picked up, which can give unusual behaviour! See bug 223094
+ // This change causes us to pick up the super aspect regardless of what was said in the aop.xml - giving
+ // predictable behaviour. If the user also supplied it, there will be no problem other than the second
+ // addition overriding the first
+ addLibraryAspect(type.getSuperclass().getName());
+ }
return type;
} else {
// FIXME AV - better warning upon no such aspect from aop.xml
if (trace.isTraceEnabled()) trace.enter("prepareForWeave",this);
needToReweaveWorld = xcutSet.hasChangedSinceLastReset();
- CflowPointcut.clearCaches();
// update mungers
for (Iterator i = addedClasses.iterator(); i.hasNext(); ) {
typeMungerList = xcutSet.getTypeMungers();
lateTypeMungerList = xcutSet.getLateTypeMungers();
declareParentsList = xcutSet.getDeclareParents();
+
+ addCustomMungers();
// The ordering here used to be based on a string compare on toString() for the two mungers -
// that breaks for the @AJ style where advice names aren't programmatically generated. So we
if (trace.isTraceEnabled()) trace.exit("prepareForWeave");
}
+ private void addCustomMungers() {
+ if (customMungerFactory != null) {
+ for (Iterator i = addedClasses.iterator(); i.hasNext();) {
+ UnwovenClassFile jc = (UnwovenClassFile) i.next();
+ String name = jc.getClassName();
+ ResolvedType type = world.resolve(name);
+ if (type.isAspect()) {
+ Collection/*ShadowMunger*/ shadowMungers = customMungerFactory.createCustomShadowMungers(type);
+ if (shadowMungers != null) {
+ shadowMungerList.addAll(shadowMungers);
+ }
+ Collection/*ConcreteTypeMunger*/ typeMungers = customMungerFactory
+ .createCustomTypeMungers(type);
+ if (typeMungers != null)
+ typeMungerList.addAll(typeMungers);
+ }
+ }
+ }
+ }
+
+ public void setCustomMungerFactory(CustomMungerFactory factory) {
+ customMungerFactory = factory;
+ }
+
/*
* Rewrite all of the pointcuts in the world into their most efficient
* form for subsequent matching. Also ensure that if pc1.equals(pc2)
*/
private void raiseUnboundFormalError(String name, Pointcut userPointcut) {
world.showMessage(IMessage.ERROR,
- WeaverMessages.format(WeaverMessages.UNBOUND_FORMAL,
- name),
- userPointcut.getSourceContext().makeSourceLocation(userPointcut),null);
+ WeaverMessages.format(WeaverMessages.UNBOUND_FORMAL,name),userPointcut.getSourceLocation(),null);
}
}
}
+ // Go through the types and ensure any 'damaged' during compile time are repaired prior to weaving
+ for (Iterator i = input.getClassFileIterator(); i.hasNext(); ) {
+ UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+ String className = classFile.getClassName();
+ ResolvedType theType = world.resolve(className);
+ if (theType!=null) {
+ BcelObjectType classType = BcelWorld.getBcelObjectType(theType);
+ if (classType!=null) classType.ensureDelegateConsistent();
+ }
+ }
+
// special case for AtAspectJMungerOnly - see #113587
if (input.isApplyAtAspectJMungersOnly()) {
ContextToken atAspectJMungersOnly = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_ATASPECTJTYPE_MUNGERS_ONLY, "");
//clazz is null if the classfile was unchanged by weaving...
if (clazz != null) {
UnwovenClassFile[] newClasses = getClassFilesFor(clazz);
+ // Copy the char[] across as it means the WeaverAdapter.removeFromMap() can be fast!
+ if (newClasses[0].getClassName().equals(classFile.getClassName())) {
+ newClasses[0].setClassNameAsChars(classFile.getClassNameAsChars());
+ }
for (int i = 0; i < newClasses.length; i++) {
requestor.acceptResult(newClasses[i]);
}
public UnwovenClassFile[] getClassFilesFor(LazyClassGen clazz) {
List childClasses = clazz.getChildClasses(world);
UnwovenClassFile[] ret = new UnwovenClassFile[1 + childClasses.size()];
- ret[0] = new UnwovenClassFile(clazz.getFileName(),clazz.getJavaClassBytesIncludingReweavable(world));
+ // APR29
+ ret[0] = new UnwovenClassFile(clazz.getFileName(),clazz.getClassName(),clazz.getJavaClassBytesIncludingReweavable(world));
int index = 1;
for (Iterator iter = childClasses.iterator(); iter.hasNext();) {
UnwovenClassFile.ChildClass element = (UnwovenClassFile.ChildClass) iter.next();
- UnwovenClassFile childClass = new UnwovenClassFile(clazz.getFileName() + "$" + element.name, element.bytes);
+ // APR29
+ UnwovenClassFile childClass = new UnwovenClassFile(clazz.getFileName() + "$" + element.name,/*clazz.getClassName()+"$"+element.name,*/ element.bytes);
ret[index++] = childClass;
}
return ret;
boolean typeChanged = applyDeclareParents(decp,onType);
if (typeChanged) {
aParentChangeOccurred = true;
- } else { // Perhaps it would have matched if a 'dec @type' had modified the type
- if (!decp.getChild().isStarAnnotation()) decpToRepeat.add(decp);
+ } else {
+ decpToRepeat.add(decp);
}
}
while (iter.hasNext()) {
ShadowMunger munger = (ShadowMunger)iter.next();
FuzzyBoolean fb = munger.getPointcut().fastMatch(info);
- WeaverMetrics.recordFastMatchTypeResult(fb); // Could pass: munger.getPointcut().toString(),info
if (fb.maybeTrue()) {
result.add(munger);
}
import org.aspectj.apache.bcel.util.Repository;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.weaver.Advice;
-import org.aspectj.weaver.AdviceKind;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AnnotationOnTypeMunger;
import org.aspectj.weaver.AnnotationX;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.ICrossReferenceHandler;
+import org.aspectj.weaver.MemberKind;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.MemberImpl;
import org.aspectj.weaver.NewParentTypeMunger;
}
-
-
private static List getPathEntries(String s) {
List ret = new ArrayList();
StringTokenizer tok = new StringTokenizer(s, File.pathSeparator);
classPath.addPath(name, this.getMessageHandler());
}
- /**
- * Parse a string into advice.
- *
- * <blockquote><pre>
- * Kind ( Id , ... ) : Pointcut -> MethodSignature
- * </pre></blockquote>
- */
- public Advice shadowMunger(String str, int extraFlag) {
- str = str.trim();
- int start = 0;
- int i = str.indexOf('(');
- AdviceKind kind =
- AdviceKind.stringToKind(str.substring(start, i));
- start = ++i;
- i = str.indexOf(')', i);
- String[] ids = parseIds(str.substring(start, i).trim());
- //start = ++i;
-
-
-
- i = str.indexOf(':', i);
- start = ++i;
- i = str.indexOf("->", i);
- Pointcut pointcut = Pointcut.fromString(str.substring(start, i).trim());
- Member m = MemberImpl.methodFromString(str.substring(i+2, str.length()).trim());
-
- // now, we resolve
- UnresolvedType[] types = m.getParameterTypes();
- FormalBinding[] bindings = new FormalBinding[ids.length];
- for (int j = 0, len = ids.length; j < len; j++) {
- bindings[j] = new FormalBinding(types[j], ids[j], j, 0, 0, "fromString");
- }
-
- Pointcut p =
- pointcut.resolve(new SimpleScope(this, bindings));
-
- return new BcelAdvice(kind, p, m, extraFlag, 0, 0, null, null);
- }
-
- private String[] parseIds(String str) {
- if (str.length() == 0) return ZERO_STRINGS;
- List l = new ArrayList();
- int start = 0;
- while (true) {
- int i = str.indexOf(',', start);
- if (i == -1) {
- l.add(str.substring(start).trim());
- break;
- }
- l.add(str.substring(start, i).trim());
- start = i+1;
- }
- return (String[]) l.toArray(new String[l.size()]);
- }
-
// ---- various interactions with bcel
public static Type makeBcelType(UnresolvedType type) {
}
- public Member makeJoinPointSignatureFromMethod(LazyMethodGen mg, MemberImpl.Kind kind) {
+ public Member makeJoinPointSignatureFromMethod(LazyMethodGen mg, MemberKind kind) {
Member ret = mg.getMemberView();
if (ret == null) {
int mods = mg.getAccessFlags();
mods |= Modifier.INTERFACE;
}
if (kind == null) {
- if (mg.getName().equals("<init>")) {
+ //OPTIMIZE surely we can pass the kind in and not resort to string compares?
+ if (mg.getName().equals("<init>")) {
kind = Member.CONSTRUCTOR;
} else if (mg.getName().equals("<clinit>")) {
kind = Member.STATIC_INITIALIZATION;
}
public Member makeJoinPointSignatureForMonitorEnter(LazyClassGen cg,InstructionHandle h) {
- Instruction i = h.getInstruction();
return MemberImpl.monitorEnter();
}
public Member makeJoinPointSignatureForMonitorExit(LazyClassGen cg,InstructionHandle h) {
- Instruction i = h.getInstruction();
return MemberImpl.monitorExit();
}
+++ /dev/null
-/* *******************************************************************
- * Copyright (c) 2005 IBM
- * 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:
- * Andy Clement initial implementation
- * ******************************************************************/
-
-
-package org.aspectj.weaver.bcel;
-
-import org.aspectj.apache.bcel.Constants;
-import org.aspectj.apache.bcel.generic.Instruction;
-import org.aspectj.apache.bcel.generic.InstructionConstants;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.apache.bcel.generic.ObjectType;
-import org.aspectj.apache.bcel.generic.Type;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.Shadow;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.Shadow.Kind;
-
-
-/**
- * Represents access to an annotation on an element, relating to some 'kinded' pointcut.
- * Depending on the kind of pointcut the element might be a field or a method or a ...
- */
-public class KindedAnnotationAccessVar extends BcelVar {
-
- private Kind kind; // What kind of shadow are we at?
- private UnresolvedType containingType; // The type upon which we want to ask for 'member'
- private Member member; // For method call/execution and field get/set contains the member that has the annotation
-
- public KindedAnnotationAccessVar(Kind kind, ResolvedType type,UnresolvedType theTargetIsStoredHere,Member sig) {
- super(type,0);
- this.kind = kind;
- this.containingType = theTargetIsStoredHere;
- this.member = sig;
- }
-
- public String toString() {
- return "KindedAnnotationAccessVar(" + getType() +")";
- }
-
- public Instruction createLoad(InstructionFactory fact) {
- throw new RuntimeException("unimplemented");
- }
- public Instruction createStore(InstructionFactory fact) {
- throw new RuntimeException("unimplemented");
- }
-
- public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) {
- throw new RuntimeException("unimplemented");
- }
-
- public void appendLoad(InstructionList il, InstructionFactory fact) {
- il.append(createLoadInstructions(getType(), fact));
- }
-
- // FIXME asc Refactor all this stuff - there is a lot of commonality
- public InstructionList createLoadInstructions(ResolvedType toType, InstructionFactory fact) {
-
- // FIXME asc Decide on whether we ought to build an exception handler for the NoSuchMethodException that can be thrown
- // by getDeclaredMethod()... right now we don't but no-one seems to care...
-// LocalVariableGen var_ex = mg.addLocalVariable("ex",Type.getType("Ljava.io.IOException;"),null,null);
-// int var_ex_slot = var_ex.getIndex();
-//
-// InstructionHandle handler = il.append(new ASTORE(var_ex_slot));
-// var_ex.setStart(handler);
-// var_ex.setEnd(il.append(InstructionConstants.RETURN));
-//
-// mg.addExceptionHandler(try_start, try_end, handler,
-// new ObjectType("java.io.IOException"));
-
-
- InstructionList il = new InstructionList();
- Type jlClass = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_CLASS);
-
- Type jlString = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.String;"));
- Type jlClassArray = BcelWorld.makeBcelType(UnresolvedType.forSignature("[Ljava.lang.Class;"));
-
- Type jlaAnnotation = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.annotation.Annotation;"));
-
- if (kind==Shadow.MethodCall || kind==Shadow.MethodExecution ||
- kind==Shadow.PreInitialization || kind==Shadow.Initialization ||
- kind==Shadow.ConstructorCall || kind==Shadow.ConstructorExecution ||
- kind==Shadow.AdviceExecution ||
- // annotations for fieldset/fieldget when an ITD is involved are stored against a METHOD
- ((kind==Shadow.FieldGet || kind==Shadow.FieldSet) && member.getKind()==Member.METHOD)) {
-
- Type jlrMethod = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.reflect.Method;"));
-
- // Calls getClass
-
- // Variant (1) Use the target directly
- il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));
-
- // Variant (2) Ask the target for its class (could give a different answer at runtime)
- // il.append(target.createLoad(fact));
- // il.append(fact.createInvoke("java/lang/Object","getClass",jlClass,new Type[]{},Constants.INVOKEVIRTUAL));
-
- // il.append(fact.createConstant(new ObjectType(toType.getClassName())));
-
-
- if (kind==Shadow.MethodCall || kind==Shadow.MethodExecution || kind==Shadow.AdviceExecution ||
- // annotations for fieldset/fieldget when an ITD is involved are stored against a METHOD
- ((kind==Shadow.FieldGet || kind==Shadow.FieldSet) && member.getKind()==Member.METHOD) ||
- ((kind==Shadow.ConstructorCall || kind==Shadow.ConstructorExecution) && member.getKind()==Member.METHOD)) {
- il.append(fact.createConstant(member.getName()));
- Type[] paramTypes = null;
- paramTypes = BcelWorld.makeBcelTypes(member.getParameterTypes());
- buildArray(il,fact,jlClass,paramTypes,1);
- // Calls getDeclaredMethod
- il.append(fact.createInvoke("java/lang/Class","getDeclaredMethod",jlrMethod,new Type[]{jlString,jlClassArray},Constants.INVOKEVIRTUAL));
- // FIXME asc perf Cache the result of getDeclaredMethod() and use it
- // again for other annotations on the same signature at this join point
- // Calls getAnnotation
- String ss = toType.getName();
- il.append(fact.createConstant(new ObjectType(toType.getName())));
- il.append(fact.createInvoke("java/lang/reflect/Method","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL));
- il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType)));
- } else { // init/preinit/ctor-call/ctor-exec
- Type[] paramTypes = BcelWorld.makeBcelTypes(member.getParameterTypes());
- buildArray(il,fact,jlClass,paramTypes,1);
- Type jlrCtor = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.reflect.Constructor;"));
- il.append(fact.createInvoke("java/lang/Class","getDeclaredConstructor",jlrCtor,new Type[]{jlClassArray},Constants.INVOKEVIRTUAL));
-
- // !!! OPTIMIZATION: Cache the result of getDeclaredMethod() and use it
- // again for other annotations on the same signature at this join point
- // Calls getAnnotation
- String ss = toType.getName();
- il.append(fact.createConstant(new ObjectType(toType.getName())));
- il.append(fact.createInvoke("java/lang/reflect/Constructor","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL));
- il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType)));
- }
- } else if (kind == Shadow.FieldSet || kind == Shadow.FieldGet) {
- Type jlrField = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.reflect.Field;"));
- il.append(fact.createConstant(BcelWorld.makeBcelType(containingType))); // Stick the target on the stack
- il.append(fact.createConstant(member.getName())); // Stick what we are after on the stack
- il.append(fact.createInvoke("java/lang/Class","getDeclaredField",jlrField,new Type[]{jlString},Constants.INVOKEVIRTUAL));
- String ss = toType.getName();
- il.append(fact.createConstant(new ObjectType(toType.getName())));
- il.append(fact.createInvoke("java/lang/reflect/Field","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL));
- il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType)));
- } else if (kind == Shadow.StaticInitialization || kind==Shadow.ExceptionHandler) {
- il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));
- String ss = toType.getName();
- il.append(fact.createConstant(new ObjectType(toType.getName())));
- il.append(fact.createInvoke("java/lang/Class","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL));
- il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType)));
- } else {
- throw new RuntimeException("Don't understand this kind "+kind);
- }
- return il;
-
- }
-
-
- private void buildArray(InstructionList il, InstructionFactory fact, Type arrayElementType, Type[] arrayEntries,int dim) {
- il.append(fact.createConstant(new Integer(arrayEntries==null?0:arrayEntries.length)));
- il.append(fact.createNewArray(arrayElementType,(short)dim));
- if (arrayEntries == null) return;
- for (int i = 0; i < arrayEntries.length; i++) {
- il.append(InstructionFactory.createDup(1));
- il.append(fact.createConstant(new Integer(i)));
- switch (arrayEntries[i].getType()) {
- case Constants.T_ARRAY:
- il.append(fact.createConstant(new ObjectType(arrayEntries[i].getSignature())));
- break;
- case Constants.T_BOOLEAN: il.append(fact.createGetStatic("java/lang/Boolean","TYPE",arrayElementType)); break;
- case Constants.T_BYTE:il.append(fact.createGetStatic("java/lang/Byte","TYPE",arrayElementType)); break;
- case Constants.T_CHAR:il.append(fact.createGetStatic("java/lang/Character","TYPE",arrayElementType)); break;
- case Constants.T_INT:il.append(fact.createGetStatic("java/lang/Integer","TYPE",arrayElementType)); break;
- case Constants.T_LONG:il.append(fact.createGetStatic("java/lang/Long","TYPE",arrayElementType)); break;
- case Constants.T_DOUBLE:il.append(fact.createGetStatic("java/lang/Double","TYPE",arrayElementType)); break;
- case Constants.T_FLOAT:il.append(fact.createGetStatic("java/lang/Float","TYPE",arrayElementType)); break;
- case Constants.T_SHORT:il.append(fact.createGetStatic("java/lang/Short","TYPE",arrayElementType)); break;
- default:
- il.append(fact.createConstant(arrayEntries[i]));
- }
- il.append(InstructionConstants.AASTORE);
- }
- }
-
- public void appendLoadAndConvert(
- InstructionList il,
- InstructionFactory fact,
- ResolvedType toType) {
- il.append(createLoadInstructions(toType, fact));
-
- }
-
- public void insertLoad(InstructionList il, InstructionFactory fact) {
- il.insert(createLoadInstructions(getType(), fact));
- }
-
-}
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.SourceLocation;
-import org.aspectj.util.CollectionUtil;
+import org.aspectj.util.LangUtil;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.Member;
}
// Add a weaver version attribute to the file being produced (if necessary...)
- boolean hasVersionAttribute = false;
- Attribute[] attrs = myGen.getAttributes();
- for (int i = 0; i < attrs.length && !hasVersionAttribute; i++) {
- Attribute attribute = attrs[i];
- if (attribute.getName().equals("org.aspectj.weaver.WeaverVersion")) hasVersionAttribute=true;
- }
- if (!hasVersionAttribute)
- myGen.addAttribute(BcelAttributes.bcelAttribute(new AjAttribute.WeaverVersionInfo(),getConstantPool()));
+ if (!myGen.hasAttribute("org.aspectj.weaver.WeaverVersion")) {
+ myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverVersionInfo(),getConstantPool()));
+ }
if (myType != null && myType.getWeaverState() != null) {
- myGen.addAttribute(BcelAttributes.bcelAttribute(
+ myGen.addAttribute(Utility.bcelAttribute(
new AjAttribute.WeaverState(myType.getWeaverState()),
getConstantPool()));
}
addAjcInitializers();
- calculateSourceDebugExtensionOffsets();
+ // 17Feb05 - ASC - Skip this for now - it crashes IBM 1.4.2 jvms (pr80430). Will be revisited when contents
+ // of attribute are confirmed to be correct.
+ boolean sourceDebugExtensionSupportSwitchedOn = false;
+
+ if (sourceDebugExtensionSupportSwitchedOn) {
+ calculateSourceDebugExtensionOffsets();
+ }
int len = methodGens.size();
myGen.setMethods(Method.NoMethods);
if (isEmptyClinit(gen)) continue;
myGen.addMethod(gen.getMethod());
}
+
len = fields.size();
myGen.setFields(Field.NoFields);
for (int i = 0; i < len; i++) {
BcelField gen = (BcelField) fields.get(i);
myGen.addField(gen.getField(this.constantPoolGen));
}
-
- if (inlinedFiles.size() != 0) {
- if (hasSourceDebugExtensionAttribute(myGen)) {
- world.showMessage(
- IMessage.WARNING,
- WeaverMessages.format(WeaverMessages.OVERWRITE_JSR45,getFileName()),
- null,
- null);
+
+ if (sourceDebugExtensionSupportSwitchedOn) {
+ if (inlinedFiles.size() != 0) {
+ if (hasSourceDebugExtensionAttribute(myGen)) {
+ world.showMessage(
+ IMessage.WARNING,
+ WeaverMessages.format(WeaverMessages.OVERWRITE_JSR45,getFileName()),
+ null,
+ null);
+ }
+ // myGen.addAttribute(getSourceDebugExtensionAttribute());
}
- // 17Feb05 - ASC - Skip this for now - it crashes IBM 1.4.2 jvms (pr80430). Will be revisited when contents
- // of attribute are confirmed to be correct.
- // myGen.addAttribute(getSourceDebugExtensionAttribute());
- }
+ }
fixupGenericSignatureAttribute();
}
// 2. Find the old attribute
Signature sigAttr = null;
if (myType!=null) { // if null, this is a type built from scratch, it won't already have a sig attribute
- Attribute[] as = myGen.getAttributes();
- for (int i = 0; i < as.length; i++) {
- Attribute attribute = as[i];
- if (attribute.getName().equals("Signature")) sigAttr = (Signature)attribute;
- }
+ sigAttr = (Signature) myGen.getAttribute("Signature");
}
// 3. Do we need an attribute?
// create an empty myGen so that we can give back a return value that doesn't upset the
// rest of the process.
myGen = new ClassGen(myGen.getClassName(), myGen.getSuperclassName(),
- myGen.getFileName(), myGen.getAccessFlags(), myGen.getInterfaceNames());
+ myGen.getFileName(), myGen.getModifiers(), myGen.getInterfaceNames());
// raise an error against this compilation unit.
getWorld().showMessage(
IMessage.ERROR,
}
private static boolean hasSourceDebugExtensionAttribute(ClassGen gen) {
- ConstantPool pool = gen.getConstantPool();
- Attribute[] attrs = gen.getAttributes();
- for (int i = 0; i < attrs.length; i++) {
- if ("SourceDebugExtension"
- .equals(((ConstantUtf8) pool.getConstant(attrs[i].getNameIndex())).getBytes())) {
- return true;
- }
- }
- return false;
+ return gen.hasAttribute("SourceDebugExtension");
+// ConstantPool pool = gen.getConstantPool();
+// Attribute[] attrs = gen.getAttributes();
+// for (int i = 0; i < attrs.length; i++) {
+// if ("SourceDebugExtension"
+// .equals(((ConstantUtf8) pool.getConstant(attrs[i].getNameIndex())).getBytes())) {
+// return true;
+// }
+// }
+// return false;
}
public JavaClass getJavaClass(BcelWorld world) {
public String toShortString() {
String s =
- org.aspectj.apache.bcel.classfile.Utility.accessToString(myGen.getAccessFlags(), true);
+ org.aspectj.apache.bcel.classfile.Utility.accessToString(myGen.getModifiers(), true);
if (s != "")
s += " ";
- s += org.aspectj.apache.bcel.classfile.Utility.classOrInterface(myGen.getAccessFlags());
+ s += org.aspectj.apache.bcel.classfile.Utility.classOrInterface(myGen.getModifiers());
s += " ";
s += myGen.getClassName();
return s;
Type.VOID,
"<clinit>",
new Type[0],
- CollectionUtil.NO_STRINGS,
+ LangUtil.NO_STRINGS,
this);
clinit.getBody().insert(InstructionConstants.RETURN);
methodGens.add(clinit);
Type.VOID,
NameMangler.AJC_PRE_CLINIT_NAME,
new Type[0],
- CollectionUtil.NO_STRINGS,
+ LangUtil.NO_STRINGS,
this);
ajcClinit.getBody().insert(InstructionConstants.RETURN);
methodGens.add(ajcClinit);
private void makeSyntheticAndTransientIfNeeded(FieldGen field) {
if (field.getName().startsWith(NameMangler.PREFIX) &&
- !field.getName().startsWith("ajc$interField$")) {
+ !field.getName().startsWith("ajc$interField$") &&
+ !field.getName().startsWith("ajc$instance$")) {
// it's an aj added field
// first do transient
if (!field.isStatic()) {
}
}
- private boolean hasSyntheticAttribute(Attribute[] attributes) {
- for (int i = 0; i < attributes.length; i++) {
- if (attributes[i].getName().equals("Synthetic")) {
+ private boolean hasSyntheticAttribute(List attributes) {
+ for (int i = 0; i < attributes.size(); i++) {
+ if (((Attribute)attributes.get(i)).getName().equals("Synthetic")) {
return true;
}
}
public void forcePublic() {
- myGen.setAccessFlags(Utility.makePublic(myGen.getAccessFlags()));
+ myGen.setModifiers(Utility.makePublic(myGen.getModifiers()));
}
import org.aspectj.apache.bcel.generic.CodeExceptionGen;
import org.aspectj.apache.bcel.generic.Instruction;
import org.aspectj.apache.bcel.generic.InstructionBranch;
+import org.aspectj.apache.bcel.generic.InstructionComparator;
import org.aspectj.apache.bcel.generic.InstructionHandle;
import org.aspectj.apache.bcel.generic.InstructionList;
import org.aspectj.apache.bcel.generic.InstructionSelect;
import org.aspectj.apache.bcel.generic.MethodGen;
import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.Tag;
+import org.aspectj.apache.bcel.generic.TargetLostException;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.weaver.tools.Traceable;
+
/**
* A LazyMethodGen should be treated as a MethodGen. It's our way of abstracting over the
* low-level Method objects. It converts through {@link MethodGen} to create
public final class LazyMethodGen implements Traceable {
private static final int ACC_SYNTHETIC = 0x1000;
- private int accessFlags;
- private Type returnType;
- private final String name;
+ private int accessFlags;
+ private Type returnType;
+ private final String name;
private Type[] argumentTypes;
//private final String[] argumentNames;
private String[] declaredExceptions;
private InstructionList body; // leaving null for abstracts
- private Attribute[] attributes;
+ private List attributes;
private List newAnnotations;
private final LazyClassGen enclosingClass;
private BcelMethod memberView;
private AjAttribute.EffectiveSignatureAttribute effectiveSignature;
int highestLineNumber = 0;
+ boolean wasNewPacked = false;
/*
+ * We use LineNumberTags and not Gens.
+ *
* This option specifies whether we let the BCEL classes create LineNumberGens and LocalVariableGens
* or if we make it create LineNumberTags and LocalVariableTags. Up until 1.5.1 we always created
* Gens - then on return from the MethodGen ctor we took them apart, reprocessed them all and
* instructions it targets, it relies on the instructions targetting *it* - this reduces the amount
* of targeter manipulation we have to do.
*
- * Because this *could* go wrong - it passes all our tests, but you never know, the option:
- * -Xset:optimizeWithTags=false
- * will turn it *OFF*
*/
- public static boolean avoidUseOfBcelGenObjects = true;
- public static boolean checkedXsetOption = false;
/** This is nonnull if this method is the result of an "inlining". We currently
* copy methods into other classes for around advice. We add this field so
} else {
body = null;
}
- this.attributes = new Attribute[0];
+ this.attributes = new ArrayList();
this.enclosingClass = enclosingClass;
assertGoodBody();
}
this.memberView = new BcelMethod(enclosingClass.getBcelObjectType(), m);
- this.accessFlags = m.getAccessFlags();
+ this.accessFlags = m.getModifiers();
this.name = m.getName();
// @AJ advice are not inlined by default since requires further analysis
}
//this.memberView = new BcelMethod(enclosingClass.getBcelObjectType(), m);
this.memberView = m;
- this.accessFlags = savedMethod.getAccessFlags();
+ this.accessFlags = savedMethod.getModifiers();
this.name = m.getName();
// @AJ advice are not inlined by default since requires further analysis
private void initialize() {
if (returnType != null) return;
- // Check whether we need to configure the optimization
- if (!checkedXsetOption) {
- Properties p = enclosingClass.getWorld().getExtraConfiguration();
- if (p!=null) {
- String s = p.getProperty("optimizeWithTags","true");
- avoidUseOfBcelGenObjects = s.equalsIgnoreCase("true");
- if (!avoidUseOfBcelGenObjects)
- enclosingClass.getWorld().getMessageHandler().handleMessage(MessageUtil.info("[optimizeWithTags=false] Disabling optimization to use Tags rather than Gens"));
- }
- checkedXsetOption=true;
- }
-
//System.err.println("initializing: " + getName() + ", " + enclosingClass.getName() + ", " + returnType + ", " + savedMethod);
- MethodGen gen = new MethodGen(savedMethod, enclosingClass.getName(), enclosingClass.getConstantPool(),avoidUseOfBcelGenObjects);
-
+ MethodGen gen = null;
+ try {
+ gen = new MethodGen(savedMethod, enclosingClass.getName(), enclosingClass.getConstantPool(),true);
+ } catch (RuntimeException t) {
+ System.err.println(getName());
+ throw t;
+ }
this.returnType = gen.getReturnType();
this.argumentTypes = gen.getArgumentTypes();
unpackHandlers(gen);
- if (avoidUseOfBcelGenObjects) {
- ensureAllLineNumberSetup(gen);
- highestLineNumber = gen.getHighestlinenumber();
- } else {
- unpackLineNumbers(gen);
- unpackLocals(gen);
- }
+ ensureAllLineNumberSetup(gen);
+ highestLineNumber = gen.getHighestlinenumber();
+
}
assertGoodBody();
}
}
- private void unpackLineNumbers(MethodGen gen) {
- LineNumberTag lr = null;
- for (InstructionHandle ih = body.getStart(); ih != null; ih = ih.getNext()) {
- InstructionTargeter[] targeters = ih.getTargeters();
- if (targeters != null) {
- for (int i = targeters.length - 1; i >= 0; i--) {
- InstructionTargeter targeter = targeters[i];
- if (targeter instanceof LineNumberGen) {
- LineNumberGen lng = (LineNumberGen) targeter;
- lng.updateTarget(ih, null);
- int lineNumber = lng.getSourceLine();
- if (highestLineNumber < lineNumber) highestLineNumber = lineNumber;
- lr = new LineNumberTag(lineNumber);
- }
- }
- }
- if (lr != null) {
- ih.addTargeter(lr);
- }
- }
- gen.removeLineNumbers();
- }
-
/**
* On entry to this method we have a method whose instruction stream contains a few instructions
* that have line numbers assigned to them (LineNumberTags). The aim is to ensure every instruction
}
}
}
-
- private void unpackLocals(MethodGen gen) {
- Set locals = new HashSet();
- for (InstructionHandle ih = body.getStart(); ih != null; ih = ih.getNext()) {
- InstructionTargeter[] targeters = ih.getTargeters();
- List ends = new ArrayList(0);
- if (targeters != null) {
- for (int i = targeters.length - 1; i >= 0; i--) {
- InstructionTargeter targeter = targeters[i];
- if (targeter instanceof LocalVariableGen) {
- LocalVariableGen lng = (LocalVariableGen) targeter;
- LocalVariableTag lr = new LocalVariableTag(lng.getType().getSignature()/*BcelWorld.fromBcel(lng.getType())*/, lng.getName(), lng.getIndex(), lng.getStart().getPosition());
- if (lng.getStart() == ih) {
- locals.add(lr);
- } else {
- ends.add(lr);
- }
- }
- }
- }
- for (Iterator i = locals.iterator(); i.hasNext(); ) {
- ih.addTargeter((LocalVariableTag) i.next());
- }
- locals.removeAll(ends);
- }
- gen.removeLocalVariables();
- }
// ===============
try {
MethodGen gen = pack();
- return gen.getMethod();
+ savedMethod = gen.getMethod();
+ return savedMethod;
} catch (ClassGenException e) {
enclosingClass.getBcelObjectType().getResolvedTypeX().getWorld().showMessage(
IMessage.ERROR,
}
public void markAsChanged() {
+ if (wasNewPacked) {
+ throw new RuntimeException("Already packed method is being re-modified: "+getClassName()+" "+toShortString());
+ }
initialize();
savedMethod = null;
}
// =============================
public String toString() {
- WeaverVersionInfo weaverVersion = enclosingClass.getBcelObjectType().getWeaverVersionAttribute();
+ BcelObjectType bot = enclosingClass.getBcelObjectType();
+ WeaverVersionInfo weaverVersion = (bot==null?WeaverVersionInfo.CURRENT:bot.getWeaverVersionAttribute());
return toLongString(weaverVersion);
}
if (enclosingClass != null && enclosingClass.getType() != null) {
context = enclosingClass.getType().getSourceContext();
}
- List as = BcelAttributes.readAjAttributes(getClassName(),attributes, context,null,weaverVersion);
+ List as = BcelAttributes.readAjAttributes(getClassName(), (Attribute[])attributes.toArray(new Attribute[]{}), context,null,weaverVersion);
if (! as.isEmpty()) {
out.println(" " + as.get(0)); // XXX assuming exactly one attribute, munger...
}
return name;
}
+ public String getGenericReturnTypeSignature() {
+ if (memberView == null) {
+ return getReturnType().getSignature();
+ } else {
+ return memberView.getGenericReturnType().getSignature();
+ }
+ }
+
public Type getReturnType() {
initialize();
return returnType;
return body != null;
}
- public Attribute[] getAttributes() {
+ public List/*Attribute*/ getAttributes() {
return attributes;
}
gen.addException(declaredExceptions[i]);
}
- for (int i = 0, len = attributes.length; i < len; i++) {
- gen.addAttribute(attributes[i]);
+ for (int i = 0, len = attributes.size(); i < len; i++) {
+ gen.addAttribute((Attribute)attributes.get(i));
}
if (newAnnotations!=null) {
}
if (hasBody()) {
- packBody(gen);
+ if (this.enclosingClass.getWorld().shouldGoForIt()) {
+ if (isAdviceMethod() || getName().equals("<clinit>")) {
+ packBody(gen);
+ } else {
+ newPackBody(gen);
+ }
+ } else {
+ packBody(gen);
+ }
+ // FINISH OFF CASE/SWITCH !
gen.setMaxLocals();
gen.setMaxStack();
} else {
}
}
+
+ /*
+ * Andys version
+ */
+ public void newPackBody(MethodGen gen) {
+ InstructionList theBody = getBody();
+ InstructionHandle iHandle = theBody.getStart();
+
+ int currLine = -1;
+ int lineNumberOffset = (fromFilename == null) ? 0: getEnclosingClass().getSourceDebugExtensionOffset(fromFilename);
+ Map localVariables = new HashMap();
+ LinkedList exceptionList = new LinkedList();
+ Set forDeletion = new HashSet();
+ Set branchInstructions = new HashSet();
+ // OPTIMIZE sort out in here: getRange()/insertHandler() and type of exceptionList
+ while (iHandle != null) {
+ Instruction inst = iHandle.getInstruction();
+ InstructionHandle nextInst = iHandle.getNext();
+ // OPTIMIZE remove this instructionhandle as it now points to nowhere?
+ if (inst == Range.RANGEINSTRUCTION) {
+ Range r = Range.getRange(iHandle);
+ if (r instanceof ExceptionRange) {
+ ExceptionRange er = (ExceptionRange) r;
+ if (er.getStart() == iHandle) {
+ if (!er.isEmpty()){
+ // order is important, insert handlers in order of start
+ insertHandler(er, exceptionList);
+ }
+ }
+ }
+ forDeletion.add(iHandle);
+ } else {
+ if (inst instanceof InstructionBranch) {
+ branchInstructions.add(iHandle);
+ }
+
+ InstructionTargeter[] targeters = iHandle.getTargeters();
+ if (targeters != null) {
+ for (int k = targeters.length - 1; k >= 0; k--) {
+ InstructionTargeter targeter = targeters[k];
+ if (targeter instanceof LineNumberTag) {
+ int line = ((LineNumberTag)targeter).getLineNumber();
+ if (line != currLine) {
+ gen.addLineNumber(iHandle, line + lineNumberOffset);
+ currLine = line;
+ }
+ } else if (targeter instanceof LocalVariableTag) {
+ LocalVariableTag lvt = (LocalVariableTag) targeter;
+ LVPosition p = (LVPosition)localVariables.get(lvt);
+ // If we don't know about it, create a new position and store
+ // If we do know about it - update its end position
+ if (p==null) {
+ LVPosition newp = new LVPosition();
+ newp.start=newp.end=iHandle;
+ localVariables.put(lvt,newp);
+ } else {
+ p.end = iHandle;
+ }
+ }
+ }
+ }
+ }
+ iHandle = iHandle.getNext();
+ }
+ for (Iterator iterator = branchInstructions.iterator(); iterator.hasNext();) {
+ BranchHandle iBranch = (BranchHandle) iterator.next();
+ handleBranchInstruction(iBranch,forDeletion);
+ }
+ // now add exception handlers
+ for (Iterator iter = exceptionList.iterator(); iter.hasNext();) {
+ ExceptionRange r = (ExceptionRange) iter.next();
+ if (r.isEmpty()) continue;
+ gen.addExceptionHandler(
+ jumpForward(r.getRealStart(),forDeletion),
+ jumpForward(r.getRealEnd(),forDeletion),
+ jumpForward(r.getHandler(),forDeletion),
+ (r.getCatchType() == null)
+ ? null
+ : (ObjectType) BcelWorld.makeBcelType(r.getCatchType()));
+ }
+
+ for (Iterator iterator = forDeletion.iterator(); iterator.hasNext();) {
+ try {
+ theBody.delete((InstructionHandle)iterator.next());
+ } catch (TargetLostException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ gen.setInstructionList(theBody);
+ addLocalVariables(gen,localVariables);
+
+ // JAVAC adds line number tables (with just one entry) to generated accessor methods - this
+ // keeps some tools that rely on finding at least some form of linenumbertable happy.
+ // Let's check if we have one - if we don't then let's add one.
+ // TODO Could be made conditional on whether line debug info is being produced
+ if (gen.getLineNumbers().length==0) {
+ gen.addLineNumber(gen.getInstructionList().getStart(),1);
+ }
+ wasNewPacked = true;
+ }
+
private void addLocalVariables(MethodGen gen, Map localVariables) {
// now add local variables
gen.removeLocalVariables();
InstructionBranch newBranchInstruction = (InstructionBranch) newInstruction;
InstructionHandle oldTarget = oldBranchInstruction.getTarget(); // old target
-// try {
// New target is in hash map
newBranchInstruction.setTarget(remap(oldTarget, map));
-// } catch (NullPointerException e) {
-// print();
-// System.out.println("Was trying to remap " + bi);
-// System.out.println("who's target was supposedly " + itarget);
-// throw e;
-// }
- if (oldBranchInstruction instanceof InstructionSelect) {
- // Either LOOKUPSWITCH or TABLESWITCH
- InstructionHandle[] oldTargets = ((InstructionSelect) oldBranchInstruction).getTargets();
- InstructionHandle[] newTargets = ((InstructionSelect) newBranchInstruction).getTargets();
+ if (oldBranchInstruction instanceof InstructionSelect) {
+ // Either LOOKUPSWITCH or TABLESWITCH
+ InstructionHandle[] oldTargets = ((InstructionSelect) oldBranchInstruction).getTargets();
+ InstructionHandle[] newTargets = ((InstructionSelect) newBranchInstruction).getTargets();
- for (int k = oldTargets.length - 1; k >= 0; k--) {
- // Update all targets
+ for (int k = oldTargets.length - 1; k >= 0; k--) {
+ // Update all targets
newTargets[k] = remap(oldTargets[k], map);
newTargets[k].addTargeter(newBranchInstruction);
}
}
}
+
+ private InstructionHandle jumpForward(InstructionHandle t,Set handlesForDeletion) {
+
+ InstructionHandle target = t;
+ if (handlesForDeletion.contains(target)) {
+ do {
+ target = target.getNext();
+ } while (handlesForDeletion.contains(target));
+ }
+ return target;
+ }
+
+ private void handleBranchInstruction(BranchHandle branchHandle, Set handlesForDeletion) {
+ InstructionBranch branchInstruction = (InstructionBranch) branchHandle.getInstruction();
+ InstructionHandle target = branchInstruction.getTarget(); // old target
+
+ if (handlesForDeletion.contains(target)) {
+ do {
+ target = target.getNext();
+ } while (handlesForDeletion.contains(target));
+ branchInstruction.setTarget(target);
+ }
+
+ if (branchInstruction instanceof InstructionSelect) {
+ // Either LOOKUPSWITCH or TABLESWITCH
+ InstructionHandle[] targets = ((InstructionSelect)branchInstruction).getTargets();
+ for (int k = targets.length - 1; k >= 0; k--) {
+ InstructionHandle oneTarget = targets[k];
+ if (handlesForDeletion.contains(oneTarget)) {
+ do {
+ oneTarget = oneTarget.getNext();
+ } while (handlesForDeletion.contains(oneTarget));
+ branchInstruction.setTarget(oneTarget);
+ oneTarget.addTargeter(branchInstruction);
+ }
+ }
+ }
+ }
private void handleRangeInstruction(InstructionHandle ih, LinkedList exnList) {
// we're a range instruction
// curr = next;
// }
// }
+
+ private static InstructionHandle fNext(InstructionHandle ih) {
+ while (true) {
+ if (ih.getInstruction()==Range.RANGEINSTRUCTION) ih = ih.getNext();
+ else return ih;
+ }
+ }
private static InstructionHandle remap(InstructionHandle ih, Map map) {
while (true) {
// ----
boolean isAdviceMethod() {
+ if (memberView==null) return false;
return memberView.getAssociatedShadowMunger() != null;
}
* @param attr
*/
public void addAttribute(Attribute attr) {
- Attribute[] newAttributes = new Attribute[attributes.length + 1];
- System.arraycopy(attributes, 0, newAttributes, 0, attributes.length);
- newAttributes[attributes.length] = attr;
- attributes = newAttributes;
+ attributes.add(attr);
+// Attribute[] newAttributes = new Attribute[attributes.length + 1];
+// System.arraycopy(attributes, 0, newAttributes, 0, attributes.length);
+// newAttributes[attributes.length] = attr;
+// attributes = newAttributes;
}
public String toTraceString() {
public class UnwovenClassFile {
protected String filename;
+ protected char[] charfilename;
protected byte[] bytes;
// protected JavaClass javaClass = null;
//protected byte[] writtenBytes = null;
return true;
}
+ public char[] getClassNameAsChars() {
+ if (charfilename==null) {
+ charfilename = getClassName().replace('.', '/').toCharArray();
+ }
+ return charfilename;
+ }
public String getClassName() {
- if (className == null) className = getJavaClass().getClassName();
+ if (className == null) className = getJavaClass().getClassName(); // OPTIMIZE quicker way to determine name??? surely?
return className;
}
}
// record
+ // OPTIMIZE why is the 'short name' used here (the bit after the dollar) - seems we mess about a lot trimming it off only to put it back on!
public static class ChildClass {
public final String name;
public final byte[] bytes;
return "(ChildClass " + name + ")";
}
}
+
+ public void setClassNameAsChars(char[] classNameAsChars) {
+ this.charfilename = classNameAsChars;
+ }
}
byte[] getBytes();
}
- public UnwovenClassFileWithThirdPartyManagedBytecode(String filename,
+ // OPTIMIZE make classname an input char[]
+ public UnwovenClassFileWithThirdPartyManagedBytecode(String filename,String classname,
IByteCodeProvider provider) {
- super(filename,null);
+ // APR29
+ super(filename,classname,null);
this.provider = provider;
}
import java.util.List;
import org.aspectj.apache.bcel.Constants;
+import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ClassParser;
+import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.Method;
+import org.aspectj.apache.bcel.classfile.Unknown;
import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValueGen;
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePairGen;
import org.aspectj.apache.bcel.classfile.annotation.ElementValueGen;
import org.aspectj.apache.bcel.generic.TargetLostException;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AnnotationX;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.Lint;
kind = Constants.INVOKEVIRTUAL;
}
- return fact.createInvoke(
- declaringClass.getClassName(),
- newMethod.getName(),
- Type.getReturnType(newMethod.getSignature()),
- Type.getArgumentTypes(newMethod.getSignature()),
- kind);
+ String sig = newMethod.getSignature();
+ return fact.createInvoke(declaringClass.getClassName(),newMethod.getName(),sig,kind);
}
public static byte[] stringToUTF(String s) {
}
}
- public static String arrayToString(int[] a) {
- int len = a.length;
- if (len == 0) return "[]";
- StringBuffer buf = new StringBuffer("[");
- buf.append(a[0]);
- for (int i = 1; i < len; i++) {
- buf.append(", ");
- buf.append(a[i]);
- }
- buf.append("]");
- return buf.toString();
- }
-
- /**
- * replace an instruction handle with another instruction, in this case, a branch instruction.
- *
- * @param ih the instruction handle to replace.
- * @param branchInstruction the branch instruction to replace ih with
- * @param enclosingMethod where to find ih's instruction list.
- */
- public static void replaceInstruction(
- InstructionHandle ih,
- InstructionBranch branchInstruction,
- LazyMethodGen enclosingMethod)
- {
-
- InstructionList il = enclosingMethod.getBody();
- InstructionHandle fresh = il.append(ih, branchInstruction);
- deleteInstruction(ih, fresh, enclosingMethod);
- }
-
public static void replaceInstruction(
InstructionHandle ih,
InstructionList replacementInstructions,
// assumes that there is no already extant source line tag. Otherwise we'll have to be better.
public static void setSourceLine(InstructionHandle ih, int lineNumber) {
+ // OPTIMIZE LineNumberTag instances for the same line could be shared throughout a method...
ih.addTargeter(new LineNumberTag(lineNumber));
}
public static int makePublic(int i) {
return i & ~(Modifier.PROTECTED | Modifier.PRIVATE) | Modifier.PUBLIC;
}
- public static int makePrivate(int i) {
- return i & ~(Modifier.PROTECTED | Modifier.PUBLIC) | Modifier.PRIVATE;
- }
+
public static BcelVar[] pushAndReturnArrayOfVars(
ResolvedType[] proceedParamTypes,
InstructionList il,
}
// not yet used...
- public static boolean isSimple(Method method) {
- if (method.getCode()==null) return true;
- if (method.getCode().getCode().length>10) return false;
- InstructionList instrucs = new InstructionList(method.getCode().getCode()); // expensive!
- InstructionHandle InstrHandle = instrucs.getStart();
- while (InstrHandle != null) {
- Instruction Instr = InstrHandle.getInstruction();
- int opCode = Instr.opcode;
- // if current instruction is a branch instruction, see if it's a backward branch.
- // if it is return immediately (can't be trivial)
- if (Instr instanceof InstructionBranch) {
- // InstructionBranch BI = (InstructionBranch) Instr;
- if (Instr.getIndex() < 0) return false;
- } else if (Instr instanceof InvokeInstruction) {
- // if current instruction is an invocation, indicate that it can't be trivial
- return false;
- }
- InstrHandle = InstrHandle.getNext();
- }
- return true;
- }
+// public static boolean isSimple(Method method) {
+// if (method.getCode()==null) return true;
+// if (method.getCode().getCode().length>10) return false;
+// InstructionList instrucs = new InstructionList(method.getCode().getCode()); // expensive!
+// InstructionHandle InstrHandle = instrucs.getStart();
+// while (InstrHandle != null) {
+// Instruction Instr = InstrHandle.getInstruction();
+// int opCode = Instr.opcode;
+// // if current instruction is a branch instruction, see if it's a backward branch.
+// // if it is return immediately (can't be trivial)
+// if (Instr instanceof InstructionBranch) {
+// // InstructionBranch BI = (InstructionBranch) Instr;
+// if (Instr.getIndex() < 0) return false;
+// } else if (Instr instanceof InvokeInstruction) {
+// // if current instruction is an invocation, indicate that it can't be trivial
+// return false;
+// }
+// InstrHandle = InstrHandle.getNext();
+// }
+// return true;
+// }
+
+ public static Attribute bcelAttribute(AjAttribute a, ConstantPool pool) {
+ int nameIndex = pool.addUtf8(a.getNameString());
+ byte[] bytes = a.getBytes();
+ int length = bytes.length;
+
+ return new Unknown(nameIndex, length, bytes, pool);
+ }
}
\ No newline at end of file
+++ /dev/null
-/* *******************************************************************
- * 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.bcel;
-
-import java.io.File;
-import java.io.IOException;
-
-
-//XXX delete very soon
-public class ZipFileWeaver {
- File inFile;
- public ZipFileWeaver(File inFile) {
- super();
- this.inFile = inFile;
- }
-
- public void weave(BcelWeaver weaver, File outFile) throws IOException {
- int count = 0;
- long startTime = System.currentTimeMillis();
- weaver.addJarFile(inFile, new File("."),false);
- weaver.weave(outFile);
- long stopTime = System.currentTimeMillis();
-
-
- System.out.println("handled " + count + " entries, in " +
- (stopTime-startTime)/1000. + " seconds");
- }
-}
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
+import java.util.List;
+
+import org.aspectj.weaver.tools.WeavingAdaptor;
/**
* This class adds support to AspectJ for an OSGi environment
*/
public boolean isLocallyDefined(String classname);
+ /**
+ * Allow custom parsing of aop.xml or alternative mechanism for providing
+ * Definitions
+ *
+ * @param loader
+ * @param adaptor
+ * @return List containing 0 or more Definition instances
+ */
+ public List getDefinitions(final ClassLoader loader, WeavingAdaptor adaptor);
+
}
visitor.visitObject(loader.getParent());
super.accept(visitor);
}
-
+ public boolean shouldGoForIt() {
+ return true; // Zooooooooooom
+ }
}
+++ /dev/null
-/* *******************************************************************
- * Copyright (c) 2005 Contributors.
- * 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://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Adrian Colyer Initial implementation
- * ******************************************************************/
-package org.aspectj.weaver.ltw;
-
-import org.aspectj.weaver.IWeaver;
-
-/**
- * @author adrian
- *
- */
-public class LTWeaver implements IWeaver {
-
-}
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.World;
-
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
+import org.aspectj.weaver.ResolvedType;
/**
* @author colyer
*
public FuzzyBoolean matches(AnnotatedElement annotated) {
return left.matches(annotated).and(right.matches(annotated));
}
+
+ public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations ) {
+ return left.matches(annotated,parameterAnnotations).and(right.matches(annotated,parameterAnnotations));
+ }
public void resolve(World world) {
left.resolve(world);
AnnotationTypePattern newRight = right.parameterizeWith(typeVariableMap,w);
AndAnnotationTypePattern ret = new AndAnnotationTypePattern(newLeft,newRight);
ret.copyLocationFrom(this);
+ if (this.isForParameterAnnotationMatch()) ret.setForParameterAnnotationMatch();
return ret;
}
AnnotationTypePattern.read(s,context),
AnnotationTypePattern.read(s,context));
p.readLocation(context,s);
+ if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MINOR_AJ160) {
+ if (s.readBoolean()) p.setForParameterAnnotationMatch();
+ }
return p;
}
left.write(s);
right.write(s);
writeLocation(s);
+ s.writeBoolean(isForParameterAnnotationMatch());
}
public boolean equals(Object obj) {
if (!(obj instanceof AndAnnotationTypePattern)) return false;
AndAnnotationTypePattern other = (AndAnnotationTypePattern) obj;
- return (left.equals(other.left) && right.equals(other.right));
+ return (left.equals(other.left) && right.equals(other.right) && left.isForParameterAnnotationMatch()==right.isForParameterAnnotationMatch());
}
public int hashCode() {
int result = 17;
result = result*37 + left.hashCode();
result = result*37 + right.hashCode();
+ result = result*37 + (isForParameterAnnotationMatch()?0:1);
return result;
}
right.traverse(visitor,ret);
return ret;
}
+
+ public void setForParameterAnnotationMatch() {
+ left.setForParameterAnnotationMatch();
+ right.setForParameterAnnotationMatch();
+ }
}
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.World;
public static final AnnotationTypePattern ANY = new AnyAnnotationTypePattern();
public static final AnnotationTypePattern ELLIPSIS = new EllipsisAnnotationTypePattern();
+ public static final AnnotationTypePattern[] NONE = new AnnotationTypePattern[0];
+ private boolean isForParameterAnnotationMatch;
/**
* TODO: write, read, equals & hashcode both in annotation hierarachy and
}
public abstract FuzzyBoolean matches(AnnotatedElement annotated);
+ public abstract FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations);
public FuzzyBoolean fastMatches(AnnotatedElement annotated) {
return FuzzyBoolean.MAYBE;
throw new BCException("unknown TypePattern kind: " + key);
}
-}
-
-class AnyAnnotationTypePattern extends AnnotationTypePattern {
-
- public FuzzyBoolean fastMatches(AnnotatedElement annotated) {
- return FuzzyBoolean.YES;
- }
-
- public FuzzyBoolean matches(AnnotatedElement annotated) {
- return FuzzyBoolean.YES;
- }
-
- public void write(DataOutputStream s) throws IOException {
- s.writeByte(AnnotationTypePattern.ANY_KEY);
- }
-
- public void resolve(World world) {
- }
-
- public String toString() { return "@ANY"; }
+ public void setForParameterAnnotationMatch() { isForParameterAnnotationMatch = true; }
+ public boolean isForParameterAnnotationMatch() { return isForParameterAnnotationMatch; }
- public Object accept(PatternNodeVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-
- public boolean isAny() { return true; }
-
- public AnnotationTypePattern parameterizeWith(Map arg0,World w) {
- return this;
- }
}
+
class EllipsisAnnotationTypePattern extends AnnotationTypePattern {
public FuzzyBoolean matches(AnnotatedElement annotated) {
return FuzzyBoolean.NO;
}
+ public FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations) {
+ return FuzzyBoolean.NO;
+ }
+
public void write(DataOutputStream s) throws IOException {
s.writeByte(AnnotationTypePattern.ELLIPSIS_KEY);
}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * 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
+ * Andy Clement - extracted from AnnotationTypePattern
+ * ******************************************************************/
+ package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ResolvedType;
+
+public class AnyAnnotationTypePattern extends AnnotationTypePattern {
+
+ public FuzzyBoolean fastMatches(AnnotatedElement annotated) {
+ return FuzzyBoolean.YES;
+ }
+
+ public FuzzyBoolean matches(AnnotatedElement annotated) {
+ return FuzzyBoolean.YES;
+ }
+
+ public FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations) {
+ return FuzzyBoolean.YES;
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ s.writeByte(AnnotationTypePattern.ANY_KEY);
+ }
+
+ public void resolve(World world) {
+ }
+
+ public String toString() { return "@ANY"; }
+
+ public Object accept(PatternNodeVisitor visitor, Object data) {
+ return visitor.visit(this, data);
+ }
+
+ public boolean isAny() { return true; }
+
+ public AnnotationTypePattern parameterizeWith(Map arg0,World w) {
+ return this;
+ }
+}
\ No newline at end of file
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.util.FuzzyBoolean;
-import org.aspectj.weaver.BetaException;
+import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
import org.aspectj.weaver.ResolvedType;
}
return findResidueNoEllipsis(shadow, state, patternsWithoutEllipsis);
} else {
- throw new BetaException("unimplemented");
+ throw new BCException("unimplemented");
}
}
case '@':
case '<':
case '>':
+ case '=':
case '?':
tokens.add(BasicToken.makeOperator(makeString(ch), i-1, i-1));
continue;
* @param annotationType
*/
public BindingAnnotationTypePattern(UnresolvedType annotationType, int index) {
- super(annotationType);
+ super(annotationType,null);
this.formalIndex = index;
}
public AnnotationTypePattern remapAdviceFormals(IntMap bindings) {
if (!bindings.hasKey(formalIndex)) {
- return new ExactAnnotationTypePattern(annotationType);
+ return new ExactAnnotationTypePattern(annotationType,null);
} else {
int newFormalIndex = bindings.get(formalIndex);
return new BindingAnnotationTypePattern(annotationType, newFormalIndex);
boolean isBelow;// Is this cflowbelow?
private int[] freeVars;
- private static Hashtable cflowFields = new Hashtable();
- private static Hashtable cflowBelowFields = new Hashtable();
/**
* Used to indicate that we're in the context of a cflow when concretizing if's
if (freeVars==null || freeVars.length == 0) { // No state, so don't use a stack, use a counter.
ResolvedMember localCflowField = null;
- Object field = getCflowfield(concreteEntry,concreteAspect,"counter");
+ Object field = getCflowfield(xcut, concreteEntry, concreteAspect, "counter");
// Check if we have already got a counter for this cflow pointcut
if (field != null) {
concreteAspect.crosscuttingMembers.addConcreteShadowMunger(
Advice.makeCflowEntry(world,concreteEntry,isBelow,localCflowField,freeVars==null?0:freeVars.length,innerCflowEntries,inAspect));
- putCflowfield(concreteEntry,concreteAspect,localCflowField,"counter"); // Remember it
+ putCflowfield(xcut,concreteEntry,concreteAspect,localCflowField,"counter"); // Remember it
}
Pointcut ret = new ConcreteCflowPointcut(localCflowField, null,true);
slots.add(slot);
}
ResolvedMember localCflowField = null;
- Object field = getCflowfield(concreteEntry,concreteAspect,"stack");
+ Object field = getCflowfield(xcut,concreteEntry,concreteAspect,"stack");
if (field != null) {
localCflowField = (ResolvedMember)field;
} else {
concreteAspect.crosscuttingMembers.addTypeMunger(
world.makeCflowStackFieldAdder(localCflowField));
- putCflowfield(concreteEntry,concreteAspect,localCflowField,"stack");
+ putCflowfield(xcut,concreteEntry,concreteAspect,localCflowField,"stack");
}
Pointcut ret = new ConcreteCflowPointcut(localCflowField, slots,false);
ret.copyLocationFrom(this);
}
- public static void clearCaches() {
- cflowFields.clear();
- cflowBelowFields.clear();
- }
private String getKey(Pointcut p,ResolvedType a,String stackOrCounter) {
StringBuffer sb = new StringBuffer();
return sb.toString();
}
- private Object getCflowfield(Pointcut pcutkey, ResolvedType concreteAspect,String stackOrCounter) {
+ private Object getCflowfield(CrosscuttingMembers xcut, Pointcut pcutkey, ResolvedType concreteAspect,String stackOrCounter) {
String key = getKey(pcutkey,concreteAspect,stackOrCounter);
Object o =null;
- if (isBelow) o = cflowBelowFields.get(key);
- else o = cflowFields.get(key);
+ if (isBelow) o = xcut.getCflowBelowFields().get(key);
+ else o = xcut.getCflowFields().get(key);
//System.err.println("Retrieving for key "+key+" returning "+o);
return o;
}
- private void putCflowfield(Pointcut pcutkey,ResolvedType concreteAspect,Object o,String stackOrCounter) {
+ private void putCflowfield(CrosscuttingMembers xcut, Pointcut pcutkey,ResolvedType concreteAspect,Object o,String stackOrCounter) {
String key = getKey(pcutkey,concreteAspect,stackOrCounter);
//System.err.println("Storing cflow field for key"+key);
if (isBelow) {
- cflowBelowFields.put(key,o);
+ xcut.getCflowBelowFields().put(key,o);
} else {
- cflowFields.put(key,o);
+ xcut.getCflowFields().put(key,o);
}
}
return visitor.visit(this, data);
}
- public static void clearCaches(ResolvedType aspectType) {
- //System.err.println("Wiping entries starting "+aspectType.getName());
- String key = aspectType.getName()+"::";
- wipeKeys(key,cflowFields);
- wipeKeys(key,cflowBelowFields);
- }
-
- private static void wipeKeys(String keyPrefix,Hashtable ht) {
- Enumeration keys = ht.keys();
- List forRemoval = new ArrayList();
- while (keys.hasMoreElements()) {
- String s = (String)keys.nextElement();
- if (s.startsWith(keyPrefix)) forRemoval.add(s);
- }
- for (Iterator iter = forRemoval.iterator(); iter.hasNext();) {
- String element = (String) iter.next();
- ht.remove(element);
- }
- }
}
import java.io.DataOutputStream;
import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.AnnotationX;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.ReferenceType;
+import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.TypeVariableReference;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.WeaverMessages;
import org.aspectj.weaver.World;
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
/**
* Matches an annotation of a given type
protected String formalName;
protected boolean resolved = false;
private boolean bindingPattern = false;
+ private Map annotationValues;
/**
+ * @param annotationValues
*
*/
- public ExactAnnotationTypePattern(UnresolvedType annotationType) {
+ // OPTIMIZE is annotationtype really unresolved???? surely it is resolved by now...
+ public ExactAnnotationTypePattern(UnresolvedType annotationType, Map annotationValues) {
+ this.annotationType = annotationType;
+ this.annotationValues = annotationValues;
+ this.resolved = (annotationType instanceof ResolvedType);
+ }
+
+ // Used when deserializing, values will be added
+ private ExactAnnotationTypePattern(UnresolvedType annotationType) {
this.annotationType = annotationType;
this.resolved = (annotationType instanceof ResolvedType);
}
public UnresolvedType getAnnotationType() {
return annotationType;
}
+
+ public Map getAnnotationValues() {
+ return annotationValues;
+ }
public FuzzyBoolean fastMatches(AnnotatedElement annotated) {
- if (annotated.hasAnnotation(annotationType)) {
+ if (annotated.hasAnnotation(annotationType) && annotationValues == null) {
return FuzzyBoolean.YES;
} else {
// could be inherited, but we don't know that until we are
}
public FuzzyBoolean matches(AnnotatedElement annotated) {
- boolean checkSupers = false;
- if (getResolvedAnnotationType().hasAnnotation(UnresolvedType.AT_INHERITED)) {
- if (annotated instanceof ResolvedType) {
- checkSupers = true;
- }
- }
-
- if (annotated.hasAnnotation(annotationType)) {
- if (annotationType instanceof ReferenceType) {
- ReferenceType rt = (ReferenceType)annotationType;
- if (rt.getRetentionPolicy()!=null && rt.getRetentionPolicy().equals("SOURCE")) {
- rt.getWorld().getMessageHandler().handleMessage(
- MessageUtil.warn(WeaverMessages.format(WeaverMessages.NO_MATCH_BECAUSE_SOURCE_RETENTION,annotationType,annotated),getSourceLocation()));
- return FuzzyBoolean.NO;
+ return matches(annotated,null);
+ }
+
+ public FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations) {
+ if (!isForParameterAnnotationMatch()) {
+ boolean checkSupers = false;
+ if (getResolvedAnnotationType().hasAnnotation(UnresolvedType.AT_INHERITED)) {
+ if (annotated instanceof ResolvedType) {
+ checkSupers = true;
}
}
- return FuzzyBoolean.YES;
- } else if (checkSupers) {
- ResolvedType toMatchAgainst = ((ResolvedType) annotated).getSuperclass();
- while (toMatchAgainst != null) {
- if (toMatchAgainst.hasAnnotation(annotationType)) return FuzzyBoolean.YES;
- toMatchAgainst = toMatchAgainst.getSuperclass();
+
+ if (annotated.hasAnnotation(annotationType)) {
+ if (annotationType instanceof ReferenceType) {
+ ReferenceType rt = (ReferenceType)annotationType;
+ if (rt.getRetentionPolicy()!=null && rt.getRetentionPolicy().equals("SOURCE")) {
+ rt.getWorld().getMessageHandler().handleMessage(
+ MessageUtil.warn(WeaverMessages.format(WeaverMessages.NO_MATCH_BECAUSE_SOURCE_RETENTION,annotationType,annotated),getSourceLocation()));
+ return FuzzyBoolean.NO;
+ }
+ }
+
+
+ // Are we also matching annotation values?
+ if (annotationValues!=null) {
+ AnnotationX theAnnotation = annotated.getAnnotationOfType(annotationType);
+
+ // Check each one
+ Set keys = annotationValues.keySet();
+ for (Iterator keyIter = keys.iterator(); keyIter.hasNext();) {
+ String k = (String) keyIter.next();
+ String v = (String)annotationValues.get(k);
+ if (theAnnotation.hasNamedValue(k)) {
+ // Simple case, value is 'name=value' and the annotation specified the same thing
+ if (!theAnnotation.hasNameValuePair(k,v)) {
+ return FuzzyBoolean.NO;
+ }
+ } else {
+ // Complex case, look at the default value
+ ResolvedMember[] ms = ((ResolvedType)annotationType).getDeclaredMethods();
+ boolean foundMatch = false;
+ for (int i=0; i<ms.length && !foundMatch;i++) {
+ if (ms[i].isAbstract() && ms[i].getParameterTypes().length==0 && ms[i].getName().equals(k)) {
+ // we might be onto something
+ String s= ms[i].getAnnotationDefaultValue();
+ if (s!=null && s.equals(v)) foundMatch=true;;
+ }
+ }
+ if (!foundMatch)
+ return FuzzyBoolean.NO;
+ }
+ }
+ }
+ return FuzzyBoolean.YES;
+ } else if (checkSupers) {
+ ResolvedType toMatchAgainst = ((ResolvedType) annotated).getSuperclass();
+ while (toMatchAgainst != null) {
+ if (toMatchAgainst.hasAnnotation(annotationType)) {
+ // Are we also matching annotation values?
+ if (annotationValues!=null) {
+ AnnotationX theAnnotation = toMatchAgainst.getAnnotationOfType(annotationType);
+
+ // Check each one
+ Set keys = annotationValues.keySet();
+ for (Iterator keyIter = keys.iterator(); keyIter.hasNext();) {
+ String k = (String) keyIter.next();
+ String v = (String)annotationValues.get(k);
+ if (theAnnotation.hasNamedValue(k)) {
+ // Simple case, value is 'name=value' and the annotation specified the same thing
+ if (!theAnnotation.hasNameValuePair(k,v)) {
+ return FuzzyBoolean.NO;
+ }
+ } else {
+ // Complex case, look at the default value
+ ResolvedMember[] ms = ((ResolvedType)annotationType).getDeclaredMethods();
+ boolean foundMatch = false;
+ for (int i=0; i<ms.length && !foundMatch;i++) {
+ if (ms[i].isAbstract() && ms[i].getParameterTypes().length==0 && ms[i].getName().equals(k)) {
+ // we might be onto something
+ String s= ms[i].getAnnotationDefaultValue();
+ if (s!=null && s.equals(v)) foundMatch=true;;
+ }
+ }
+ if (!foundMatch)
+ return FuzzyBoolean.NO;
+ }
+ }
+ }
+ return FuzzyBoolean.YES;
+ }
+ toMatchAgainst = toMatchAgainst.getSuperclass();
+ }
+ }
+ } else {
+ // check parameter annotations
+ if (parameterAnnotations==null) return FuzzyBoolean.NO;
+ for (int i = 0; i < parameterAnnotations.length; i++) {
+ if (annotationType.equals(parameterAnnotations[i])) {
+ // Are we also matching annotation values?
+ if (annotationValues!=null) {
+ parameterAnnotations[i].getWorld().getMessageHandler().handleMessage(
+ MessageUtil.error("Compiler limitation: annotation value matching for parameter annotations not yet supported"));
+ return FuzzyBoolean.NO;
+ }
+ return FuzzyBoolean.YES;
+ }
}
- }
+ }
+
+
return FuzzyBoolean.NO;
}
public void resolve(World world) {
- if (!resolved) annotationType = annotationType.resolve(world);
+ if (!resolved) {
+ annotationType = annotationType.resolve(world);
+ }
resolved = true;
}
binding.copyLocationFrom(this);
bindings.register(binding, scope);
binding.resolveBinding(scope.getWorld());
+ if (isForParameterAnnotationMatch()) binding.setForParameterAnnotationMatch();
return binding;
}
} else if (annotationType.isParameterizedType()) {
newAnnotationType = annotationType.parameterize(typeVariableMap);
}
- ExactAnnotationTypePattern ret = new ExactAnnotationTypePattern(newAnnotationType);
+ ExactAnnotationTypePattern ret = new ExactAnnotationTypePattern(newAnnotationType,annotationValues);
ret.formalName = formalName;
ret.bindingPattern = bindingPattern;
ret.copyLocationFrom(this);
+ if (isForParameterAnnotationMatch()) ret.setForParameterAnnotationMatch();
return ret;
}
annotationType.write(s);
}
writeLocation(s);
+ s.writeBoolean(isForParameterAnnotationMatch());
+ if (annotationValues==null) {
+ s.writeInt(0);
+ } else {
+ s.writeInt(annotationValues.size());
+ Set key = annotationValues.keySet();
+ for (Iterator keys = key.iterator(); keys.hasNext();) {
+ String k = (String) keys.next();
+ s.writeUTF(k);
+ s.writeUTF((String)annotationValues.get(k));
+ }
+ }
}
public static AnnotationTypePattern read(VersionedDataInputStream s,ISourceContext context) throws IOException {
- AnnotationTypePattern ret;
+ ExactAnnotationTypePattern ret;
byte version = s.readByte();
if (version > VERSION) {
throw new BCException("ExactAnnotationTypePattern was written by a newer version of AspectJ");
ret = new ExactAnnotationTypePattern(UnresolvedType.read(s));
}
ret.readLocation(context,s);
+ if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160) {
+ if (s.readBoolean()) ret.setForParameterAnnotationMatch();
+ }
+ if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160M2) {
+ int annotationValueCount = s.readInt();
+ if (annotationValueCount>0) {
+ Map aValues = new HashMap();
+ for (int i=0;i<annotationValueCount;i++) {
+ String key = s.readUTF();
+ String val = s.readUTF();
+ aValues.put(key,val);
+ }
+ ret.annotationValues = aValues;
+ }
+ }
return ret;
}
public boolean equals(Object obj) {
if (!(obj instanceof ExactAnnotationTypePattern)) return false;
ExactAnnotationTypePattern other = (ExactAnnotationTypePattern) obj;
- return (other.annotationType.equals(annotationType));
+ return (other.annotationType.equals(annotationType)) && isForParameterAnnotationMatch()==other.isForParameterAnnotationMatch();
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
- return annotationType.hashCode();
+ return annotationType.hashCode()*37+(isForParameterAnnotationMatch()?0:1);
}
public String toString() {
typeMatch = matchesTypeVariable((TypeVariableReferenceType)matchType);
}
annotationPattern.resolve(matchType.getWorld());
- boolean annMatch = this.annotationPattern.matches(matchType).alwaysTrue();
+ boolean annMatch = false;
+ if (matchType.temporaryAnnotationTypes!=null) {
+ annMatch = annotationPattern.matches(matchType,matchType.temporaryAnnotationTypes).alwaysTrue();
+ } else {
+ annMatch = annotationPattern.matches(matchType).alwaysTrue();
+ }
return (typeMatch && annMatch);
}
typeMatch = matchesTypeVariable((TypeVariableReferenceType)matchType);
}
annotationPattern.resolve(matchType.getWorld());
- boolean annMatch = this.annotationPattern.matches(annotatedType).alwaysTrue();
+ boolean annMatch = false;
+ if (annotatedType.temporaryAnnotationTypes!=null) {
+ annMatch = annotationPattern.matches(annotatedType,annotatedType.temporaryAnnotationTypes).alwaysTrue();
+ } else {
+ annMatch = annotationPattern.matches(annotatedType).alwaysTrue();
+ }
return (typeMatch && annMatch);
}
// true if (matchType instanceof this.type)
public FuzzyBoolean matchesInstanceof(ResolvedType matchType) {
// in our world, Object is assignable from anything
+ annotationPattern.resolve(matchType.getWorld());
if (type.equals(ResolvedType.OBJECT))
return FuzzyBoolean.YES.and(annotationPattern.matches(matchType));
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.AnnotatedElement;
import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.World;
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
public class NotAnnotationTypePattern extends AnnotationTypePattern {
return negatedPattern.matches(annotated).not();
}
+ public FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations) {
+ return negatedPattern.matches(annotated,parameterAnnotations).not();
+ }
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.AnnotationTypePattern#resolve(org.aspectj.weaver.World)
*/
AnnotationTypePattern newNegatedPattern = negatedPattern.parameterizeWith(typeVariableMap,w);
NotAnnotationTypePattern ret = new NotAnnotationTypePattern(newNegatedPattern);
ret.copyLocationFrom(this);
+ if (this.isForParameterAnnotationMatch()) ret.setForParameterAnnotationMatch();
return ret;
}
s.writeByte(AnnotationTypePattern.NOT);
negatedPattern.write(s);
writeLocation(s);
+ s.writeBoolean(isForParameterAnnotationMatch());
}
public static AnnotationTypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
AnnotationTypePattern ret = new NotAnnotationTypePattern(AnnotationTypePattern.read(s,context));
ret.readLocation(context,s);
+ if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MINOR_AJ160) {
+ if (s.readBoolean()) ret.setForParameterAnnotationMatch();
+ }
return ret;
}
public boolean equals(Object obj) {
if (!(obj instanceof NotAnnotationTypePattern)) return false;
NotAnnotationTypePattern other = (NotAnnotationTypePattern) obj;
- return other.negatedPattern.equals(negatedPattern);
+ return other.negatedPattern.equals(negatedPattern) && other.isForParameterAnnotationMatch()==isForParameterAnnotationMatch();
}
public int hashCode() {
int result = 17 + 37*negatedPattern.hashCode();
+ result = 37*result +(isForParameterAnnotationMatch()?0:1);
return result;
}
negatedPattern.traverse(visitor,ret);
return ret;
}
+
+ public void setForParameterAnnotationMatch() {
+ negatedPattern.setForParameterAnnotationMatch();
+ }
}
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.AnnotatedElement;
import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.World;
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
public class OrAnnotationTypePattern extends AnnotationTypePattern {
public FuzzyBoolean matches(AnnotatedElement annotated) {
return left.matches(annotated).or(right.matches(annotated));
}
+
+ public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations ) {
+ return left.matches(annotated,parameterAnnotations).or(right.matches(annotated,parameterAnnotations));
+ }
public void resolve(World world) {
left.resolve(world);
AnnotationTypePattern newRight = right.parameterizeWith(typeVariableMap,w);
OrAnnotationTypePattern ret = new OrAnnotationTypePattern(newLeft,newRight);
ret.copyLocationFrom(this);
+ if (isForParameterAnnotationMatch()) ret.setForParameterAnnotationMatch();
return ret;
}
AnnotationTypePattern.read(s,context),
AnnotationTypePattern.read(s,context));
p.readLocation(context,s);
+ if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MINOR_AJ160) {
+ if (s.readBoolean()) p.setForParameterAnnotationMatch();
+ }
return p;
}
left.write(s);
right.write(s);
writeLocation(s);
+ s.writeBoolean(isForParameterAnnotationMatch());
}
public boolean equals(Object obj) {
if (!(obj instanceof OrAnnotationTypePattern)) return false;
OrAnnotationTypePattern other = (OrAnnotationTypePattern) obj;
- return (left.equals(other.left) && right.equals(other.right));
+ return (left.equals(other.left) && right.equals(other.right)) && isForParameterAnnotationMatch()==other.isForParameterAnnotationMatch();
}
public int hashCode() {
int result = 17;
result = result*37 + left.hashCode();
result = result*37 + right.hashCode();
+ result = result*37 + (isForParameterAnnotationMatch()?0:1);
return result;
}
public AnnotationTypePattern getLeft() { return left; }
public AnnotationTypePattern getRight() { return right; }
+ public void setForParameterAnnotationMatch() {
+ left.setForParameterAnnotationMatch();
+ right.setForParameterAnnotationMatch();
+ }
+
}
*******************************************************************************/
package org.aspectj.weaver.patterns;
-import org.aspectj.weaver.Member;
/**
* A Pointcut or TypePattern visitor
// Catch-all
Object visit(PatternNode node, Object data);
- /**
- * A sample toString like visitor that helps understanding the AST tree structure organization
- *
- * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
- */
- static class DumpPointcutVisitor implements PatternNodeVisitor {
-
- private StringBuffer sb = new StringBuffer();
- public String get() {
- return sb.toString();
- }
-
- private void append(Object o) {
- sb.append(o.toString());
- }
-
- private void append(char c) {
- sb.append(c);
- }
-
- /**
- * This method helps maintaining the API and raises warning when PatternNode subclasses do not
- * implement the visitor pattern
- *
- * @param node
- * @param data
- * @return
- */
- public Object visit(PatternNode node, Object data) {
- System.err.println("Should implement: " + node.getClass());
- return null;
- }
-
- public Object visit(AnyTypePattern node, Object data) {
- append('*');
- return null;
- }
-
- public Object visit(NoTypePattern node, Object data) {
- append(node.toString());//TODO no idea when this one is used
- return null;
- }
-
- public Object visit(EllipsisTypePattern node, Object data) {
- append(node.toString());
- return null;
- }
-
- public Object visit(AnyWithAnnotationTypePattern node, Object data) {
- node.annotationPattern.accept(this, data);
- append(" *");
- return null;
- }
-
- public Object visit(AnyAnnotationTypePattern node, Object data) {
- //@ANY : ignore
- append('*');
- return null;
- }
-
- public Object visit(EllipsisAnnotationTypePattern node, Object data) {
- append("..");
- return null;
- }
-
- public Object visit(AndAnnotationTypePattern node, Object data) {
- node.getLeft().accept(this, data);
- append(' ');
- node.getRight().accept(this, data);
- return null;
- }
-
- public Object visit(AndPointcut node, Object data) {
- append('(');
- node.getLeft().accept(this, data);
- append(" && ");
- node.getRight().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(AndTypePattern node, Object data) {
- append('(');
- node.getLeft().accept(this, data);
- append(" && ");
- node.getRight().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(AnnotationPatternList node, Object data) {
- AnnotationTypePattern[] annotations = node.getAnnotationPatterns();
- for (int i = 0; i < annotations.length; i++) {
- if (i>0) append(", ");//Note: list is ",", and is " " separated for annotations
- annotations[i].accept(this, data);
- }
- return null;
- }
-
- public Object visit(AnnotationPointcut node, Object data) {
- append("@annotation(");
- node.getAnnotationTypePattern().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(ArgsAnnotationPointcut node, Object data) {
- append("@args(");
- node.getArguments().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(ArgsPointcut node, Object data) {
- append("args(");
- node.getArguments().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(BindingAnnotationTypePattern node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(BindingTypePattern node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(CflowPointcut node, Object data) {
- append(node.isCflowBelow()?"cflowbelow(":"cflow(");
- node.getEntry().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(ExactAnnotationTypePattern node, Object data) {
- //append('@'); // since @annotation(@someAnno) cannot be parsed anymore
- append(node.getAnnotationType().getName());
- return null;
- }
-
- public Object visit(ExactTypePattern node, Object data) {
- if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
- append('(');
- node.getAnnotationPattern().accept(this, data);
- append(' ');
- }
-
- String typeString = node.getType().toString();
- if (node.isVarArgs()) typeString = typeString.substring(0, typeString.lastIndexOf('['));//TODO AV - ugly
- append(typeString);
- if (node.isIncludeSubtypes()) append('+');
- if (node.isVarArgs()) append("...");
- if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
- append(')');
- }
- return null;
- }
-
- public Object visit(KindedPointcut node, Object data) {
- append(node.getKind().getSimpleName());
- append('(');
- node.getSignature().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(ModifiersPattern node, Object data) {
- append(node.toString());//note: node takes care of forbidden mods
- return null;
- }
-
- public Object visit(NamePattern node, Object data) {
- append(node.toString());
- return null;
- }
-
- public Object visit(NotAnnotationTypePattern node, Object data) {
- append("!");
- node.getNegatedPattern().accept(this, data);
- return null;
- }
-
- public Object visit(NotPointcut node, Object data) {
- append("!(");
- node.getNegatedPointcut().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(NotTypePattern node, Object data) {
- append("!(");
- node.getNegatedPattern().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(OrAnnotationTypePattern node, Object data) {
- append('(');
- node.getLeft().accept(this, data);
- append(" || ");
- node.getRight().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(OrPointcut node, Object data) {
- append('(');
- node.getLeft().accept(this, data);
- append(" || ");
- node.getRight().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(OrTypePattern node, Object data) {
- append('(');
- node.getLeft().accept(this, data);
- append(" || ");
- node.getRight().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(ReferencePointcut node, Object data) {
- append(node.toString());
- return null;
- }
-
- public Object visit(SignaturePattern node, Object data) {
- if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
- node.getAnnotationPattern().accept(this, data);
- append(' ');
- }
-
- if (node.getModifiers() != ModifiersPattern.ANY) {
- node.getModifiers().accept(this, data);
- append(' ');
- }
-
- if (node.getKind() == Member.STATIC_INITIALIZATION) {
- node.getDeclaringType().accept(this, data);
- } else if (node.getKind() == Member.HANDLER) {
- append("handler(");
- node.getParameterTypes().get(0).accept(this, data);//Note: we know we have 1 child
- append(')');
- } else {
- if (!(node.getKind() == Member.CONSTRUCTOR)) {
- node.getReturnType().accept(this, data);
- append(' ');
- }
- if (node.getDeclaringType() != TypePattern.ANY) {
- node.getDeclaringType().accept(this, data);
- append('.');
- }
- if (node.getKind() == Member.CONSTRUCTOR) {
- append("new");
- } else {
- node.getName().accept(this, data);
- }
- if (node.getKind() == Member.METHOD || node.getKind() == Member.CONSTRUCTOR) {
- append('(');
- node.getParameterTypes().accept(this, data);
- append(')');
- }
- if (node.getThrowsPattern() != null) {
- append(' ');
- node.getThrowsPattern().accept(this, data);
- }
- }
- return null;
- }
-
- public Object visit(ThisOrTargetAnnotationPointcut node, Object data) {
- append(node.isThis() ? "@this(" : "@target(");
- node.getAnnotationTypePattern().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(ThisOrTargetPointcut node, Object data) {
- append(node.isThis() ? "this(" : "target(");
- node.getType().accept(this, data);
- append(')');
- return null;
- }
-
- // Note: a visitor instance is not thread safe so should not be shared
- private boolean inThrowsForbidden = false;
-
- public Object visit(ThrowsPattern node, Object data) {
- if (node == ThrowsPattern.ANY) return null;
-
- append("throws ");
- node.getRequired().accept(this, data);
- if (node.getForbidden().size() > 0) {
- // a hack since throws !(A, B) cannot be parsed
- try {
- inThrowsForbidden = true;
- node.getForbidden().accept(this, data);
- } finally {
- inThrowsForbidden = false;
- }
- }
- return null;
- }
-
- public Object visit(TypePatternList node, Object data) {
- if (node.getTypePatterns().length == 0) return null;
-
- TypePattern[] typePatterns = node.getTypePatterns();
- for (int i = 0; i < typePatterns.length; i++) {
- TypePattern typePattern = typePatterns[i];
- if (i > 0) append(", ");
- if (inThrowsForbidden) append('!');
- typePattern.accept(this, data);
- }
- return null;
- }
-
- public Object visit(WildAnnotationTypePattern node, Object data) {
- append("@(");
- node.getTypePattern().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(WildTypePattern node, Object data) {
- if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
- append('(');
- node.getAnnotationPattern().accept(this, data);
- append(' ');
- }
- NamePattern[] namePatterns = node.getNamePatterns();
- for (int i=0; i < namePatterns.length; i++) {
- if (namePatterns[i] == null) {
- append('.');//FIXME mh, error prone, can't we have a nullNamePattern ?
- } else {
- if (i > 0) append('.');
- namePatterns[i].accept(this, data);
- }
- }
- if (node.isIncludeSubtypes()) append('+');
- if (node.isVarArgs()) append("...");
- if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
- append(')');
- }
- return null;
- }
-
- public Object visit(WithinAnnotationPointcut node, Object data) {
- append("@within(");
- node.getAnnotationTypePattern().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(WithinCodeAnnotationPointcut node, Object data) {
- append("@withincode(");
- node.getAnnotationTypePattern().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(WithinPointcut node, Object data) {
- append("within(");
- node.getTypePattern().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(WithincodePointcut node, Object data) {
- append("withincode(");
- node.getSignature().accept(this, data);
- append(')');
- return null;
- }
-
- public Object visit(Pointcut.MatchesNothingPointcut node, Object data) {
- append("");//TODO shouldn't that be a "false" ?
- return null;
- }
-
-
- //-------------- perX
-
- public Object visit(PerCflow node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(PerFromSuper node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(PerObject node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(PerSingleton node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(PerTypeWithin node, Object data) {
- append(node);
- return null;
- }
-
- // ------------- declare X
-
- public Object visit(DeclareAnnotation node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(DeclareErrorOrWarning node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(DeclareParents node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(DeclarePrecedence node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(DeclareSoft node, Object data) {
- append(node);
- return null;
- }
-
- // ----------- misc
-
- public Object visit(ConcreteCflowPointcut node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(HandlerPointcut node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(IfPointcut node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(TypeVariablePattern node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(TypeVariablePatternList node, Object data) {
- append(node);
- return null;
- }
-
- public Object visit(HasMemberTypePattern node, Object data) {
- append(node);
- return null;
- }
-
- public static void check(String s) {
- check(Pointcut.fromString(s), false);
- }
-
- public static void check(PatternNode pc, boolean isTypePattern) {
- DumpPointcutVisitor v1 = new DumpPointcutVisitor();
- pc.accept(v1, null);
-
- DumpPointcutVisitor v2 = new DumpPointcutVisitor();
- final PatternNode pc2;
- if (isTypePattern) {
- pc2 = new PatternParser(v1.get()).parseTypePattern();
- } else {
- pc2 = Pointcut.fromString(v1.get());
- }
- pc2.accept(v2, null);
-
- // at second parsing, the String form stay stable when parsed and parsed again
- if (! v1.get().equals(v2.get())) {
- throw new ParserException("Unstable back parsing for '"+pc+"', got '" + v1.get() + "' and '" + v2.get() + "'", null);
- }
- }
-
- public static void main(String args[]) throws Throwable {
- String[] s = new String[]{
- //"@args(Foo, Goo, *, .., Moo)",
- //"execution(* *())",
- //"call(* *(int, Integer...))",
- //"staticinitialization(@(Foo) @(Boo) @(Goo) Moo)",
- "(if(true) && set(int BaseApp.i))"
-
- };
- for (int i = 0; i < s.length; i++) {
- check(s[i]);
- }
- }
-
- }
-
}
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.MemberKind;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.UnresolvedType;
/** extension handlers used in weaver tools API only */
private Set pointcutDesignatorHandlers = Collections.EMPTY_SET;
private ReflectionWorld world;
+
+ private AnnotationTypePattern[] parameterAnnotationTypePatterns;
/**
* Constructor for PatternParser.
*/
eat(":");
allowHasTypePatterns = true;
- TypePattern p = parseTypePattern(false);
+ TypePattern p = parseTypePattern(false,false);
allowHasTypePatterns = false;
IToken t = tokenSource.next();
if (!(t.getString().equals("extends") || t.getString().equals("implements"))) {
AnnotationTypePattern.ANY));
} else if (kind.equals("handler")) {
eat("(");
- TypePattern typePat = parseTypePattern(false);
+ TypePattern typePat = parseTypePattern(false,false);
eat(")");
p = new HandlerPointcut(typePat);
} else if (kind.equals("lock") || kind.equals("unlock")) {
p = new KindedPointcut(Shadow.Initialization, sig);
} else if (kind.equals("staticinitialization")) {
eat("(");
- TypePattern typePat = parseTypePattern(false);
+ TypePattern typePat = parseTypePattern(false,false);
eat(")");
p = new KindedPointcut(Shadow.StaticInitialization,
new SignaturePattern(Member.STATIC_INITIALIZATION, ModifiersPattern.ANY,
*/
private Pointcut parseArgsPointcut() {
//parseIdentifier();
- TypePatternList arguments = parseArgumentsPattern();
+ TypePatternList arguments = parseArgumentsPattern(false);
return new ArgsPointcut(arguments);
}
throw new ParserException("(",tokenSource.peek(-1));
}
- TypePatternList arguments = parseArgumentsPattern();
+ TypePatternList arguments = parseArgumentsPattern(false);
return new ReferencePointcut(onType, simpleName, arguments);
}
}
public TypePattern parseTypePattern() {
- return parseTypePattern(false);
+ return parseTypePattern(false,false);
}
- public TypePattern parseTypePattern(boolean insideTypeParameters) {
- TypePattern p = parseAtomicTypePattern(insideTypeParameters);
+ public TypePattern parseTypePattern(boolean insideTypeParameters,boolean parameterAnnotationsPossible) {
+ TypePattern p = parseAtomicTypePattern(insideTypeParameters,parameterAnnotationsPossible);
if (maybeEat("&&")) {
- p = new AndTypePattern(p, parseNotOrTypePattern(insideTypeParameters));
+ p = new AndTypePattern(p, parseNotOrTypePattern(insideTypeParameters,parameterAnnotationsPossible));
}
if (maybeEat("||")) {
- p = new OrTypePattern(p, parseTypePattern(insideTypeParameters));
+ p = new OrTypePattern(p, parseTypePattern(insideTypeParameters,parameterAnnotationsPossible));
}
return p;
}
- private TypePattern parseNotOrTypePattern(boolean insideTypeParameters) {
- TypePattern p = parseAtomicTypePattern(insideTypeParameters);
+ private TypePattern parseNotOrTypePattern(boolean insideTypeParameters,boolean parameterAnnotationsPossible) {
+ TypePattern p = parseAtomicTypePattern(insideTypeParameters,parameterAnnotationsPossible);
if (maybeEat("&&")) {
- p = new AndTypePattern(p, parseTypePattern(insideTypeParameters));
+ p = new AndTypePattern(p, parseTypePattern(insideTypeParameters,parameterAnnotationsPossible));
}
return p;
}
- private TypePattern parseAtomicTypePattern(boolean insideTypeParameters) {
- AnnotationTypePattern ap = maybeParseAnnotationPattern();
+
+ // Need to differentiate in here between two kinds of annotation pattern - depending on where the ( is
+
+ private TypePattern parseAtomicTypePattern(boolean insideTypeParameters,boolean parameterAnnotationsPossible) {
+ AnnotationTypePattern ap = maybeParseAnnotationPattern(); // might be parameter annotation pattern or type annotation pattern
if (maybeEat("!")) {
//int startPos = tokenSource.peek(-1).getStart();
//??? we lose source location for true start of !type
- TypePattern p = new NotTypePattern(parseAtomicTypePattern(insideTypeParameters));
- p = setAnnotationPatternForTypePattern(p,ap);
+
+ // An annotation, if processed, is outside of the Not - so here we have to build
+ // an And pattern containing the annotation and the not as left and right children
+ // *unless* the annotation pattern was just 'Any' then we can skip building the
+ // And and just return the Not directly (pr228980)
+ TypePattern p = null;
+ TypePattern tp = parseAtomicTypePattern(insideTypeParameters,parameterAnnotationsPossible);
+ if (!(ap instanceof AnyAnnotationTypePattern)) {
+ p = new NotTypePattern(tp);
+ p = new AndTypePattern(setAnnotationPatternForTypePattern(TypePattern.ANY,ap,false),p);
+ } else {
+ p = new NotTypePattern(tp);
+ }
return p;
}
if (maybeEat("(")) {
- TypePattern p = parseTypePattern(insideTypeParameters);
- p = setAnnotationPatternForTypePattern(p,ap);
+ TypePattern p = parseTypePattern(insideTypeParameters,false);
+ if ((p instanceof NotTypePattern) && !(ap instanceof AnyAnnotationTypePattern)) {
+ // dont set the annotation on it, we don't want the annotation to be
+ // considered as part of the not, it is outside the not (pr228980)
+ TypePattern tp = setAnnotationPatternForTypePattern(TypePattern.ANY, ap, parameterAnnotationsPossible);
+ p = new AndTypePattern(tp,p);
+ } else {
+ p = setAnnotationPatternForTypePattern(p,ap,parameterAnnotationsPossible);
+ }
eat(")");
boolean isVarArgs = maybeEat("...");
if (isVarArgs) p.setIsVarArgs(isVarArgs);
int startPos = tokenSource.peek().getStart();
TypePattern p = parseSingleTypePattern(insideTypeParameters);
int endPos = tokenSource.peek(-1).getEnd();
- p = setAnnotationPatternForTypePattern(p,ap);
+ p = setAnnotationPatternForTypePattern(p,ap,false);
p.setLocation(sourceContext, startPos, endPos);
return p;
}
- private TypePattern setAnnotationPatternForTypePattern(TypePattern t, AnnotationTypePattern ap) {
+
+ private TypePattern setAnnotationPatternForTypePattern(TypePattern t, AnnotationTypePattern ap,boolean parameterAnnotationsPattern) {
TypePattern ret = t;
+ if (parameterAnnotationsPattern) ap.setForParameterAnnotationMatch();
if (ap != AnnotationTypePattern.ANY) {
if (t == TypePattern.ANY) {
ret = new WildTypePattern(new NamePattern[] {NamePattern.ANY},false,0,false,null);
return ret;
}
+ // PVAL cope with annotation values at other places in this code
public AnnotationTypePattern maybeParseSingleAnnotationPattern() {
AnnotationTypePattern ret = null;
+ Map values = null;
// LALR(2) - fix by making "!@" a single token
int startIndex = tokenSource.getIndex();
if (maybeEat("!")) {
return ret;
} else {
TypePattern p = parseSingleTypePattern();
- ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p));
+ if (maybeEatAdjacent("(")) {
+ values = parseAnnotationValues();
+ eat(")");
+ ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p,values));
+ } else {
+ ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p));
+ }
return ret;
}
} else {
return ret;
} else {
TypePattern p = parseSingleTypePattern();
- ret = new WildAnnotationTypePattern(p);
+ if (maybeEatAdjacent("(")) {
+ values = parseAnnotationValues();
+ eat(")");
+ ret = new WildAnnotationTypePattern(p,values);
+ } else {
+ ret = new WildAnnotationTypePattern(p);
+ }
return ret;
}
} else {
}
}
+ // Parse annotation values. In an expression in @A(a=b,c=d) this method will be
+ // parsing the a=b,c=d.)
+ public Map/*String,String*/ parseAnnotationValues() {
+ Map values = new HashMap();
+ boolean seenDefaultValue = false;
+ do {
+ String possibleKeyString = parseAnnotationNameValuePattern();
+ if (possibleKeyString==null) {
+ throw new ParserException("expecting simple literal ",tokenSource.peek(-1));
+ }
+ // did they specify just a single entry 'v' or a keyvalue pair 'k=v'
+ if (maybeEat("=")) {
+ // it was a key!
+ String valueString = parseAnnotationNameValuePattern();
+ if (valueString==null) {
+ throw new ParserException("expecting simple literal ",tokenSource.peek(-1));
+ }
+ values.put(possibleKeyString,valueString);
+ } else {
+ if (seenDefaultValue) {
+ throw new ParserException("cannot specify two default values",tokenSource.peek(-1));
+ }
+ seenDefaultValue = true;
+ values.put("value",possibleKeyString);
+ }
+ } while (maybeEat(",")); // keep going whilst there are ','
+ return values;
+ }
+
public TypePattern parseSingleTypePattern() {
return parseSingleTypePattern(false);
}
TypePattern[] additionalInterfaceBounds = new TypePattern[0];
TypePattern lowerBound = null;
if (maybeEatIdentifier("extends")) {
- upperBound = parseTypePattern(false);
+ upperBound = parseTypePattern(false,false);
additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds();
}
if (maybeEatIdentifier("super")) {
- lowerBound = parseTypePattern(false);
+ lowerBound = parseTypePattern(false,false);
}
int endPos = tokenSource.peek(-1).getEnd();
return new WildTypePattern(names,false,0,endPos,false,null,upperBound,additionalInterfaceBounds,lowerBound);
annotationName.append(parseIdentifier());
}
UnresolvedType type = UnresolvedType.forName(annotationName.toString());
- p = new ExactAnnotationTypePattern(type);
+ p = new ExactAnnotationTypePattern(type,null);
return p;
}
return names;
}
+ // supported form 'a.b.c.d' or just 'a'
+ public String parseAnnotationNameValuePattern() {
+ StringBuffer buf = new StringBuffer();
+ IToken tok;
+ int startPos = tokenSource.peek().getStart();
+ boolean dotOK = false;
+ int depth = 0;
+ while (true) {
+ tok = tokenSource.peek();
+ // keep going until we hit ')' or '=' or ','
+ if (tok.getString()==")" && depth==0) break;
+ if (tok.getString()=="=" && depth==0) break;
+ if (tok.getString()=="," && depth==0) break;
+
+ // keep track of nested brackets
+ if (tok.getString()=="(") depth++;
+ if (tok.getString()==")") depth--;
+ if (tok.getString()=="{") depth++;
+ if (tok.getString()=="}") depth--;
+
+ if (tok.getString()=="." && !dotOK) {
+ throw new ParserException("dot not expected",tok);
+ }
+ buf.append(tok.getString());
+ tokenSource.next();
+ dotOK=true;
+ }
+ if (buf.length()==0) return null;
+ else return buf.toString();
+ }
public NamePattern parseNamePattern() {
}
}
- public TypePatternList parseArgumentsPattern() {
+ public TypePatternList parseArgumentsPattern(boolean parameterAnnotationsPossible) {
List patterns = new ArrayList();
eat("(");
+
+ // ()
if (maybeEat(")")) {
return new TypePatternList();
}
do {
- if (maybeEat(".")) {
+ if (maybeEat(".")) { // ..
eat(".");
patterns.add(TypePattern.ELLIPSIS);
- } else {
- patterns.add(parseTypePattern());
+ } else {
+ patterns.add(parseTypePattern(false,parameterAnnotationsPossible));
}
} while (maybeEat(","));
eat(")");
int startPos = tokenSource.peek().getStart();
AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern();
ModifiersPattern modifiers = parseModifiersPattern();
- TypePattern returnType = parseTypePattern(false);
+ TypePattern returnType = parseTypePattern(false,false);
TypePattern declaringType;
NamePattern name = null;
- Member.Kind kind;
+ MemberKind kind;
// here we can check for 'new'
if (maybeEatNew(returnType)) {
kind = Member.CONSTRUCTOR;
} else {
kind = Member.METHOD;
IToken nameToken = tokenSource.peek();
- declaringType = parseTypePattern(false);
+ declaringType = parseTypePattern(false,false);
if (maybeEat(".")) {
nameToken = tokenSource.peek();
name = parseNamePattern();
}
}
- TypePatternList parameterTypes = parseArgumentsPattern();
-
+ TypePatternList parameterTypes = parseArgumentsPattern(true);
+
ThrowsPattern throwsPattern = parseOptionalThrowsPattern();
SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType, name, parameterTypes, throwsPattern, annotationPattern);
int endPos = tokenSource.peek(-1).getEnd();
if (!maybeEat("<")) return null;
List typePats = new ArrayList();
do {
- TypePattern tp = parseTypePattern(true);
+ TypePattern tp = parseTypePattern(true,false);
typePats.add(tp);
} while(maybeEat(","));
eat(">");
}
}
+ public boolean maybeEatAdjacent(String token) {
+ IToken next = tokenSource.peek();
+ if (next.getString() == token) {
+ if (isAdjacent(tokenSource.peek(-1),next)) {
+ tokenSource.next();
+ return true;
+ }
+ }
+ return false;
+ }
+
public boolean maybeEat(String token) {
IToken next = tokenSource.peek();
if (next.getString() == token) {
// A && (B || C) => (A && B) || (A && C)
// (A || B) && C => (A && C) || (B && C)
- // is this next one optimal??
- // (A || B) && (C || D) => (¬A && B && ¬C && D) || (B && C) || (A && ¬C && D) || (A && ¬B && C)
private Pointcut pullUpDisjunctions(Pointcut pc) {
if (isNot(pc)) {
NotPointcut npc = (NotPointcut)pc;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.AnnotationTargetKind;
+import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.Constants;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.JoinPointSignature;
+import org.aspectj.weaver.MemberKind;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.NameMangler;
import org.aspectj.weaver.NewFieldTypeMunger;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.World;
-import org.aspectj.weaver.bcel.BcelTypeMunger;
public class SignaturePattern extends PatternNode {
- private Member.Kind kind;
+ private MemberKind kind;
private ModifiersPattern modifiers;
private TypePattern returnType;
private TypePattern declaringType;
private AnnotationTypePattern annotationPattern;
private transient int hashcode = -1;
- public SignaturePattern(Member.Kind kind, ModifiersPattern modifiers,
+ public SignaturePattern(MemberKind kind, ModifiersPattern modifiers,
TypePattern returnType, TypePattern declaringType,
NamePattern name, TypePatternList parameterTypes,
ThrowsPattern throwsPattern,
}
if (parameterTypes != null) {
parameterTypes = parameterTypes.resolveBindings(scope, bindings, false, false);
- checkForIncorrectTargetKind(parameterTypes,scope,false);
+ checkForIncorrectTargetKind(parameterTypes,scope,false,true);
}
if (throwsPattern != null) {
throwsPattern = throwsPattern.resolveBindings(scope, bindings);
hashcode =-1;
return this;
}
+ private void checkForIncorrectTargetKind(PatternNode patternNode, IScope scope, boolean targetsOtherThanTypeAllowed) {
+ checkForIncorrectTargetKind(patternNode, scope, targetsOtherThanTypeAllowed, false);
+
+ }
// bug 115252 - adding an xlint warning if the annnotation target type is
// wrong. This logic, or similar, may have to be applied elsewhere in the case
// of pointcuts which don't go through SignaturePattern.resolveBindings(..)
- private void checkForIncorrectTargetKind(PatternNode patternNode, IScope scope, boolean targetsOtherThanTypeAllowed) {
+ private void checkForIncorrectTargetKind(PatternNode patternNode, IScope scope, boolean targetsOtherThanTypeAllowed, boolean parameterTargettingAnnotationsAllowed) {
// return if we're not in java5 mode, if the unmatchedTargetKind Xlint
// warning has been turned off, or if the patternNode is *
if (!scope.getWorld().isInJava5Mode()
reportUnmatchedTargetKindMessage(targetKinds,patternNode,scope,false);
}
} else {
- TypePatternVisitor visitor = new TypePatternVisitor(scope,targetsOtherThanTypeAllowed);
+ TypePatternVisitor visitor = new TypePatternVisitor(scope,targetsOtherThanTypeAllowed,parameterTargettingAnnotationsAllowed);
patternNode.traverse(visitor,null);
if (visitor.containedIncorrectTargetKind()) {
Set keys = visitor.getIncorrectTargetKinds().keySet();
private IScope scope;
private Map incorrectTargetKinds /* PatternNode -> AnnotationTargetKind[] */ = new HashMap();
private boolean targetsOtherThanTypeAllowed;
+ private boolean parameterTargettingAnnotationsAllowed;
/**
* @param requiredTarget - the signature pattern Kind
* @param scope
+ * @param parameterTargettingAnnotationsAllowed
*/
- public TypePatternVisitor(IScope scope, boolean targetsOtherThanTypeAllowed) {
+ public TypePatternVisitor(IScope scope, boolean targetsOtherThanTypeAllowed, boolean parameterTargettingAnnotationsAllowed) {
this.scope = scope;
this.targetsOtherThanTypeAllowed = targetsOtherThanTypeAllowed;
+ this.parameterTargettingAnnotationsAllowed = parameterTargettingAnnotationsAllowed;
}
public Object visit(WildAnnotationTypePattern node, Object data) {
if (targetKinds == null) return data;
List incorrectTargets = new ArrayList();
for (int i = 0; i < targetKinds.length; i++) {
- if (targetKinds[i].getName().equals(kind.getName())) {
+ if (targetKinds[i].getName().equals(kind.getName()) ||
+ (targetKinds[i].getName().equals("PARAMETER") && node.isForParameterAnnotationMatch())
+ ) {
return data;
}
incorrectTargets.add(targetKinds[i]);
} else if (!targetsOtherThanTypeAllowed && !resolvedType.canAnnotationTargetType()) {
AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds();
if (targetKinds == null) return data;
+ // exception here is if parameter annotations are allowed
+ if (parameterTargettingAnnotationsAllowed) {
+ for (int i = 0; i < targetKinds.length; i++) {
+ AnnotationTargetKind annotationTargetKind = targetKinds[i];
+ if (annotationTargetKind.getName().equals("PARAMETER") && node.isForParameterAnnotationMatch()) return data;
+ }
+ }
incorrectTargetKinds.put(node,targetKinds);
}
return data;
}
public Object visit(ExactTypePattern node, Object data) {
- ExactAnnotationTypePattern eatp = new ExactAnnotationTypePattern(node.getExactType().resolve(scope.getWorld()));
+ ExactAnnotationTypePattern eatp = new ExactAnnotationTypePattern(node.getExactType().resolve(scope.getWorld()),null);
eatp.accept(this,data);
return data;
}
}
if (!parameterTypes.canMatchSignatureWithNParameters(aMethod.getParameterTypes().length)) return FuzzyBoolean.NO;
ResolvedType[] resolvedParameters = world.resolve(aMethod.getParameterTypes());
- if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC).alwaysTrue()) {
+ ResolvedType[][] parameterAnnotationTypes = aMethod.getParameterAnnotationTypes();
+ if (parameterAnnotationTypes==null || parameterAnnotationTypes.length==0) parameterAnnotationTypes=null;
+ if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC,parameterAnnotationTypes).alwaysTrue()) {
// It could still be a match based on the generic sig parameter types of a parameterized type
- if (!parameterTypes.matches(world.resolve(aMethod.getGenericParameterTypes()),TypePattern.STATIC).alwaysTrue()) {
+ if (!parameterTypes.matches(world.resolve(aMethod.getGenericParameterTypes()),TypePattern.STATIC,parameterAnnotationTypes).alwaysTrue()) {
return FuzzyBoolean.MAYBE;
// It could STILL be a match based on the erasure of the parameter types??
// to be determined via test cases...
return FuzzyBoolean.YES;
}
+
+
/**
* match on declaring type, parameter types, throws types
*/
if (!parameterTypes.canMatchSignatureWithNParameters(aConstructor.getParameterTypes().length)) return FuzzyBoolean.NO;
ResolvedType[] resolvedParameters = world.resolve(aConstructor.getParameterTypes());
- if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC).alwaysTrue()) {
+
+ ResolvedType[][] parameterAnnotationTypes = aConstructor.getParameterAnnotationTypes();
+
+ if (parameterAnnotationTypes==null || parameterAnnotationTypes.length==0) parameterAnnotationTypes=null;
+
+ if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC,parameterAnnotationTypes).alwaysTrue()) {
// It could still be a match based on the generic sig parameter types of a parameterized type
if (!parameterTypes.matches(world.resolve(aConstructor.getGenericParameterTypes()),TypePattern.STATIC).alwaysTrue()) {
return FuzzyBoolean.MAYBE;
ResolvedMember [] mems = member.getDeclaringType().resolve(world).getDeclaredFields(); // FIXME asc should include supers with getInterTypeMungersIncludingSupers?
List mungers = member.getDeclaringType().resolve(world).getInterTypeMungers();
for (Iterator iter = mungers.iterator(); iter.hasNext();) {
- BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next();
+ ConcreteTypeMunger typeMunger = (ConcreteTypeMunger) iter.next();
if (typeMunger.getMunger() instanceof NewFieldTypeMunger) {
ResolvedMember fakerm = typeMunger.getSignature();
ResolvedMember ajcMethod = AjcMemberMaker.interFieldInitializer(fakerm,typeMunger.getAspectType());
public NamePattern getName() { return name; }
public TypePattern getDeclaringType() { return declaringType; }
- public Member.Kind getKind() {
+ public MemberKind getKind() {
return kind;
}
}
public static SignaturePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
- Member.Kind kind = Member.Kind.read(s);
+ MemberKind kind = MemberKind.read(s);
ModifiersPattern modifiers = ModifiersPattern.read(s);
TypePattern returnType = TypePattern.read(s, context);
TypePattern declaringType = TypePattern.read(s, context);
if (type.isTypeVariableReference()) {
typesIterator = ((TypeVariableReference)type).getTypeVariable().getFirstBound().resolve(type.getWorld()).getDirectSupertypes();
} else {
- typesIterator = type.getDirectSupertypes();
+ // pr223605
+ if (type.isRawType()) {
+ type = type.getGenericType();
+ }
+ typesIterator = type.getDirectSupertypes();
}
// FuzzyBoolean ret = FuzzyBoolean.NO; // ??? -eh
protected boolean matchesExactly(ResolvedType type) {
annotationPattern.resolve(type.getWorld());
- return annotationPattern.matches(type).alwaysTrue();
+ boolean b = false;
+ if (type.temporaryAnnotationTypes!=null) {
+ b = annotationPattern.matches(type,type.temporaryAnnotationTypes).alwaysTrue();
+ } else {
+ b = annotationPattern.matches(type).alwaysTrue();
+ }
+ return b;
}
+
protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
annotationPattern.resolve(type.getWorld());
return annotationPattern.matches(annotatedType).alwaysTrue();
return (size() -ellipsisCount) <= numParams;
}
}
+ public FuzzyBoolean matches(ResolvedType[] types, TypePattern.MatchKind kind) {
+ return matches(types,kind,null);
+ }
//XXX shares much code with WildTypePattern and with NamePattern
/**
*
* This method will never return FuzzyBoolean.NEVER
*/
- public FuzzyBoolean matches(ResolvedType[] types, TypePattern.MatchKind kind) {
+ public FuzzyBoolean matches(ResolvedType[] types, TypePattern.MatchKind kind, ResolvedType[][] parameterAnnotations) {
int nameLength = types.length;
int patternLength = typePatterns.length;
if (nameLength != patternLength) return FuzzyBoolean.NO;
FuzzyBoolean finalReturn = FuzzyBoolean.YES;
while (patternIndex < patternLength) {
- FuzzyBoolean ret = typePatterns[patternIndex++].matches(types[nameIndex++], kind);
+ ResolvedType t = types[nameIndex];
+ FuzzyBoolean ret = null;
+ try {
+ if (parameterAnnotations!=null) t.temporaryAnnotationTypes = parameterAnnotations[nameIndex];
+ ret = typePatterns[patternIndex].matches(t,kind);
+ } finally {
+ t.temporaryAnnotationTypes=null;
+ }
+ patternIndex++;
+ nameIndex++;
if (ret == FuzzyBoolean.NO) return ret;
if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
}
if (p == TypePattern.ELLIPSIS) {
nameIndex = nameLength - (patternLength-patternIndex);
} else {
- FuzzyBoolean ret = p.matches(types[nameIndex++], kind);
+ ResolvedType t = types[nameIndex];
+ FuzzyBoolean ret = null;
+ try {
+ if (parameterAnnotations!=null) t.temporaryAnnotationTypes = parameterAnnotations[nameIndex];
+ ret = p.matches(t, kind);
+ } finally {
+ t.temporaryAnnotationTypes=null;
+ }
+ nameIndex++;
if (ret == FuzzyBoolean.NO) return ret;
if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
}
import java.io.DataOutputStream;
import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.weaver.AnnotatedElement;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.WeaverMessages;
import org.aspectj.weaver.World;
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
/**
* @author colyer
private TypePattern typePattern;
private boolean resolved = false;
+ Map annotationValues;
/**
*
this.typePattern = typePattern;
this.setLocation(typePattern.getSourceContext(), typePattern.start, typePattern.end);
}
+
+ public WildAnnotationTypePattern(TypePattern typePattern, Map annotationValues) {
+ super();
+ this.typePattern = typePattern;
+ this.annotationValues = annotationValues;
+ // PVAL make the location be from start of type pattern to end of values
+ this.setLocation(typePattern.getSourceContext(), typePattern.start, typePattern.end);
+ }
public TypePattern getTypePattern() {
return typePattern;
}
-
+
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.AnnotationTypePattern#matches(org.aspectj.weaver.AnnotatedElement)
*/
public FuzzyBoolean matches(AnnotatedElement annotated) {
+ return matches(annotated,null);
+ }
+
+ /**
+ * Resolve any annotation values specified, checking they are all well formed (valid names, valid values)
+ * @param annotationType the annotation type for which the values have been specified
+ * @param scope the scope within which to resolve type references (eg. Color.GREEN)
+ */
+ protected void resolveAnnotationValues(ResolvedType annotationType, IScope scope) {
+ if (annotationValues == null) return;
+ // Check any values specified are OK:
+ // - the value names are for valid annotation fields
+ // - the specified values are of the correct type
+ // - for enums, check the specified values can be resolved in the specified scope
+ Set keys = annotationValues.keySet();
+ ResolvedMember[] ms = annotationType.getDeclaredMethods();
+ for (Iterator kIter = keys.iterator(); kIter.hasNext();) {
+ String k = (String) kIter.next();
+ String v = (String) annotationValues.get(k);
+ boolean validKey = false;
+ for (int i = 0; i < ms.length; i++) {
+ ResolvedMember resolvedMember = ms[i];
+ if (resolvedMember.getName().equals(k) && resolvedMember.isAbstract()) {
+ validKey = true;
+ ResolvedType t = resolvedMember.getReturnType().resolve(scope.getWorld());
+ if (t.isEnum()) {
+ // value must be an enum reference X.Y
+ int pos = v.lastIndexOf(".");
+ if (pos == -1) {
+ IMessage m = MessageUtil.error(
+ WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"enum"),
+ getSourceLocation());
+ scope.getWorld().getMessageHandler().handleMessage(m);
+ } else {
+ String typename = v.substring(0,pos);
+ ResolvedType rt = scope.lookupType(typename, this).resolve(scope.getWorld());
+ v = rt.getSignature()+v.substring(pos+1); // from 'Color.RED' to 'Lp/Color;RED'
+ annotationValues.put(k,v);
+ }
+ } else if (t.isPrimitiveType()) {
+ if (t.getSignature()=="I") {
+ try {
+ int value = Integer.parseInt(v);
+ annotationValues.put(k,Integer.toString(value));
+ } catch (NumberFormatException nfe) {
+ IMessage m = MessageUtil.error(
+ WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"int"),
+ getSourceLocation());
+ scope.getWorld().getMessageHandler().handleMessage(m);
+ }
+ } else if (t.getSignature()=="F") {
+ try {
+ float value = Float.parseFloat(v);
+ annotationValues.put(k,Float.toString(value));
+ } catch (NumberFormatException nfe) {
+ IMessage m = MessageUtil.error(
+ WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"float"),
+ getSourceLocation());
+ scope.getWorld().getMessageHandler().handleMessage(m);
+ }
+
+ } else if (t.getSignature()=="Z") {
+ if (v.equalsIgnoreCase("true") || v.equalsIgnoreCase("false")) {
+ // is it ok !
+ } else {
+ IMessage m = MessageUtil.error(
+ WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"boolean"),
+ getSourceLocation());
+ scope.getWorld().getMessageHandler().handleMessage(m);
+ }
+ } else if (t.getSignature()=="S") {
+ try {
+ short value = Short.parseShort(v);
+ annotationValues.put(k,Short.toString(value));
+ } catch (NumberFormatException nfe) {
+ IMessage m = MessageUtil.error(
+ WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"short"),
+ getSourceLocation());
+ scope.getWorld().getMessageHandler().handleMessage(m);
+ }
+ } else if (t.getSignature()=="J") {
+ try {
+ long value = Long.parseLong(v);
+ annotationValues.put(k,Long.toString(value));
+ } catch (NumberFormatException nfe) {
+ IMessage m = MessageUtil.error(
+ WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"long"),
+ getSourceLocation());
+ scope.getWorld().getMessageHandler().handleMessage(m);
+ }
+ } else if (t.getSignature()=="D") {
+ try {
+ double value = Double.parseDouble(v);
+ annotationValues.put(k,Double.toString(value));
+ } catch (NumberFormatException nfe) {
+ IMessage m = MessageUtil.error(
+ WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"double"),
+ getSourceLocation());
+ scope.getWorld().getMessageHandler().handleMessage(m);
+ }
+ } else if (t.getSignature()=="B") {
+ try {
+ byte value = Byte.parseByte(v);
+ annotationValues.put(k,Byte.toString(value));
+ } catch (NumberFormatException nfe) {
+ IMessage m = MessageUtil.error(
+ WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"byte"),
+ getSourceLocation());
+ scope.getWorld().getMessageHandler().handleMessage(m);
+ }
+ } else if (t.getSignature()=="C") {
+ if (v.length()!=3) { // '?'
+ IMessage m = MessageUtil.error(
+ WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"char"),
+ getSourceLocation());
+ scope.getWorld().getMessageHandler().handleMessage(m);
+ } else {
+ annotationValues.put(k,v.substring(1,2));
+ }
+ } else {
+ throw new RuntimeException("Not implemented for "+t);
+ }
+ } else if (t.equals(ResolvedType.JAVA_LANG_STRING)) {
+ // nothing to do, it will be OK
+ } else {
+ throw new RuntimeException("Compiler limitation: annotation value support not implemented for type "+t);
+ }
+ }
+ }
+ if (!validKey) {
+ IMessage m = MessageUtil.error(
+ WeaverMessages.format(WeaverMessages.UNKNOWN_ANNOTATION_VALUE,annotationType,k),
+ getSourceLocation());
+ scope.getWorld().getMessageHandler().handleMessage(m);
+ }
+ }
+ }
+
+
+
+
+ public FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations) {
if (!resolved) {
throw new IllegalStateException("Can't match on an unresolved annotation type pattern");
}
- // matches if the type of any of the annotations on the AnnotatedElement is
- // matched by the typePattern.
- ResolvedType[] annTypes = annotated.getAnnotationTypes();
-
- if (annTypes!=null && annTypes.length!=0) {
- for (int i = 0; i < annTypes.length; i++) {
- if (typePattern.matches(annTypes[i],TypePattern.STATIC).alwaysTrue()) {
- return FuzzyBoolean.YES;
+ if (annotationValues!=null) {
+ // PVAL improve this restriction, would allow '*(value=Color.RED)'
+ throw new IllegalStateException("Cannot use annotationvalues with a wild annotation pattern");
+ }
+ if (isForParameterAnnotationMatch()) {
+ if (parameterAnnotations!=null && parameterAnnotations.length!=0) {
+ for (int i = 0; i < parameterAnnotations.length; i++) {
+ if (typePattern.matches(parameterAnnotations[i],TypePattern.STATIC).alwaysTrue()) {
+ return FuzzyBoolean.YES;
+ }
+ }
+ }
+ } else {
+ // matches if the type of any of the annotations on the AnnotatedElement is
+ // matched by the typePattern.
+ ResolvedType[] annTypes = annotated.getAnnotationTypes();
+ if (annTypes!=null && annTypes.length!=0) {
+ for (int i = 0; i < annTypes.length; i++) {
+ if (typePattern.matches(annTypes[i],TypePattern.STATIC).alwaysTrue()) {
+ return FuzzyBoolean.YES;
+ }
}
}
}
scope.getWorld().getMessageHandler().handleMessage(m);
resolved = false;
}
- ExactAnnotationTypePattern eatp = new ExactAnnotationTypePattern(et.getExactType().resolve(scope.getWorld()));
+ ResolvedType annotationType = et.getExactType().resolve(scope.getWorld());
+ resolveAnnotationValues(annotationType,scope);
+ ExactAnnotationTypePattern eatp = new ExactAnnotationTypePattern(annotationType,annotationValues);
eatp.copyLocationFrom(this);
+ if (isForParameterAnnotationMatch()) eatp.setForParameterAnnotationMatch();
return eatp;
} else {
return this;
s.writeByte(VERSION);
typePattern.write(s);
writeLocation(s);
+ s.writeBoolean(isForParameterAnnotationMatch());
+ // PVAL
+ if (annotationValues==null) {
+ s.writeInt(0);
+ } else {
+ s.writeInt(annotationValues.size());
+ Set key = annotationValues.keySet();
+ for (Iterator keys = key.iterator(); keys.hasNext();) {
+ String k = (String) keys.next();
+ s.writeUTF(k);
+ s.writeUTF((String)annotationValues.get(k));
+ }
+ }
}
public static AnnotationTypePattern read(VersionedDataInputStream s,ISourceContext context) throws IOException {
- AnnotationTypePattern ret;
+ WildAnnotationTypePattern ret;
byte version = s.readByte();
if (version > VERSION) {
throw new BCException("ExactAnnotationTypePattern was written by a newer version of AspectJ");
TypePattern t = TypePattern.read(s,context);
ret = new WildAnnotationTypePattern(t);
ret.readLocation(context,s);
+ if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MINOR_AJ160) {
+ if (s.readBoolean()) ret.setForParameterAnnotationMatch();
+ }
+ if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160M2) {
+ int annotationValueCount = s.readInt();
+ if (annotationValueCount>0) {
+ Map aValues = new HashMap();
+ for (int i=0;i<annotationValueCount;i++) {
+ String key = s.readUTF();
+ String val = s.readUTF();
+ aValues.put(key,val);
+ }
+ ret.annotationValues = aValues;
+ }
+ }
return ret;
}
public boolean equals(Object obj) {
if (!(obj instanceof WildAnnotationTypePattern)) return false;
WildAnnotationTypePattern other = (WildAnnotationTypePattern) obj;
- return other.typePattern.equals(typePattern);
+ return other.typePattern.equals(typePattern) && this.isForParameterAnnotationMatch()==other.isForParameterAnnotationMatch();
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
- return 17 + 37*typePattern.hashCode();
+ return (17 + 37*typePattern.hashCode())*37+(isForParameterAnnotationMatch()?0:1);
}
/* (non-Javadoc)
return matchesExactlyByName(targetTypeName,type.isAnonymous(),type.isNested()) &&
matchesParameters(type,STATIC) &&
- matchesBounds(type,STATIC) &&
- annotationPattern.matches(annotatedType).alwaysTrue();
+ matchesBounds(type,STATIC) &&
+ annotationPattern.matches(annotatedType,type.temporaryAnnotationTypes).alwaysTrue();
}
if (dim == 0 && !isVarArgs && upperBound == null && lowerBound == null && (additionalInterfaceBounds == null || additionalInterfaceBounds.length==0)) { // pr72531
return TypePattern.ANY; //??? loses source location
}
- } else {
+ } else if (!isVarArgs){
annotationPattern = annotationPattern.resolveBindings(scope,bindings,allowBinding);
AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(annotationPattern);
ret.setLocation(sourceContext,start,end);
+++ /dev/null
-
-Current situation with respect to raw types...
-
-* We can create an unresolved type (typeKind = SIMPLE) by
- UnresolvedType.forSignature or forName
-
-* We can create an unresolved type (typeKind = RAW) by calling
- UnresolvedType.forRawTypeName
-
- This method is called by...
-
- BcelWorld.addSourceObjectType when types in jar files or on the classpath are added to
- the weaver for processing. If the JavaClass is determined to be generic then a raw
- UnresolvedType is built and a ReferenceType constructed from that. A BcelObjectType is
- built using the Resolved raw type (and when it's generic signature is unpacked later that will
- be swapped out for the generic type). Then a generic type is created, the delegates of
- the generic and raw types are set to point to the BcelObjectType, and the generic type
- of the raw type is set to point to the generic type. The raw type is explicitly added into
- the typeMap.
-
- EclipseFactory.addSourceTypeBinding when adding a binding for a generic type during
- completeTypeBindings. This is put into the world by calling world.lookupOrCreateName.
- Then a generic type is created and the raw type's generic type is set to refer to it.
-
- EclipseFactory.fromBinding when processing a RawTypeBinding. A later call to resolve
- is responsible for adding this to the type map.
-
-* World.resolve processing works as follows:
-
- in resolveObjectType, if the typeKind of the UnresolvedType is neither parameterized
- nor generic, then a new ReferenceType is created using the rawTypeSignature of the
- unresolved type. Then the delegate is created, and if this turns out to be generic then a
- generic type is also built and set as the generic type of the reference type (but nothing
- sets the type of the reference type to raw???).
-
- in resolveTheGenericType the rawTypeSignature is looked up in the typeMap. If it
- is not found, then a new UnresolvedType is created forSignature, resolved (see above),
- and put in the type map. The generic type is then created and set as the generic type
- of the raw type.
-
import java.lang.reflect.Member;
import java.util.Set;
+import org.aspectj.weaver.AnnotationX;
import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.World;
/**
Object getAnnotation(ResolvedType annotationType, Object onObject);
Object getAnnotationFromMember(ResolvedType annotationType, Member aMember);
+ public AnnotationX getAnnotationOfType(UnresolvedType ofType,Member onMember);
+ public String getAnnotationDefaultValue(Member onMember);
+
Object getAnnotationFromClass(ResolvedType annotationType, Class aClass);
Set/*ResolvedType*/ getAnnotations(Member onMember);
+
+ ResolvedType[][] getParameterAnnotationTypes(Member onMember);
}
public ResolvedMember[] getDeclaredFields() {
if (fields == null) {
Field[] reflectFields = this.myClass.getDeclaredFields();
- this.fields = new ResolvedMember[reflectFields.length];
+ ResolvedMember[] rFields = new ResolvedMember[reflectFields.length];
for (int i = 0; i < reflectFields.length; i++) {
- this.fields[i] =
+ rFields[i] =
ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(reflectFields[i], world);
}
+ this.fields = rFields;
}
return fields;
}
public ResolvedType[] getDeclaredInterfaces() {
if (interfaces == null) {
Class[] reflectInterfaces = this.myClass.getInterfaces();
- this.interfaces = new ResolvedType[reflectInterfaces.length];
+ ResolvedType[] rInterfaces = new ResolvedType[reflectInterfaces.length];
for (int i = 0; i < reflectInterfaces.length; i++) {
- this.interfaces[i] = ReflectionBasedReferenceTypeDelegateFactory
+ rInterfaces[i] = ReflectionBasedReferenceTypeDelegateFactory
.resolveTypeInWorld(reflectInterfaces[i],world);
}
+ this.interfaces = rInterfaces;
}
return interfaces;
}
if (methods == null) {
Method[] reflectMethods = this.myClass.getDeclaredMethods();
Constructor[] reflectCons = this.myClass.getDeclaredConstructors();
- this.methods = new ResolvedMember[reflectMethods.length + reflectCons.length];
+ ResolvedMember[] rMethods = new ResolvedMember[reflectMethods.length + reflectCons.length];
for (int i = 0; i < reflectMethods.length; i++) {
- this.methods[i] =
+ rMethods[i] =
ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(reflectMethods[i], world);
}
for (int i = 0; i < reflectCons.length; i++) {
- this.methods[i + reflectMethods.length] =
+ rMethods[i + reflectMethods.length] =
ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(reflectCons[i], world);
}
+ this.methods = rMethods;
}
return methods;
}
package org.aspectj.weaver.reflect;
import java.lang.reflect.Member;
+import java.util.Iterator;
+import org.aspectj.weaver.AnnotationX;
+import org.aspectj.weaver.MemberKind;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedMemberImpl;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.UnresolvedType;
+
/**
* Subtype of ResolvedMemberImpl used in reflection world.
* Knows how to get annotations from a java.lang.reflect.Member
* @param name
* @param parameterTypes
*/
- public ReflectionBasedResolvedMemberImpl(Kind kind,
+ public ReflectionBasedResolvedMemberImpl(MemberKind kind,
UnresolvedType declaringType, int modifiers,
UnresolvedType returnType, String name,
UnresolvedType[] parameterTypes,
* @param parameterTypes
* @param checkedExceptions
*/
- public ReflectionBasedResolvedMemberImpl(Kind kind,
+ public ReflectionBasedResolvedMemberImpl(MemberKind kind,
UnresolvedType declaringType, int modifiers,
UnresolvedType returnType, String name,
UnresolvedType[] parameterTypes, UnresolvedType[] checkedExceptions,
* @param checkedExceptions
* @param backingGenericMember
*/
- public ReflectionBasedResolvedMemberImpl(Kind kind,
+ public ReflectionBasedResolvedMemberImpl(MemberKind kind,
UnresolvedType declaringType, int modifiers,
UnresolvedType returnType, String name,
UnresolvedType[] parameterTypes,
* @param name
* @param signature
*/
- public ReflectionBasedResolvedMemberImpl(Kind kind,
+ public ReflectionBasedResolvedMemberImpl(MemberKind kind,
UnresolvedType declaringType, int modifiers, String name,
String signature, Member reflectMember) {
super(kind, declaringType, modifiers, name, signature);
return super.getAnnotationTypes();
}
+ public AnnotationX getAnnotationOfType(UnresolvedType ofType) {
+ unpackAnnotations();
+ if (annotationFinder==null) return null;
+ for (Iterator iterator = annotationTypes.iterator(); iterator.hasNext();) {
+ ResolvedType type = (ResolvedType) iterator.next();
+ if (type.getSignature().equals(ofType.getSignature())) {
+ return annotationFinder.getAnnotationOfType(ofType, reflectMember);
+ }
+ }
+ return null;
+ }
+
+ public String getAnnotationDefaultValue() {
+ if (annotationFinder==null) return null;
+ return annotationFinder.getAnnotationDefaultValue(reflectMember);
+ }
+
+ public ResolvedType[][] getParameterAnnotationTypes() {
+ if (parameterAnnotationTypes==null && annotationFinder!=null) {
+ parameterAnnotationTypes = annotationFinder.getParameterAnnotationTypes(reflectMember);
+ }
+ return parameterAnnotationTypes;
+ }
+
private void unpackAnnotations() {
if (annotationTypes == null && annotationFinder != null) {
annotationTypes = annotationFinder.getAnnotations(reflectMember);
package org.aspectj.weaver.tools;
import org.apache.commons.logging.LogFactory;
-
+//OPTIMIZE move out of main weaver for now?
public class CommonsTraceFactory extends TraceFactory {
private LogFactory logFactory = LogFactory.getFactory();
package org.aspectj.weaver.tools;
-/** This class implements a boolean that includes a "maybe"
+/**
+ * This class implements a boolean that includes a "maybe"
*/
public class FuzzyBoolean {
*/
public void registerPointcutDesignatorHandler(PointcutDesignatorHandler designatorHandler) {
this.pointcutDesignators.add(designatorHandler);
+ if (world != null) world.registerPointcutHandler(designatorHandler);
}
/**
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.weaver.IClassFileProvider;
import org.aspectj.weaver.IWeaveRequestor;
import org.aspectj.weaver.ResolvedType;
+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.bcel.Utility;
+// 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
protected Map generatedClasses = new HashMap(); /* String -> UnwovenClassFile */
protected BcelObjectType delegateForCurrentClass; // lazily initialized, should be used to prevent parsing bytecode multiple times
+ 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 () {
URL[] urls = ((URLClassLoader)loader).getURLs();
list.addAll(0,FileUtil.makeClasspath(urls));
}
- else {
+ else {
warn("cannot determine classpath");
}
}
private void init(List classPath, List aspectPath) {
abortOnError = true;
createMessageHandler();
-
info("using classpath: " + classPath);
info("using aspectpath: " + aspectPath);
weaver.addLibraryJarFile(libFile);
}
catch (IOException ex) {
- warn("bad library: '" + libFile + "'");
+ 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
+ * @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) throws IOException {
+ public byte[] weaveClass (String name, byte[] bytes,boolean mustWeave) throws IOException {
if (trace.isTraceEnabled()) trace.enter("weaveClass",this,new Object[] {name, bytes});
if (!enabled) {
debug("weaving '" + name + "'");
bytes = getWovenBytes(name, bytes);
} 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
debug("weaving '" + name + "'");
bytes = getAtAspectJAspectBytes(name, bytes);
}
private boolean shouldWeaveName (String name) {
+ 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;
+ }
+ }
+ }
boolean should =
- !((name.startsWith("org.aspectj.")
- || name.startsWith("java.")
- || name.startsWith("javax."))
+ !(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."));//JDK reflect
return should;
}
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)
+ if (delegateForCurrentClass==null) // OPTIMIZE better job here?
delegateForCurrentClass = ((BcelWorld)weaver.getWorld()).addSourceObjectType(Utility.makeJavaClass(name, bytes));
}
info("adding aspect library: '" + aspectLibrary + "'");
weaver.addLibraryJarFile(aspectLibrary);
} catch (IOException ex) {
- error("exception adding aspect library: '" + ex + "'");
+ error("exception adding aspect library: '" + ex + "'");
}
} else {
- error("bad aspect library: '" + aspectLibrary + "'");
+ error("bad aspect library: '" + aspectLibrary + "'");
}
}
os.close();
}
catch (IOException ex) {
- warn("unable to dump class " + name + " in directory " + dirName,ex);
+ warn("unable to dump class " + name + " in directory " + dirName,ex);
}
}
private class WeavingClassFileProvider implements IClassFileProvider {
private UnwovenClassFile unwovenClass;
- private List unwovenClasses = new ArrayList(); /* List<UnovenClassFile> */
+ private List unwovenClasses = new ArrayList(); /* List<UnwovenClassFile> */
private UnwovenClassFile wovenClass;
private boolean isApplyAtAspectJMungersOnly = false;
+++ /dev/null
-<html>
-<body>
-Provides a set of interfaces for third-parties wishing to integrate
-AspectJ weaving capabilities into their environments.
-</body>
-</html>
bindingNonRuntimeRetentionAnnotation=Annotation type {0} does not have runtime retention
noMatchBecauseSourceRetention=Failing match because annotation ''{0}'' on type ''{1}'' has SOURCE retention. Matching allowed when RetentionPolicy is CLASS or RUNTIME
+# Annotation value
+invalidAnnotationValue=Invalid annotation value ''{0}'', expected {1} value
+unknownAnnotationValue=The annotation ''{0}'' does not define a value named ''{1}''
+
# Generics
cantDecpMultipleParameterizations=Cannot declare parent {0} onto type {1} since it already has {2} in its hierarchy
noParameterizedTypePatternInHandler=a parameterized type pattern may not be used in a handler pointcut expression
}
public void testMethodConstruction() {
- Member s = MemberImpl.methodFromString("void Foo.goo(int)");
+ Member s = TestUtils.methodFromString("void Foo.goo(int)");
Member t = MemberImpl.method(UnresolvedType.forName("Foo"), 0, "goo", "(I)V");
- Member u = MemberImpl.methodFromString("void Foo1.goo(int)");
- Member v = MemberImpl.methodFromString("int Foo.goo(int)");
+ Member u = TestUtils.methodFromString("void Foo1.goo(int)");
+ Member v = TestUtils.methodFromString("int Foo.goo(int)");
TestUtil.assertCommutativeEquals(s, s, true);
TestUtil.assertCommutativeEquals(t, t, true);
TestUtil.assertCommutativeEquals(t, v, false);
TestUtil.assertCommutativeEquals(u, v, false);
- s = MemberImpl.fieldFromString("int Foo.goo");
+ s = TestUtils.fieldFromString("int Foo.goo");
t = MemberImpl.field("Foo", 0, "goo", "I");
- u = MemberImpl.fieldFromString("int Foo.goo1");
- v = MemberImpl.fieldFromString("long Foo.goo");
+ u = TestUtils.fieldFromString("int Foo.goo1");
+ v = TestUtils.fieldFromString("long Foo.goo");
TestUtil.assertCommutativeEquals(s, s, true);
TestUtil.assertCommutativeEquals(t, t, true);
public void testMethodContents() {
- Member m = MemberImpl.methodFromString("void Foo.goo(int)");
+ Member m = TestUtils.methodFromString("void Foo.goo(int)");
kindTest(m, Member.METHOD);
declaringTypeTest(m, "Foo");
nameTest(m, "goo");
isConstructorTest(m, false);
isStaticTest(m, false);
- m = MemberImpl.methodFromString("interface java.lang.Object java.util.Iterator.next()");
+ m = TestUtils.methodFromString("interface java.lang.Object java.util.Iterator.next()");
kindTest(m, Member.METHOD);
declaringTypeTest(m, "java.util.Iterator");
nameTest(m, "next");
isConstructorTest(m, false);
isStaticTest(m, false);
- m = MemberImpl.methodFromString("void Foo.<init>(int, java.lang.Object)");
+ m = TestUtils.methodFromString("void Foo.<init>(int, java.lang.Object)");
kindTest(m, Member.CONSTRUCTOR);
declaringTypeTest(m, "Foo");
nameTest(m, "<init>");
isConstructorTest(m, true);
isStaticTest(m, false);
- m = MemberImpl.methodFromString("private double Foo.sqrt(double)");
+ m = TestUtils.methodFromString("private double Foo.sqrt(double)");
kindTest(m, Member.METHOD);
declaringTypeTest(m, "Foo");
nameTest(m, "sqrt");
isConstructorTest(m, false);
isStaticTest(m, false);
- m = MemberImpl.methodFromString("static int java.lang.Math.max(int, int)");
+ m = TestUtils.methodFromString("static int java.lang.Math.max(int, int)");
kindTest(m, Member.METHOD);
declaringTypeTest(m, "java.lang.Math");
nameTest(m, "max");
}
public void testFieldContents() {
- Member m = MemberImpl.fieldFromString("int Foo.goo");
+ Member m = TestUtils.fieldFromString("int Foo.goo");
kindTest(m, Member.FIELD);
declaringTypeTest(m, "Foo");
nameTest(m, "goo");
isConstructorTest(m, false);
isStaticTest(m, false);
- m = MemberImpl.fieldFromString("static java.util.Iterator goo.Bar.i");
+ m = TestUtils.fieldFromString("static java.util.Iterator goo.Bar.i");
kindTest(m, Member.FIELD);
declaringTypeTest(m, "goo.Bar");
nameTest(m, "i");
private void declaringTypeTest(Member m, String declaringName) {
assertEquals(m + " declared in", UnresolvedType.forName(declaringName), m.getDeclaringType());
}
- private void kindTest(Member m, MemberImpl.Kind kind) {
+ private void kindTest(Member m, MemberKind kind) {
assertEquals(m + " kind", kind, m.getKind());
}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * 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:
+ * Andy Clement initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.aspectj.weaver.bcel.BcelAdvice;
+import org.aspectj.weaver.patterns.FormalBinding;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.patterns.SimpleScope;
+
+
+public class TestUtils {
+ private static final String[] ZERO_STRINGS = new String[0];
+
+ /**
+ * Build a member from a string representation:
+ * <blockquote><pre>
+ * static? TypeName TypeName.Id
+ * </pre></blockquote>
+ */
+ public static MemberImpl fieldFromString(String str) {
+ str = str.trim();
+ final int len = str.length();
+ int i = 0;
+ int mods = 0;
+ if (str.startsWith("static", i)) {
+ mods = Modifier.STATIC;
+ i += 6;
+ while (Character.isWhitespace(str.charAt(i))) i++;
+ }
+ int start = i;
+ while (! Character.isWhitespace(str.charAt(i))) i++;
+ UnresolvedType retTy = UnresolvedType.forName(str.substring(start, i));
+
+ start = i;
+ i = str.lastIndexOf('.');
+ UnresolvedType declaringTy = UnresolvedType.forName(str.substring(start, i).trim());
+ start = ++i;
+ String name = str.substring(start, len).trim();
+ return new MemberImpl(
+ Member.FIELD,
+ declaringTy,
+ mods,
+ retTy,
+ name,
+ UnresolvedType.NONE);
+ }
+
+ /**
+ * Build a member from a string representation:
+ * <blockquote><pre>
+ * (static|interface|private)? TypeName TypeName . Id ( TypeName , ...)
+ * </pre></blockquote>
+ */
+
+ public static Member methodFromString(String str) {
+ str = str.trim();
+ // final int len = str.length();
+ int i = 0;
+
+ int mods = 0;
+ if (str.startsWith("static", i)) {
+ mods = Modifier.STATIC;
+ i += 6;
+ } else if (str.startsWith("interface", i)) {
+ mods = Modifier.INTERFACE;
+ i += 9;
+ } else if (str.startsWith("private", i)) {
+ mods = Modifier.PRIVATE;
+ i += 7;
+ }
+ while (Character.isWhitespace(str.charAt(i))) i++;
+
+ int start = i;
+ while (! Character.isWhitespace(str.charAt(i))) i++;
+ UnresolvedType returnTy = UnresolvedType.forName(str.substring(start, i));
+
+ start = i;
+ i = str.indexOf('(', i);
+ i = str.lastIndexOf('.', i);
+ UnresolvedType declaringTy = UnresolvedType.forName(str.substring(start, i).trim());
+
+ start = ++i;
+ i = str.indexOf('(', i);
+ String name = str.substring(start, i).trim();
+ start = ++i;
+ i = str.indexOf(')', i);
+
+ String[] paramTypeNames = parseIds(str.substring(start, i).trim());
+
+ return MemberImpl.method(declaringTy, mods, returnTy, name, UnresolvedType.forNames(paramTypeNames));
+ }
+
+ private static String[] parseIds(String str) {
+ if (str.length() == 0) return ZERO_STRINGS;
+ List l = new ArrayList();
+ int start = 0;
+ while (true) {
+ int i = str.indexOf(',', start);
+ if (i == -1) {
+ l.add(str.substring(start).trim());
+ break;
+ }
+ l.add(str.substring(start, i).trim());
+ start = i+1;
+ }
+ return (String[]) l.toArray(new String[l.size()]);
+ }
+
+ /**
+ * Moved from BcelWorld to here
+ *
+ * Parse a string into advice.
+ *
+ * <blockquote><pre>
+ * Kind ( Id , ... ) : Pointcut -> MethodSignature
+ * </pre></blockquote>
+ */
+ public static Advice shadowMunger(World w,String str, int extraFlag) {
+ str = str.trim();
+ int start = 0;
+ int i = str.indexOf('(');
+ AdviceKind kind =
+ AdviceKind.stringToKind(str.substring(start, i));
+ start = ++i;
+ i = str.indexOf(')', i);
+ String[] ids = parseIds(str.substring(start, i).trim());
+ //start = ++i;
+
+
+
+ i = str.indexOf(':', i);
+ start = ++i;
+ i = str.indexOf("->", i);
+ Pointcut pointcut = Pointcut.fromString(str.substring(start, i).trim());
+ Member m = TestUtils.methodFromString(str.substring(i+2, str.length()).trim());
+
+ // now, we resolve
+ UnresolvedType[] types = m.getParameterTypes();
+ FormalBinding[] bindings = new FormalBinding[ids.length];
+ for (int j = 0, len = ids.length; j < len; j++) {
+ bindings[j] = new FormalBinding(types[j], ids[j], j, 0, 0, "fromString");
+ }
+
+ Pointcut p =
+ pointcut.resolve(new SimpleScope(w, bindings));
+
+ return new BcelAdvice(kind, p, m, extraFlag, 0, 0, null, null);
+ }
+}
}
}
+ public void testTypeFactoryForParameterizedTypes() {
+ if (LangUtil.is15VMOrGreater()) { // no funny types pre 1.5
+ UnresolvedType enumOfSimpleType =
+ TypeFactory.createTypeFromSignature("Pjava/lang/Enum<Ljava/lang/String;>;");
+ assertEquals(1, enumOfSimpleType.getTypeParameters().length);
+
+ UnresolvedType enumOfNestedType =
+ TypeFactory.createTypeFromSignature("Pjava/lang/Enum<Ljavax/jws/soap/SOAPBinding$ParameterStyle;>;");
+ assertEquals(1, enumOfNestedType.getTypeParameters().length);
+
+ // is this signature right?
+ UnresolvedType nestedTypeOfParameterized =
+ TypeFactory.createTypeFromSignature("PMyInterface<Ljava/lang/String;>$MyOtherType;");
+ assertEquals(0, nestedTypeOfParameterized.getTypeParameters().length);
+
+ // how about this one? is this valid?
+ UnresolvedType doublyNestedTypeSignatures =
+ TypeFactory.createTypeFromSignature("PMyInterface<Ljava/lang/String;Ljava/lang/String;>$MyOtherType<Ljava/lang/Object;>;");
+ assertEquals(1, doublyNestedTypeSignatures.getTypeParameters().length);
+
+ }
+ }
+
private void checkTX(UnresolvedType tx,boolean shouldBeParameterized,int numberOfTypeParameters) {
assertTrue("Expected parameterization flag to be "+shouldBeParameterized,tx.isParameterizedType()==shouldBeParameterized);
if (numberOfTypeParameters==0) {
BcelWorld world = new BcelWorld();
ShadowMunger myMunger =
- world.shadowMunger("afterThrowing(): get(* *.out) -> static void Aspect.ajc_afterThrowing_field_get(java.lang.Throwable)",
+ TestUtils.shadowMunger(world,"afterThrowing(): get(* *.out) -> static void Aspect.ajc_afterThrowing_field_get(java.lang.Throwable)",
Advice.ExtraArgument);
ShadowMunger cm = myMunger.concretize(ResolvedType.MISSING, world, null);
import org.aspectj.weaver.Advice;
import org.aspectj.weaver.AdviceKind;
import org.aspectj.weaver.MemberImpl;
+import org.aspectj.weaver.TestUtils;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.UnresolvedType;
BcelAdvice munger = new BcelAdvice(
AdviceKind.stringToKind("before"),
makePointcutAll(),
- MemberImpl.methodFromString("static void Aspect.ajc_before(org.aspectj.lang.JoinPoint$StaticPart)"),
+ TestUtils.methodFromString("static void Aspect.ajc_before(org.aspectj.lang.JoinPoint$StaticPart)"),
Advice.ThisJoinPointStaticPart, -1, -1, null, null);
weaveTest("HelloWorld", "StaticTjpBeforeHelloWorld", munger);
BcelAdvice munger = new BcelAdvice(
AdviceKind.stringToKind("before"),
makePointcutAll(),
- MemberImpl.methodFromString("static void Aspect.ajc_before(org.aspectj.lang.JoinPoint$StaticPart)"),
+ TestUtils.methodFromString("static void Aspect.ajc_before(org.aspectj.lang.JoinPoint$StaticPart)"),
Advice.ThisEnclosingJoinPointStaticPart, -1, -1, null, null);
weaveTest("HelloWorld", "StaticEnclosingTjpBeforeHelloWorld", munger);
BcelAdvice munger = new BcelAdvice(
AdviceKind.stringToKind("before"),
makePointcutAll(),
- MemberImpl.methodFromString("static void Aspect.ajc_before(org.aspectj.lang.JoinPoint)"),
+ TestUtils.methodFromString("static void Aspect.ajc_before(org.aspectj.lang.JoinPoint)"),
Advice.ThisJoinPoint, -1, -1, null, null);
weaveTest("HelloWorld", "TjpBeforeHelloWorld", munger);
BcelAdvice munger = new BcelAdvice(
AdviceKind.stringToKind("around"),
makePointcutAll(),
- MemberImpl.methodFromString("static java.lang.Object Aspect.ajc_around(org.aspectj.runtime.internal.AroundClosure, org.aspectj.lang.JoinPoint)"),
+ TestUtils.methodFromString("static java.lang.Object Aspect.ajc_around(org.aspectj.runtime.internal.AroundClosure, org.aspectj.lang.JoinPoint)"),
Advice.ThisJoinPoint | Advice.ExtraArgument, -1, -1, null, null);
weaveTest("HelloWorld", "TjpAroundHelloWorld", munger);
BcelAdvice munger1 = new BcelAdvice(
AdviceKind.stringToKind("around"),
makePointcutAll(),
- MemberImpl.methodFromString("static java.lang.Object Aspect.ajc_around(org.aspectj.runtime.internal.AroundClosure, org.aspectj.lang.JoinPoint)"),
+ TestUtils.methodFromString("static java.lang.Object Aspect.ajc_around(org.aspectj.runtime.internal.AroundClosure, org.aspectj.lang.JoinPoint)"),
Advice.ThisJoinPoint | Advice.ExtraArgument, -1, -1, null,
rtx);
BcelAdvice munger2 = new BcelAdvice(
AdviceKind.stringToKind("around"),
makePointcutAll(),
- MemberImpl.methodFromString("static java.lang.Object Aspect.ajc_around(org.aspectj.runtime.internal.AroundClosure, org.aspectj.lang.JoinPoint)"),
+ TestUtils.methodFromString("static java.lang.Object Aspect.ajc_around(org.aspectj.runtime.internal.AroundClosure, org.aspectj.lang.JoinPoint)"),
Advice.ThisJoinPoint | Advice.ExtraArgument, -1, -1, null,
rtx);
protected ShadowMunger makeConcreteAdvice(String mungerString, int extraArgFlag, PerClause perClause) {
Advice myMunger =
- world.shadowMunger(mungerString, extraArgFlag);
+ TestUtils.shadowMunger(world,mungerString, extraArgFlag);
// PerSingleton s = new PerSingleton();
// s.concretize(world.resolve("Aspect"));
ResolvedType trace = world.resolve(UnresolvedType.forName("Trace"),true);
assertTrue("Couldnt find type Trace",!trace.isMissing());
fieldsTest(trace, Member.NONE);
- /*Member constr = */MemberImpl.methodFromString("void Trace.<init>()");
+ /*Member constr = */TestUtils.methodFromString("void Trace.<init>()");
//XXX need attribute fix -
//methodsTest(trace, new Member[] { constr });
mungersTest(trace,
new ShadowMunger[] {
- world.shadowMunger("before(foo): traced(foo) -> void Trace.ajc_before_4(java.lang.Object))",
+ TestUtils.shadowMunger(world,"before(foo): traced(foo) -> void Trace.ajc_before_4(java.lang.Object))",
0),
- world.shadowMunger("afterReturning(foo): traced(foo) -> void Trace.ajc_afterreturning_3(java.lang.Object, java.lang.Object))",
+ TestUtils.shadowMunger(world,"afterReturning(foo): traced(foo) -> void Trace.ajc_afterreturning_3(java.lang.Object, java.lang.Object))",
Advice.ExtraArgument),
- world.shadowMunger("around(): execution(* doit(..)) -> java.lang.Object Trace.ajc_around_2(org.aspectj.runtime.internal.AroundClosure))",
+ TestUtils.shadowMunger(world,"around(): execution(* doit(..)) -> java.lang.Object Trace.ajc_around_2(org.aspectj.runtime.internal.AroundClosure))",
Advice.ExtraArgument),
- world.shadowMunger("around(foo): traced(foo) -> java.lang.Object Trace.ajc_around_1(java.lang.Object, org.aspectj.runtime.internal.AroundClosure))",
+ TestUtils.shadowMunger(world,"around(foo): traced(foo) -> java.lang.Object Trace.ajc_around_1(java.lang.Object, org.aspectj.runtime.internal.AroundClosure))",
Advice.ExtraArgument),
});
--- /dev/null
+/* *******************************************************************
+ * 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.bcel;
+
+import java.io.File;
+import java.io.IOException;
+
+
+//XXX delete very soon
+public class ZipFileWeaver {
+ File inFile;
+ public ZipFileWeaver(File inFile) {
+ super();
+ this.inFile = inFile;
+ }
+
+ public void weave(BcelWeaver weaver, File outFile) throws IOException {
+ int count = 0;
+ long startTime = System.currentTimeMillis();
+ weaver.addJarFile(inFile, new File("."),false);
+ weaver.weave(outFile);
+ long stopTime = System.currentTimeMillis();
+
+
+ System.out.println("handled " + count + " entries, in " +
+ (stopTime-startTime)/1000. + " seconds");
+ }
+}
import org.aspectj.bridge.AbortException;
import org.aspectj.util.LangUtil;
import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.AnnotationX;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.BcweaverTests;
import org.aspectj.weaver.UnresolvedType;
AndAnnotationTypePattern atp = (AndAnnotationTypePattern) ap;
NotAnnotationTypePattern notBoo = (NotAnnotationTypePattern) atp.getRight();
ExactAnnotationTypePattern boo = (ExactAnnotationTypePattern) notBoo.getNegatedPattern();
- WildAnnotationTypePattern fooOrGoo = (WildAnnotationTypePattern) atp.getLeft();
+ AnnotationTypePattern fooOrGoo = (AnnotationTypePattern) atp.getLeft();
assertEquals("@((Foo || Goo)) !@Boo",ap.toString());
}
// TODO Auto-generated method stub
return null;
}
+
+ public AnnotationX getAnnotationOfType(UnresolvedType ofType) {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2007-2008 Contributors
+ * 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:
+ * Alexandre Vasseur
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.Member;
+
+/**
+ * A sample toString like visitor that helps understanding the AST tree structure organization
+ *
+ * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+ */
+public class DumpPointcutVisitor implements PatternNodeVisitor {
+
+ private StringBuffer sb = new StringBuffer();
+ public String get() {
+ return sb.toString();
+ }
+
+ private void append(Object o) {
+ sb.append(o.toString());
+ }
+
+ private void append(char c) {
+ sb.append(c);
+ }
+
+ /**
+ * This method helps maintaining the API and raises warning when PatternNode subclasses do not
+ * implement the visitor pattern
+ *
+ * @param node
+ * @param data
+ * @return
+ */
+ public Object visit(PatternNode node, Object data) {
+ System.err.println("Should implement: " + node.getClass());
+ return null;
+ }
+
+ public Object visit(AnyTypePattern node, Object data) {
+ append('*');
+ return null;
+ }
+
+ public Object visit(NoTypePattern node, Object data) {
+ append(node.toString());//TODO no idea when this one is used
+ return null;
+ }
+
+ public Object visit(EllipsisTypePattern node, Object data) {
+ append(node.toString());
+ return null;
+ }
+
+ public Object visit(AnyWithAnnotationTypePattern node, Object data) {
+ node.annotationPattern.accept(this, data);
+ append(" *");
+ return null;
+ }
+
+ public Object visit(AnyAnnotationTypePattern node, Object data) {
+ //@ANY : ignore
+ append('*');
+ return null;
+ }
+
+ public Object visit(EllipsisAnnotationTypePattern node, Object data) {
+ append("..");
+ return null;
+ }
+
+ public Object visit(AndAnnotationTypePattern node, Object data) {
+ node.getLeft().accept(this, data);
+ append(' ');
+ node.getRight().accept(this, data);
+ return null;
+ }
+
+ public Object visit(AndPointcut node, Object data) {
+ append('(');
+ node.getLeft().accept(this, data);
+ append(" && ");
+ node.getRight().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(AndTypePattern node, Object data) {
+ append('(');
+ node.getLeft().accept(this, data);
+ append(" && ");
+ node.getRight().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(AnnotationPatternList node, Object data) {
+ AnnotationTypePattern[] annotations = node.getAnnotationPatterns();
+ for (int i = 0; i < annotations.length; i++) {
+ if (i>0) append(", ");//Note: list is ",", and is " " separated for annotations
+ annotations[i].accept(this, data);
+ }
+ return null;
+ }
+
+ public Object visit(AnnotationPointcut node, Object data) {
+ append("@annotation(");
+ node.getAnnotationTypePattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(ArgsAnnotationPointcut node, Object data) {
+ append("@args(");
+ node.getArguments().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(ArgsPointcut node, Object data) {
+ append("args(");
+ node.getArguments().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(BindingAnnotationTypePattern node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(BindingTypePattern node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(CflowPointcut node, Object data) {
+ append(node.isCflowBelow()?"cflowbelow(":"cflow(");
+ node.getEntry().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(ExactAnnotationTypePattern node, Object data) {
+ //append('@'); // since @annotation(@someAnno) cannot be parsed anymore
+ append(node.getAnnotationType().getName());
+ return null;
+ }
+
+ public Object visit(ExactTypePattern node, Object data) {
+ if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
+ append('(');
+ node.getAnnotationPattern().accept(this, data);
+ append(' ');
+ }
+
+ String typeString = node.getType().toString();
+ if (node.isVarArgs()) typeString = typeString.substring(0, typeString.lastIndexOf('['));//TODO AV - ugly
+ append(typeString);
+ if (node.isIncludeSubtypes()) append('+');
+ if (node.isVarArgs()) append("...");
+ if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
+ append(')');
+ }
+ return null;
+ }
+
+ public Object visit(KindedPointcut node, Object data) {
+ append(node.getKind().getSimpleName());
+ append('(');
+ node.getSignature().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(ModifiersPattern node, Object data) {
+ append(node.toString());//note: node takes care of forbidden mods
+ return null;
+ }
+
+ public Object visit(NamePattern node, Object data) {
+ append(node.toString());
+ return null;
+ }
+
+ public Object visit(NotAnnotationTypePattern node, Object data) {
+ append("!");
+ node.getNegatedPattern().accept(this, data);
+ return null;
+ }
+
+ public Object visit(NotPointcut node, Object data) {
+ append("!(");
+ node.getNegatedPointcut().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(NotTypePattern node, Object data) {
+ append("!(");
+ node.getNegatedPattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(OrAnnotationTypePattern node, Object data) {
+ append('(');
+ node.getLeft().accept(this, data);
+ append(" || ");
+ node.getRight().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(OrPointcut node, Object data) {
+ append('(');
+ node.getLeft().accept(this, data);
+ append(" || ");
+ node.getRight().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(OrTypePattern node, Object data) {
+ append('(');
+ node.getLeft().accept(this, data);
+ append(" || ");
+ node.getRight().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(ReferencePointcut node, Object data) {
+ append(node.toString());
+ return null;
+ }
+
+ public Object visit(SignaturePattern node, Object data) {
+ if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
+ node.getAnnotationPattern().accept(this, data);
+ append(' ');
+ }
+
+ if (node.getModifiers() != ModifiersPattern.ANY) {
+ node.getModifiers().accept(this, data);
+ append(' ');
+ }
+
+ if (node.getKind() == Member.STATIC_INITIALIZATION) {
+ node.getDeclaringType().accept(this, data);
+ } else if (node.getKind() == Member.HANDLER) {
+ append("handler(");
+ node.getParameterTypes().get(0).accept(this, data);//Note: we know we have 1 child
+ append(')');
+ } else {
+ if (!(node.getKind() == Member.CONSTRUCTOR)) {
+ node.getReturnType().accept(this, data);
+ append(' ');
+ }
+ if (node.getDeclaringType() != TypePattern.ANY) {
+ node.getDeclaringType().accept(this, data);
+ append('.');
+ }
+ if (node.getKind() == Member.CONSTRUCTOR) {
+ append("new");
+ } else {
+ node.getName().accept(this, data);
+ }
+ if (node.getKind() == Member.METHOD || node.getKind() == Member.CONSTRUCTOR) {
+ append('(');
+ node.getParameterTypes().accept(this, data);
+ append(')');
+ }
+ if (node.getThrowsPattern() != null) {
+ append(' ');
+ node.getThrowsPattern().accept(this, data);
+ }
+ }
+ return null;
+ }
+
+ public Object visit(ThisOrTargetAnnotationPointcut node, Object data) {
+ append(node.isThis() ? "@this(" : "@target(");
+ node.getAnnotationTypePattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(ThisOrTargetPointcut node, Object data) {
+ append(node.isThis() ? "this(" : "target(");
+ node.getType().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ // Note: a visitor instance is not thread safe so should not be shared
+ private boolean inThrowsForbidden = false;
+
+ public Object visit(ThrowsPattern node, Object data) {
+ if (node == ThrowsPattern.ANY) return null;
+
+ append("throws ");
+ node.getRequired().accept(this, data);
+ if (node.getForbidden().size() > 0) {
+ // a hack since throws !(A, B) cannot be parsed
+ try {
+ inThrowsForbidden = true;
+ node.getForbidden().accept(this, data);
+ } finally {
+ inThrowsForbidden = false;
+ }
+ }
+ return null;
+ }
+
+ public Object visit(TypePatternList node, Object data) {
+ if (node.getTypePatterns().length == 0) return null;
+
+ TypePattern[] typePatterns = node.getTypePatterns();
+ for (int i = 0; i < typePatterns.length; i++) {
+ TypePattern typePattern = typePatterns[i];
+ if (i > 0) append(", ");
+ if (inThrowsForbidden) append('!');
+ typePattern.accept(this, data);
+ }
+ return null;
+ }
+
+ public Object visit(WildAnnotationTypePattern node, Object data) {
+ append("@(");
+ node.getTypePattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(WildTypePattern node, Object data) {
+ if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
+ append('(');
+ node.getAnnotationPattern().accept(this, data);
+ append(' ');
+ }
+ NamePattern[] namePatterns = node.getNamePatterns();
+ for (int i=0; i < namePatterns.length; i++) {
+ if (namePatterns[i] == null) {
+ append('.');//FIXME mh, error prone, can't we have a nullNamePattern ?
+ } else {
+ if (i > 0) append('.');
+ namePatterns[i].accept(this, data);
+ }
+ }
+ if (node.isIncludeSubtypes()) append('+');
+ if (node.isVarArgs()) append("...");
+ if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
+ append(')');
+ }
+ return null;
+ }
+
+ public Object visit(WithinAnnotationPointcut node, Object data) {
+ append("@within(");
+ node.getAnnotationTypePattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(WithinCodeAnnotationPointcut node, Object data) {
+ append("@withincode(");
+ node.getAnnotationTypePattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(WithinPointcut node, Object data) {
+ append("within(");
+ node.getTypePattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(WithincodePointcut node, Object data) {
+ append("withincode(");
+ node.getSignature().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(Pointcut.MatchesNothingPointcut node, Object data) {
+ append("");//TODO shouldn't that be a "false" ?
+ return null;
+ }
+
+
+ //-------------- perX
+
+ public Object visit(PerCflow node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(PerFromSuper node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(PerObject node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(PerSingleton node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(PerTypeWithin node, Object data) {
+ append(node);
+ return null;
+ }
+
+ // ------------- declare X
+
+ public Object visit(DeclareAnnotation node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(DeclareErrorOrWarning node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(DeclareParents node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(DeclarePrecedence node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(DeclareSoft node, Object data) {
+ append(node);
+ return null;
+ }
+
+ // ----------- misc
+
+ public Object visit(ConcreteCflowPointcut node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(HandlerPointcut node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(IfPointcut node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(TypeVariablePattern node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(TypeVariablePatternList node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(HasMemberTypePattern node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public static void check(String s) {
+ check(Pointcut.fromString(s), false);
+ }
+
+ public static void check(PatternNode pc, boolean isTypePattern) {
+ DumpPointcutVisitor v1 = new DumpPointcutVisitor();
+ pc.accept(v1, null);
+
+ DumpPointcutVisitor v2 = new DumpPointcutVisitor();
+ final PatternNode pc2;
+ if (isTypePattern) {
+ pc2 = new PatternParser(v1.get()).parseTypePattern();
+ } else {
+ pc2 = Pointcut.fromString(v1.get());
+ }
+ pc2.accept(v2, null);
+
+ // at second parsing, the String form stay stable when parsed and parsed again
+ if (! v1.get().equals(v2.get())) {
+ throw new ParserException("Unstable back parsing for '"+pc+"', got '" + v1.get() + "' and '" + v2.get() + "'", null);
+ }
+ }
+
+ public static void main(String args[]) throws Throwable {
+ String[] s = new String[]{
+ //"@args(Foo, Goo, *, .., Moo)",
+ //"execution(* *())",
+ //"call(* *(int, Integer...))",
+ //"staticinitialization(@(Foo) @(Boo) @(Goo) Moo)",
+ "(if(true) && set(int BaseApp.i))"
+
+ };
+ for (int i = 0; i < s.length; i++) {
+ check(s[i]);
+ }
+ }
+
+}
\ No newline at end of file
package org.aspectj.weaver.patterns;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
import junit.framework.TestCase;
import org.aspectj.weaver.BcweaverTests;
public void testParseAnythingTypeVariable() {
PatternParser parser = new PatternParser("?");
- WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true);
+ WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true,false);
assertEquals("Expected type variable ?","?",tp.maybeGetSimpleName());
}
public void testParseAnythingExtendsTypeVariable() {
PatternParser parser = new PatternParser("? extends Number");
- WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true);
+ WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true,false);
assertEquals("Expected type variable ?","?",tp.maybeGetSimpleName());
assertEquals("upper Bound of Number",new PatternParser("Number").parseTypePattern(),tp.getUpperBound());
}
public void testParseAnythingSuperTypeVariable() {
PatternParser parser = new PatternParser("? super Number+");
- WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true);
+ WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true,false);
assertEquals("Expected type variable ?","?",tp.maybeGetSimpleName());
assertEquals("lower Bound of Number+",new PatternParser("Number+").parseTypePattern(),tp.getLowerBound());
}
public void testParameterizedTypePatternsAny() {
try {
PatternParser parser = new PatternParser("*<T,S extends Number>");
- WildTypePattern wtp = (WildTypePattern) parser.parseTypePattern(false);
+ WildTypePattern wtp = (WildTypePattern) parser.parseTypePattern(false,false);
// TypePatternList tvs = wtp.getTypeParameters();
// assertEquals("2 type parameters",2,tvs.getTypePatterns().length);
// assertEquals("T",new PatternParser("T").parseTypePattern(),tvs.getTypePatterns()[0]);
public void testTypeParamList() {
PatternParser parser = new PatternParser("Bar<T,S extends T, R extends S>");
try {
- TypePattern tp = parser.parseTypePattern(false);
+ TypePattern tp = parser.parseTypePattern(false,false);
// TypePattern[] tps = tp.getTypeParameters().getTypePatterns();
// assertEquals("3 type patterns",3,tps.length);
// assertEquals("T",tps[0].toString());
assertEquals("(",pEx.getMessage());
}
}
+
+ public void testIntAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(ival=5) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found","ival=5",getValueString(pc));
+ }
+
+ private String getValueString(Pointcut pc) {
+ if (!(pc instanceof KindedPointcut)) fail("Expected KindedPointcut but was "+pc.getClass());
+ KindedPointcut kpc = (KindedPointcut)pc;
+ AnnotationTypePattern atp = kpc.getSignature().getAnnotationPattern();
+ if (!(atp instanceof WildAnnotationTypePattern)) fail("Expected WildAnnotationTypePattern but was "+atp.getClass());
+ WildAnnotationTypePattern watp = (WildAnnotationTypePattern)atp;
+ Map m = watp.annotationValues;
+ Set keys = m.keySet();
+ List orderedKeys = new ArrayList();
+ orderedKeys.addAll(keys);
+ Collections.sort(orderedKeys);
+ StringBuffer sb = new StringBuffer();
+ for (Iterator iterator = orderedKeys.iterator(); iterator.hasNext();) {
+ String object = (String) iterator.next();
+ sb.append(object).append("=").append(m.get(object));
+ if (iterator.hasNext()) sb.append(",");
+ }
+ return sb.toString();
+ }
+
+ public void testByteAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(bval=5) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found","bval=5",getValueString(pc));
+ }
+
+ public void testCharAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(cval='5') * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found","cval='5'",getValueString(pc));
+ }
+
+ public void testLongAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(jval=123123) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found","jval=123123",getValueString(pc));
+ }
+
+ public void testDoubleAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(dval=123.3) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found","dval=123.3",getValueString(pc));
+ }
+
+ public void testBooleanAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(zval=true) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found","zval=true",getValueString(pc));
+ }
+
+ public void testShortAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(sval=43) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found","sval=43",getValueString(pc));
+ }
+
+ public void testEnumAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(enumval=Color.GREEN) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found","enumval=Color.GREEN",getValueString(pc));
+ }
+
+ public void testStringAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(strval=\"abc\") * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ // notice quotes stripped...
+ assertEquals("Expected annotation value not found","strval=abc",getValueString(pc));
+ }
+
+ public void testClassAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(classval=String.class) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found","classval=String.class",getValueString(pc));
+ }
+
+ // failing as {1 is treated as a single token and so we don't realise the , is within the curlies
+// public void testArrayAnnotationVal() {
+// PatternParser parser = new PatternParser("execution(@ComplexAnnotation(arrayval={1,2,3}) * *(..))");
+// Pointcut pc = parser.parsePointcut();
+// assertEquals("Expected annotation value not found","arrayval={1,2,3}",getValueString(pc));
+// }
+
+
+
+
+ // ---
public TestScope makeSimpleScope() {
BcelWorld world = new BcelWorld();
public void testThrowsMatch() throws IOException {
- Member onlyDerivedOnDerived = MemberImpl.methodFromString("static void fluffy.Derived.onlyDerived()");
- Member mOnBase = MemberImpl.methodFromString("void fluffy.Base.m()");
- Member mOnDerived = MemberImpl.methodFromString("void fluffy.Derived.m()");
+ Member onlyDerivedOnDerived = TestUtils.methodFromString("static void fluffy.Derived.onlyDerived()");
+ Member mOnBase = TestUtils.methodFromString("void fluffy.Base.m()");
+ Member mOnDerived = TestUtils.methodFromString("void fluffy.Derived.m()");
checkMatch(makeMethodPat("* fluffy.Base.*(..) throws java.lang.CloneNotSupportedException"),
new Member[] { mOnBase },
}
public void testInstanceMethodMatch() throws IOException {
- Member objectToString = MemberImpl.methodFromString("java.lang.String java.lang.Object.toString()");
- Member integerToString = MemberImpl.methodFromString("java.lang.String java.lang.Integer.toString()");
- Member integerIntValue = MemberImpl.methodFromString("int java.lang.Integer.intValue()");
+ Member objectToString = TestUtils.methodFromString("java.lang.String java.lang.Object.toString()");
+ Member integerToString = TestUtils.methodFromString("java.lang.String java.lang.Integer.toString()");
+ Member integerIntValue = TestUtils.methodFromString("int java.lang.Integer.intValue()");
//Member objectToString = Member.methodFromString("java.lang.String java.lang.Object.toString()");
checkMatch(makeMethodPat("* java.lang.Object.*(..)"),
public void testStaticMethodMatch() throws IOException {
- Member onlyBaseOnBase = MemberImpl.methodFromString("static void fluffy.Base.onlyBase()");
- Member onlyBaseOnDerived = MemberImpl.methodFromString("static void fluffy.Derived.onlyBase()");
- Member onlyDerivedOnDerived = MemberImpl.methodFromString("static void fluffy.Derived.onlyDerived()");
- Member bothOnBase = MemberImpl.methodFromString("static void fluffy.Base.both()");
- Member bothOnDerived = MemberImpl.methodFromString("static void fluffy.Derived.both()");
+ Member onlyBaseOnBase = TestUtils.methodFromString("static void fluffy.Base.onlyBase()");
+ Member onlyBaseOnDerived = TestUtils.methodFromString("static void fluffy.Derived.onlyBase()");
+ Member onlyDerivedOnDerived = TestUtils.methodFromString("static void fluffy.Derived.onlyDerived()");
+ Member bothOnBase = TestUtils.methodFromString("static void fluffy.Base.both()");
+ Member bothOnDerived = TestUtils.methodFromString("static void fluffy.Derived.both()");
checkMatch(makeMethodPat("* fluffy.Base.*(..)"),
new Member[] { onlyBaseOnBase, onlyBaseOnDerived, bothOnBase },
}
public void testFieldMatch() throws IOException {
- Member onlyBaseOnBase = MemberImpl.fieldFromString("int fluffy.Base.onlyBase");
- Member onlyBaseOnDerived = MemberImpl.fieldFromString("int fluffy.Derived.onlyBase");
- Member onlyDerivedOnDerived = MemberImpl.fieldFromString("int fluffy.Derived.onlyDerived");
- Member bothOnBase = MemberImpl.fieldFromString("int fluffy.Base.both");
- Member bothOnDerived = MemberImpl.fieldFromString("int fluffy.Derived.both");
+ Member onlyBaseOnBase = TestUtils.fieldFromString("int fluffy.Base.onlyBase");
+ Member onlyBaseOnDerived = TestUtils.fieldFromString("int fluffy.Derived.onlyBase");
+ Member onlyDerivedOnDerived = TestUtils.fieldFromString("int fluffy.Derived.onlyDerived");
+ Member bothOnBase = TestUtils.fieldFromString("int fluffy.Base.both");
+ Member bothOnDerived = TestUtils.fieldFromString("int fluffy.Derived.both");
checkMatch(makeFieldPat("* fluffy.Base.*"),
new Member[] { onlyBaseOnBase, onlyBaseOnDerived, bothOnBase },
}
public void testConstructorMatch() throws IOException {
- Member onBase = MemberImpl.methodFromString("void fluffy.Base.<init>()");
- Member onDerived = MemberImpl.methodFromString("void fluffy.Derived.<init>()");
- Member onBaseWithInt = MemberImpl.methodFromString("void fluffy.Base.<init>(int)");
+ Member onBase = TestUtils.methodFromString("void fluffy.Base.<init>()");
+ Member onDerived = TestUtils.methodFromString("void fluffy.Derived.<init>()");
+ Member onBaseWithInt = TestUtils.methodFromString("void fluffy.Base.<init>(int)");
checkMatch(makeMethodPat("fluffy.Base.new(..)"),
}
private TypePatternList makeArgumentsPattern(String pattern) {
- return new PatternParser(pattern).parseArgumentsPattern();
+ return new PatternParser(pattern).parseArgumentsPattern(false);
}
private void checkStaticMatch(String pattern, String[] names,
}
private TestScope makeTestScope() {
- TestScope scope = new TestScope(CollectionUtil.NO_STRINGS, CollectionUtil.NO_STRINGS, world);
+ TestScope scope = new TestScope(LangUtil.NO_STRINGS, LangUtil.NO_STRINGS, world);
return scope;
}
for (Iterator iterator = pointcuts.iterator(); iterator.hasNext();) {
String pointcut = (String) iterator.next();
try {
- PatternNodeVisitor.DumpPointcutVisitor.check(pointcut);
+ DumpPointcutVisitor.check(pointcut);
} catch (Throwable t) {
t.printStackTrace();
fail("Failed on '"+pointcut+"': " +t.toString());
String tp = (String) iterator.next();
try {
TypePattern p = new PatternParser(tp).parseTypePattern();
- PatternNodeVisitor.DumpPointcutVisitor.check(p, true);
+ DumpPointcutVisitor.check(p, true);
} catch (Throwable t) {
fail("Failed on '"+tp+"': " +t.toString());
}
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.IntMap;
import org.aspectj.weaver.MemberImpl;
+import org.aspectj.weaver.TestUtils;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.TestShadow;
import org.aspectj.weaver.UnresolvedType;
public void testMatch() throws IOException {
Shadow getOutFromArrayList = new TestShadow(
Shadow.FieldGet,
- MemberImpl.fieldFromString("java.io.PrintStream java.lang.System.out"),
+ TestUtils.fieldFromString("java.io.PrintStream java.lang.System.out"),
UnresolvedType.forName("java.util.ArrayList"),
world);
Shadow getOutFromEntry = new TestShadow(
Shadow.FieldGet,
- MemberImpl.fieldFromString("java.io.PrintStream java.lang.System.out"),
+ TestUtils.fieldFromString("java.io.PrintStream java.lang.System.out"),
UnresolvedType.forName("java.util.Map$Entry"),
world);
* ******************************************************************/
package org.aspectj.weaver.tools;
-import org.aspectj.util.LangUtil;
-
import junit.framework.TestCase;
+import org.aspectj.util.LangUtil;
+
/**
- * @author Adrian
- *
+ * @author Adrian Colyer
+ *
*/
public class PointcutDesignatorHandlerTests extends TestCase {
assertEquals("service.*",beanHandler.getExpressionLastAskedToParse());
}
- public void testParseWithHandlerAndMultipleSegments() {
- if (needToSkip) return;
- PointcutParser parser = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution();
+
+ /*
+ * Bug 205907 - the registered pointcut designator does not also get registered with the
+ * InternalUseOnlyPointcutParser inside the Java15ReflectionBasedReferenceTypeDelegate code. First test checks
+ * parsing is OK
+ */
+ public void testParsingBeanInReferencePointcut01() throws Exception {
+ if (needToSkip) return;
+ PointcutParser parser = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution();
+ BeanDesignatorHandler beanHandler = new BeanDesignatorHandler();
+ parser.registerPointcutDesignatorHandler(beanHandler);
+ // The pointcut in CounterAspect look as follows:
+ //
+ // @Pointcut("execution(* setAge(..)) && bean(testBean1)")
+ // public void testBean1SetAge() { }
+
+ // This should be found and resolved
+ PointcutExpression pc = parser.parsePointcutExpression("CounterAspect.testBean1SetAge()");
+
+ }
+
+ /*
+ * Bug 205907 - the registered pointcut designator does not also get registered with the
+ * InternalUseOnlyPointcutParser inside the Java15ReflectionBasedReferenceTypeDelegate code. This test checks the
+ * actual matching.
+ */
+ public void testParsingBeanInReferencePointcut02() throws Exception {
+ if (needToSkip) return;
+ PointcutParser parser = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution();
+ BeanDesignatorHandler beanHandler = new BeanDesignatorHandler();
+ parser.registerPointcutDesignatorHandler(beanHandler);
+ // The pointcut in CounterAspect look as follows:
+ //
+ // @Pointcut("execution(* toString(..)) && bean(testBean1)")
+ // public void testBean1toString() { }
+
+ // This should be found and resolved
+ PointcutExpression pc = parser.parsePointcutExpression("CounterAspect.testBean1toString()");
+
+ DefaultMatchingContext context = new DefaultMatchingContext();
+ context.addContextBinding("beanName", "testBean1");
+ pc.setMatchingContext(context);
+ ShadowMatch sm = pc.matchesMethodExecution(Object.class.getMethod("toString", new Class[0]));
+ assertTrue(sm.alwaysMatches());
+
+ sm = pc.matchesMethodExecution(Object.class.getMethod("hashCode", new Class[0]));
+ assertTrue(sm.neverMatches());
+
+ context = new DefaultMatchingContext();
+ context.addContextBinding("beanName", "testBean2");
+ pc.setMatchingContext(context);
+ sm = pc.matchesMethodExecution(Object.class.getMethod("toString", new Class[0]));
+ assertTrue(sm.neverMatches());
+ }
+
+ public void testParseWithHandlerAndMultipleSegments() {
+ if (needToSkip) return;
+ PointcutParser parser = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution();
BeanDesignatorHandler beanHandler = new BeanDesignatorHandler();
parser.registerPointcutDesignatorHandler(beanHandler);
parser.parsePointcutExpression("bean(org.xyz.someapp..*)");
return this.beanNamePattern.equals(matchContext.getBinding("beanName"));
}
}
-}
\ No newline at end of file
+}