aboutsummaryrefslogtreecommitdiffstats
path: root/weaver/src/org
diff options
context:
space:
mode:
authorAndy Clement <aclement@pivotal.io>2019-01-25 15:14:30 -0800
committerAndy Clement <aclement@pivotal.io>2019-01-25 15:14:30 -0800
commitd3da67c03dc7d19782d60d82fdf8fc7c7895280e (patch)
treeb8c82793fa0b6843e022a126f942dc132133b3fd /weaver/src/org
parent7758d629f9bc6818709d5ae97bbb98a27c908f75 (diff)
downloadaspectj-d3da67c03dc7d19782d60d82fdf8fc7c7895280e.tar.gz
aspectj-d3da67c03dc7d19782d60d82fdf8fc7c7895280e.zip
mavenizing weaver - wip
Diffstat (limited to 'weaver/src/org')
-rw-r--r--weaver/src/org/aspectj/weaver/IClassFileProvider.java44
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/AnnotationAccessFieldVar.java186
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/AnnotationAccessVar.java272
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/AspectInstanceVar.java119
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java2046
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelAccessForInlineMunger.java386
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java801
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelAnnotation.java151
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelCflowAccessVar.java87
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelCflowCounterFieldAdder.java88
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelCflowStackFieldAdder.java77
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java3377
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelConstantPoolReader.java34
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelConstantPoolWriter.java34
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelField.java307
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelFieldRef.java100
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXConverter.java278
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelMethod.java714
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java1023
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java560
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelRenderer.java270
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelShadow.java3425
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java2116
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelVar.java117
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelWeakClassLoaderReference.java49
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java2043
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelWeavingSupport.java71
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelWorld.java1329
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java579
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/ExceptionRange.java151
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/ExtensibleURLClassLoader.java113
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/FakeAnnotation.java80
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/IfFinder.java56
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java1940
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java1870
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/Range.java243
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/ShadowRange.java244
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/TypeAnnotationAccessVar.java80
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/TypeDelegateResolver.java28
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/UnwovenClassFile.java200
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/UnwovenClassFileWithThirdPartyManagedBytecode.java36
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/Utility.java719
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/asm/AsmDetector.java36
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/asm/StackMapAdder.java121
-rw-r--r--weaver/src/org/aspectj/weaver/loadtime/IWeavingContext.java92
-rw-r--r--weaver/src/org/aspectj/weaver/loadtime/definition/Definition.java222
-rw-r--r--weaver/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java382
-rw-r--r--weaver/src/org/aspectj/weaver/loadtime/definition/LightXMLParser.java471
-rw-r--r--weaver/src/org/aspectj/weaver/loadtime/definition/SimpleAOPParser.java265
-rw-r--r--weaver/src/org/aspectj/weaver/ltw/LTWWorld.java294
-rw-r--r--weaver/src/org/aspectj/weaver/model/AsmRelationshipProvider.java1133
-rw-r--r--weaver/src/org/aspectj/weaver/model/AsmRelationshipUtils.java79
-rw-r--r--weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java951
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/AbstractCacheBacking.java45
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/AbstractFileCacheBacking.java86
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/AbstractIndexedFileCacheBacking.java262
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/AsynchronousFileCacheBacking.java424
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/CacheBacking.java63
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/CacheFactory.java25
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/CacheKeyResolver.java88
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/CacheStatistics.java107
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/CachedClassEntry.java90
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/CachedClassReference.java85
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/DefaultCacheFactory.java26
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/DefaultCacheKeyResolver.java117
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/DefaultFileCacheBacking.java289
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/FlatFileCacheBacking.java139
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/GeneratedCachedClassHandler.java39
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/SimpleCache.java377
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/SimpleCacheFactory.java104
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/WeavedClassCache.java278
-rw-r--r--weaver/src/org/aspectj/weaver/tools/cache/ZippedFileCacheBacking.java321
72 files changed, 0 insertions, 33454 deletions
diff --git a/weaver/src/org/aspectj/weaver/IClassFileProvider.java b/weaver/src/org/aspectj/weaver/IClassFileProvider.java
deleted file mode 100644
index 029bba7c6..000000000
--- a/weaver/src/org/aspectj/weaver/IClassFileProvider.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * 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:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.aspectj.weaver;
-
-import java.util.Iterator;
-
-import org.aspectj.weaver.bcel.UnwovenClassFile;
-
-/**
- * @author colyer
- *
- * Clients implementing the IClassFileProvider can have a set of class files under their control woven by a weaver, by
- * calling the weave(IClassFileProvider source) method. The contract is that a call to getRequestor().acceptResult() is
- * providing a result for the class file most recently returned from the getClassFileIterator().
- */
-public interface IClassFileProvider {
-
- /**
- * Answer an iterator that can be used to iterate over a set of UnwovenClassFiles to be woven. During a weave, this method may
- * be called multiple times.
- *
- * @return iterator over UnwovenClassFiles.
- */
- Iterator<UnwovenClassFile> getClassFileIterator();
-
- /**
- * The client to which the woven results should be returned.
- */
- IWeaveRequestor getRequestor();
-
- /**
- * @return true if weaver should only do some internal munging as the one needed for @AspectJ aspectOf methods creation
- */
- boolean isApplyAtAspectJMungersOnly();
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/AnnotationAccessFieldVar.java b/weaver/src/org/aspectj/weaver/bcel/AnnotationAccessFieldVar.java
deleted file mode 100644
index 60aa84125..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/AnnotationAccessFieldVar.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/* *******************************************************************
- * 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.bcel;
-
-import java.util.List;
-
-import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
-import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
-import org.aspectj.apache.bcel.classfile.annotation.EnumElementValue;
-import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
-import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValue;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.apache.bcel.generic.Type;
-import org.aspectj.weaver.AnnotationAJ;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.Shadow;
-import org.aspectj.weaver.UnresolvedType;
-
-/**
- * An AnnotationAccessVar represents access to a particular annotation, whilst an AnnotationAccessFieldVar represents access to a
- * specific field of that annotation.
- *
- * @author Andy Clement
- */
-class AnnotationAccessFieldVar extends BcelVar {
-
- private AnnotationAccessVar annoAccessor;
- private ResolvedType annoFieldOfInterest;
- private String name;
- private int elementValueType;
-
- public AnnotationAccessFieldVar(AnnotationAccessVar aav, ResolvedType annoFieldOfInterest, String name) {
- super(annoFieldOfInterest, 0);
- this.annoAccessor = aav;
- this.name = name;
- String sig = annoFieldOfInterest.getSignature();
- if (sig.length() == 1) {
- switch (sig.charAt(0)) {
- case 'I':
- elementValueType = ElementValue.PRIMITIVE_INT;
- break;
- default:
- throw new IllegalStateException(sig);
- }
- } else if (sig.equals("Ljava/lang/String;")) {
- elementValueType = ElementValue.STRING;
- } else if (annoFieldOfInterest.isEnum()) {
- elementValueType = ElementValue.ENUM_CONSTANT;
- } else {
- throw new IllegalStateException(sig);
- }
- this.annoFieldOfInterest = annoFieldOfInterest;
- }
-
- @Override
- public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) {
- // Only possible to do annotation field value extraction at MethodExecution
- if (annoAccessor.getKind() != Shadow.MethodExecution) {
- return;
- }
- String annotationOfInterestSignature = annoAccessor.getType().getSignature();
- // So we have an entity that has an annotation on and within it is the value we want
- Member holder = annoAccessor.getMember();
- AnnotationAJ[] annos = holder.getAnnotations();
- for (AnnotationAJ anno : annos) {
- AnnotationGen annotation = ((BcelAnnotation) anno).getBcelAnnotation();
- boolean foundValueInAnnotationUsage = false;
- if (annotation.getTypeSignature().equals(annotationOfInterestSignature)) {
- ResolvedMember[] annotationFields = toType.getWorld()
- .resolve(UnresolvedType.forSignature(annotation.getTypeSignature())).getDeclaredMethods();
- // Check how many fields there are of the type we are looking for. If >1 then we'll need
- // to use the name to choose the right one
- int countOfType = 0;
- for (ResolvedMember annotationField : annotationFields) {
- if (annotationField.getType().equals(annoFieldOfInterest)) {
- countOfType++;
- }
- }
-
- // this block deals with an annotation that has actual values (i.e. not falling back to default values)
- List<NameValuePair> nvps = annotation.getValues();
- for (NameValuePair nvp : nvps) {
- // If multiple of the same type, match by name
- if (countOfType > 1) {
- if (!nvp.getNameString().equals(name)) {
- continue;
- }
- }
- ElementValue o = nvp.getValue();
- if (o.getElementValueType() != elementValueType) {
- continue;
- }
- if (o instanceof EnumElementValue) {
- EnumElementValue v = (EnumElementValue) o;
- String s = v.getEnumTypeString();
- ResolvedType rt = toType.getWorld().resolve(UnresolvedType.forSignature(s));
- if (rt.equals(toType)) {
- il.append(fact.createGetStatic(rt.getName(), v.getEnumValueString(), Type.getType(rt.getSignature())));
- foundValueInAnnotationUsage = true;
- }
- } else if (o instanceof SimpleElementValue) {
- SimpleElementValue v = (SimpleElementValue) o;
- switch (v.getElementValueType()) {
- case ElementValue.PRIMITIVE_INT:
- il.append(fact.createConstant(v.getValueInt()));
- foundValueInAnnotationUsage = true;
- break;
- case ElementValue.STRING:
- il.append(fact.createConstant(v.getValueString()));
- foundValueInAnnotationUsage = true;
- break;
- default:
- throw new IllegalStateException("NYI: Unsupported annotation value binding for " + o);
- }
- }
- if (foundValueInAnnotationUsage) {
- break;
- }
- }
- // this block deals with default values
- if (!foundValueInAnnotationUsage) {
- for (ResolvedMember annotationField : annotationFields) {
- if (countOfType > 1) {
- if (!annotationField.getName().equals(name)) {
- continue;
- }
- }
- if (!annotationField.getType().getSignature().equals(annoFieldOfInterest.getSignature())) {
- continue;
- }
- if (annotationField.getType().getSignature().equals("I")) {
- int ivalue = Integer.parseInt(annotationField.getAnnotationDefaultValue());
- il.append(fact.createConstant(ivalue));
- foundValueInAnnotationUsage = true;
- break;
- } else if (annotationField.getType().getSignature().equals("Ljava/lang/String;")) {
- String svalue = annotationField.getAnnotationDefaultValue();
- il.append(fact.createConstant(svalue));
- foundValueInAnnotationUsage = true;
- break;
- } else {
- String dvalue = annotationField.getAnnotationDefaultValue();
- // form will be LBLAHBLAHBLAH;X where X is the field within X
- String typename = dvalue.substring(0, dvalue.lastIndexOf(';') + 1);
- String field = dvalue.substring(dvalue.lastIndexOf(';') + 1);
- ResolvedType rt = toType.getWorld().resolve(UnresolvedType.forSignature(typename));
- il.append(fact.createGetStatic(rt.getName(), field, Type.getType(rt.getSignature())));
- foundValueInAnnotationUsage = true;
- break;
- }
- }
- }
- }
- if (foundValueInAnnotationUsage) {
- break;
- }
- }
- }
-
- @Override
- public void insertLoad(InstructionList il, InstructionFactory fact) {
- // Only possible to do annotation field value extraction at
- // MethodExecution
- if (annoAccessor.getKind() != Shadow.MethodExecution) {
- return;
- }
- appendLoadAndConvert(il, fact, annoFieldOfInterest);
- }
-
- @Override
- public String toString() {
- return super.toString();
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/AnnotationAccessVar.java b/weaver/src/org/aspectj/weaver/bcel/AnnotationAccessVar.java
deleted file mode 100644
index 88a67d666..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/AnnotationAccessVar.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/* *******************************************************************
- * 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.classfile.Field;
-import org.aspectj.apache.bcel.generic.Instruction;
-import org.aspectj.apache.bcel.generic.InstructionBranch;
-import org.aspectj.apache.bcel.generic.InstructionConstants;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionHandle;
-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.Shadow.Kind;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.ast.Var;
-
-/**
- * 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 BcelShadow shadow;
- 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)
- private boolean isWithin; // implies @within() or @withincode(). If false, that implies @annotation()
-
- public AnnotationAccessVar(BcelShadow shadow, Kind kind, ResolvedType annotationType, UnresolvedType theTargetIsStoredHere,
- Member sig, boolean isWithin) {
- super(annotationType, 0);
- this.shadow = shadow;
- this.kind = kind;
- this.containingType = theTargetIsStoredHere;
- this.member = sig;
- this.isWithin = isWithin;
- }
-
- public Kind getKind() {
- return kind;
- }
-
- @Override
- public String toString() {
- return "AnnotationAccessVar(" + getType() + ")";
- }
-
- @Override
- public Instruction createLoad(InstructionFactory fact) {
- throw new IllegalStateException("unimplemented");
- }
-
- @Override
- public Instruction createStore(InstructionFactory fact) {
- throw new IllegalStateException("unimplemented");
- }
-
- @Override
- public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) {
- throw new IllegalStateException("unimplemented");
- }
-
- @Override
- public void appendLoad(InstructionList il, InstructionFactory fact) {
- il.append(createLoadInstructions(getType(), fact));
- }
-
- @Override
- public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) {
- il.append(createLoadInstructions(toType, fact));
- }
-
- @Override
- 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.JL_CLASS);
- Type jlString = BcelWorld.makeBcelType(UnresolvedType.JL_STRING);
- Type jlClassArray = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_CLASS_ARRAY);
- Type jlaAnnotation = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_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 jlAnnotation = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava/lang/annotation/Annotation;"));
- 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)) {
-
- // Need to look at the cached annotation before going to fetch it again
- Field annotationCachingField = shadow.getEnclosingClass().getAnnotationCachingField(shadow, toType, isWithin);
-
- // Basic idea here is to check if the cached field is null, if it is then initialize it, otherwise use it
- il.append(fact.createGetStatic(shadow.getEnclosingClass().getName(), annotationCachingField.getName(), jlAnnotation));
- il.append(InstructionConstants.DUP);
- InstructionBranch ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
- il.append(ifNonNull);
- il.append(InstructionConstants.POP);
- il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));
-
- il.append(fact.createConstant(member.getName()));
- buildArray(il, fact, jlClass, paramTypes, 1);
- // OPTIMIZE cache result of getDeclaredMethod?
- 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));
- il.append(InstructionConstants.DUP);
- il.append(fact.createPutStatic(shadow.getEnclosingClass().getName(), annotationCachingField.getName(), jlAnnotation));
- InstructionHandle ifNullElse = il.append(InstructionConstants.NOP);
- ifNonNull.setTarget(ifNullElse);
-
- } else { // init/preinit/ctor-call/ctor-exec
- il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));
- buildArray(il, fact, jlClass, paramTypes, 1);
- Type jlrCtor = BcelWorld.makeBcelType(UnresolvedType.JAVA_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) {
- generateBytecodeToAccessAnnotationAtFieldGetSetShadow(toType, fact, il, pushConstant);
- } 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;
- }
-
- /**
- * At a FieldGet or FieldSet shadow, generate the bytecode to access the annotation for that field. The annotation is cached so
- * the code checks that cached value before proceeding.
- */
- private void generateBytecodeToAccessAnnotationAtFieldGetSetShadow(ResolvedType toType, InstructionFactory fact,
- InstructionList il, Instruction pushConstantAnnotationType) {
- Type jlClass = BcelWorld.makeBcelType(UnresolvedType.JL_CLASS);
- Type jlString = BcelWorld.makeBcelType(UnresolvedType.JL_STRING);
- Type jlaAnnotation = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_ANNOTATION);
- Type jlrField = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_REFLECT_FIELD);
-
- LazyClassGen shadowEnclosingClass = shadow.getEnclosingClass();
-
- // The annotation for the field of interest is cached, check cached value before fetching it
- Field annotationCachingField = shadowEnclosingClass.getAnnotationCachingField(shadow, toType, isWithin);
- String annotationCachingFieldName = annotationCachingField.getName();
-
- // Basic idea here is to check if the cached field is null, if it is then initialize it, otherwise use it
- il.append(fact.createGetStatic(shadowEnclosingClass.getName(), annotationCachingFieldName, jlaAnnotation));
- il.appendDUP();
- InstructionBranch ifNonNull = new InstructionBranch(Constants.IFNONNULL, null);
- il.append(ifNonNull);
- il.appendPOP();
-
- // get the field of interest
- il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));
- il.append(fact.createConstant(member.getName()));
- il.append(fact.createInvoke("java/lang/Class", "getDeclaredField", jlrField, new Type[] { jlString },
- Constants.INVOKEVIRTUAL));
- il.append(pushConstantAnnotationType);
- il.append(fact.createInvoke("java/lang/reflect/Field", "getAnnotation", jlaAnnotation, new Type[] { jlClass },
- Constants.INVOKEVIRTUAL));
- il.appendDUP();
- il.append(fact.createPutStatic(shadowEnclosingClass.getName(), annotationCachingFieldName, jlaAnnotation));
- InstructionHandle ifNullElse = il.appendNOP();
- ifNonNull.setTarget(ifNullElse);
- }
-
- 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()))); // FIXME should be getName() and not
- // 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 Member getMember() {
- return member;
- }
-
- /**
- * Return an object that can access a particular value of this annotation.
- *
- * @param valueType The type from the annotation that is of interest
- * @param the formal name expressed in the pointcut, can be used to disambiguate
- * @return a variable that represents access to that annotation value
- */
- @Override
- public Var getAccessorForValue(ResolvedType valueType, String formalName) {
- return new AnnotationAccessFieldVar(this, valueType, formalName);
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/AspectInstanceVar.java b/weaver/src/org/aspectj/weaver/bcel/AspectInstanceVar.java
deleted file mode 100644
index 37633b71f..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/AspectInstanceVar.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2011 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 - SpringSource/vmware
- * ******************************************************************/
-package org.aspectj.weaver.bcel;
-
-import org.aspectj.apache.bcel.Constants;
-import org.aspectj.apache.bcel.generic.Instruction;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.weaver.ResolvedType;
-
-/**
- * Used to represent a variable reference to an aspect instance. This is used to support the if pointcut usage of
- * 'thisAspectInstance'. This variable does not have a slot, instead on requesting a reference we call aspectOf() on the aspect in
- * question to retrieve it. For now it only works with singleton aspects.
- */
-public class AspectInstanceVar extends BcelVar {
-
- public AspectInstanceVar(ResolvedType type) {
- super(type, -1);
- }
-
- // fact is used in the subtypes
- public Instruction createLoad(InstructionFactory fact) {
-
- throw new IllegalStateException();
- // return InstructionFactory.createLoad(BcelWorld.makeBcelType(getType()), slot);
- }
-
- public Instruction createStore(InstructionFactory fact) {
- throw new IllegalStateException();
- // return InstructionFactory.createStore(BcelWorld.makeBcelType(getType()), slot);
- }
-
- public void appendStore(InstructionList il, InstructionFactory fact) {
- throw new IllegalStateException();
- // il.append(createStore(fact));
- }
-
- public void appendLoad(InstructionList il, InstructionFactory fact) {
- throw new IllegalStateException();
- // il.append(createLoad(fact));
- }
-
- public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) {
- throw new IllegalStateException();
- // il.append(createLoad(fact));
- // Utility.appendConversion(il, fact, getType(), toType);
- }
-
- public void insertLoad(InstructionList il, InstructionFactory fact) {
- InstructionList loadInstructions = new InstructionList();
- loadInstructions.append(fact.createInvoke(getType().getName(), "aspectOf", "()" + getType().getSignature(),
- Constants.INVOKESTATIC));
- il.insert(loadInstructions);
- // throw new IllegalStateException();
- // il.insert(createLoad(fact));
- }
-
- public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) {
- throw new IllegalStateException();
- // InstructionList il = new InstructionList();
- // il.append(InstructionFactory.createLoad(BcelWorld.makeBcelType(getType()), oldSlot));
- // il.append(createStore(fact));
- // return il;
- }
-
- // this is an array var
- void appendConvertableArrayLoad(InstructionList il, InstructionFactory fact, int index, ResolvedType convertTo) {
- throw new IllegalStateException();
- // ResolvedType convertFromType = getType().getResolvedComponentType();
- // appendLoad(il, fact);
- // il.append(Utility.createConstant(fact, index));
- // il.append(InstructionFactory.createArrayLoad(BcelWorld.makeBcelType(convertFromType)));
- // Utility.appendConversion(il, fact, convertFromType, convertTo);
- }
-
- void appendConvertableArrayStore(InstructionList il, InstructionFactory fact, int index, BcelVar storee) {
- throw new IllegalStateException();
- // ResolvedType convertToType = getType().getResolvedComponentType();
- // appendLoad(il, fact);
- // il.append(Utility.createConstant(fact, index));
- // storee.appendLoad(il, fact);
- // Utility.appendConversion(il, fact, storee.getType(), convertToType);
- // il.append(InstructionFactory.createArrayStore(BcelWorld.makeBcelType(convertToType)));
- }
-
- InstructionList createConvertableArrayStore(InstructionFactory fact, int index, BcelVar storee) {
- throw new IllegalStateException();
- // InstructionList il = new InstructionList();
- // appendConvertableArrayStore(il, fact, index, storee);
- // return il;
- }
-
- InstructionList createConvertableArrayLoad(InstructionFactory fact, int index, ResolvedType convertTo) {
- throw new IllegalStateException();
- // InstructionList il = new InstructionList();
- // appendConvertableArrayLoad(il, fact, index, convertTo);
- // return il;
- }
-
- public int getPositionInAroundState() {
- throw new IllegalStateException();
- // return positionInAroundState;
- }
-
- public void setPositionInAroundState(int positionInAroundState) {
- throw new IllegalStateException();
- // this.positionInAroundState = positionInAroundState;
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java
deleted file mode 100644
index 2da044c11..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java
+++ /dev/null
@@ -1,2046 +0,0 @@
-/*******************************************************************************
- * 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:
- * initial implementation Alexandre Vasseur
- *******************************************************************************/
-package org.aspectj.weaver.bcel;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-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.apache.bcel.classfile.Constant;
-import org.aspectj.apache.bcel.classfile.ConstantUtf8;
-import org.aspectj.apache.bcel.classfile.Field;
-import org.aspectj.apache.bcel.classfile.JavaClass;
-import org.aspectj.apache.bcel.classfile.LocalVariable;
-import org.aspectj.apache.bcel.classfile.LocalVariableTable;
-import org.aspectj.apache.bcel.classfile.Method;
-import org.aspectj.apache.bcel.classfile.Unknown;
-import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
-import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValue;
-import org.aspectj.apache.bcel.classfile.annotation.ClassElementValue;
-import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
-import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
-import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnos;
-import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisAnnos;
-import org.aspectj.apache.bcel.generic.Type;
-import org.aspectj.asm.AsmManager;
-import org.aspectj.asm.IHierarchy;
-import org.aspectj.asm.IProgramElement;
-import org.aspectj.bridge.IMessage;
-import org.aspectj.bridge.IMessageHandler;
-import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.bridge.Message;
-import org.aspectj.bridge.MessageUtil;
-import org.aspectj.weaver.Advice;
-import org.aspectj.weaver.AdviceKind;
-import org.aspectj.weaver.AjAttribute;
-import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
-import org.aspectj.weaver.AjcMemberMaker;
-import org.aspectj.weaver.BindingScope;
-import org.aspectj.weaver.ISourceContext;
-import org.aspectj.weaver.MethodDelegateTypeMunger;
-import org.aspectj.weaver.NameMangler;
-import org.aspectj.weaver.ReferenceType;
-import org.aspectj.weaver.ReferenceTypeDelegate;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedPointcutDefinition;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.VersionedDataInputStream;
-import org.aspectj.weaver.WeaverMessages;
-import org.aspectj.weaver.World;
-import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
-import org.aspectj.weaver.patterns.DeclareParents;
-import org.aspectj.weaver.patterns.DeclareParentsMixin;
-import org.aspectj.weaver.patterns.DeclarePrecedence;
-import org.aspectj.weaver.patterns.FormalBinding;
-import org.aspectj.weaver.patterns.IScope;
-import org.aspectj.weaver.patterns.ParserException;
-import org.aspectj.weaver.patterns.PatternParser;
-import org.aspectj.weaver.patterns.PerCflow;
-import org.aspectj.weaver.patterns.PerClause;
-import org.aspectj.weaver.patterns.PerFromSuper;
-import org.aspectj.weaver.patterns.PerObject;
-import org.aspectj.weaver.patterns.PerSingleton;
-import org.aspectj.weaver.patterns.PerTypeWithin;
-import org.aspectj.weaver.patterns.Pointcut;
-import org.aspectj.weaver.patterns.TypePattern;
-
-/**
- * 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>
- */
-public class AtAjAttributes {
-
- private final static List<AjAttribute> NO_ATTRIBUTES = Collections.emptyList();
- 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";
- private final static String STRING_DESC = "Ljava/lang/String;";
- private final static String ASPECTJ_ANNOTATION_PACKAGE = "org.aspectj.lang.annotation";
- private final static char PACKAGE_INITIAL_CHAR = ASPECTJ_ANNOTATION_PACKAGE.charAt(0);
-
- /**
- * A struct that allows to add extra arguments without always breaking the API
- */
- private static class AjAttributeStruct {
-
- /**
- * The list of AjAttribute.XXX that we are populating from the @AJ read
- */
- List<AjAttribute> ajAttributes = new ArrayList<AjAttribute>();
-
- /**
- * The resolved type (class) for which we are reading @AJ for (be it class, method, field annotations)
- */
- final ResolvedType enclosingType;
-
- final ISourceContext context;
- final IMessageHandler handler;
-
- public AjAttributeStruct(ResolvedType type, ISourceContext sourceContext, IMessageHandler messageHandler) {
- enclosingType = type;
- context = sourceContext;
- handler = messageHandler;
- }
- }
-
- /**
- * A struct when we read @AJ on method
- *
- * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
- */
- private static class AjAttributeMethodStruct extends AjAttributeStruct {
-
- // 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 AjAttributeMethodStruct(Method method, BcelMethod bMethod, ResolvedType type, ISourceContext sourceContext,
- IMessageHandler messageHandler) {
- super(type, sourceContext, messageHandler);
- this.method = method;
- this.bMethod = bMethod;
- }
-
- public String[] getArgumentNames() {
- if (m_argumentNamesLazy == null) {
- m_argumentNamesLazy = getMethodArgumentNames(method, unparsedArgumentNames, this);
- }
- return m_argumentNamesLazy;
- }
- }
-
- /**
- * A struct when we read @AJ on field
- */
- private static class AjAttributeFieldStruct extends AjAttributeStruct {
-
- final Field field;
-
- // final BcelField bField;
-
- public AjAttributeFieldStruct(Field field, BcelField bField, ResolvedType type, ISourceContext sourceContext,
- IMessageHandler messageHandler) {
- super(type, sourceContext, messageHandler);
- this.field = field;
- // this.bField = bField;
- }
- }
-
- /**
- * Annotations are RuntimeVisible only. This allow us to not visit RuntimeInvisible ones.
- *
- * @param attribute
- * @return true if runtime visible annotation
- */
- public static boolean acceptAttribute(Attribute attribute) {
- return (attribute instanceof RuntimeVisAnnos);
- }
-
- /**
- * Extract class level annotations and turn them into AjAttributes.
- *
- * @param javaClass
- * @param type
- * @param context
- * @param msgHandler
- * @return list of AjAttributes
- */
- public static List<AjAttribute> readAj5ClassAttributes(AsmManager model, JavaClass javaClass, ReferenceType type,
- ISourceContext context, IMessageHandler msgHandler, boolean isCodeStyleAspect) {
- boolean ignoreThisClass = javaClass.getClassName().charAt(0) == PACKAGE_INITIAL_CHAR
- && javaClass.getClassName().startsWith(ASPECTJ_ANNOTATION_PACKAGE);
- if (ignoreThisClass) {
- return NO_ATTRIBUTES;
- }
- 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).getValue();
- if (constantValue.length() > 28 && constantValue.charAt(1) == PACKAGE_INITIAL_CHAR) {
- 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()
- + "')", IMessage.WARNING, null, type.getSourceLocation()));
- }
- if ("Lorg/aspectj/lang/annotation/Pointcut;".equals(constantValue)) {
- containsPointcut = true;
- }
- }
-
- }
- }
- }
- if (!containsAnnotationClassReference) {
- return NO_ATTRIBUTES;
- }
-
- AjAttributeStruct struct = new AjAttributeStruct(type, context, msgHandler);
- Attribute[] attributes = javaClass.getAttributes();
- boolean hasAtAspectAnnotation = false;
- boolean hasAtPrecedenceAnnotation = false;
-
- WeaverVersionInfo wvinfo = null;
- for (int i = 0; i < attributes.length; i++) {
- Attribute attribute = attributes[i];
- if (acceptAttribute(attribute)) {
- RuntimeAnnos rvs = (RuntimeAnnos) attribute;
- // 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
- hasAtPrecedenceAnnotation = handlePrecedenceAnnotation(rvs, struct);
- }
- // there can only be one RuntimeVisible bytecode attribute
- break;
- }
- }
- for (int i = attributes.length - 1; i >= 0; i--) {
- Attribute attribute = attributes[i];
- if (attribute.getName().equals(WeaverVersionInfo.AttributeName)) {
- try {
- VersionedDataInputStream s = new VersionedDataInputStream(new ByteArrayInputStream(
- ((Unknown) attribute).getBytes()), null);
- wvinfo = WeaverVersionInfo.read(s);
- struct.ajAttributes.add(0, wvinfo);
- } catch (IOException ioe) {
- ioe.printStackTrace();
- }
- }
- }
- if (wvinfo == null) {
- // If we are in here due to a resetState() call (presumably because of reweavable state processing), the
- // original type delegate will have been set with a version but that version will be missing from
- // the new set of attributes (looks like a bug where the version attribute was not included in the
- // data compressed into the attribute). So rather than 'defaulting' to current, we should use one
- // if it set on the delegate for the type.
- ReferenceTypeDelegate delegate = type.getDelegate();
- if (delegate instanceof BcelObjectType) {
- wvinfo = ((BcelObjectType) delegate).getWeaverVersionAttribute();
- if (wvinfo != null) {
- if (wvinfo.getMajorVersion() != WeaverVersionInfo.WEAVER_VERSION_MAJOR_UNKNOWN) {
- // use this one
- struct.ajAttributes.add(0, wvinfo);
- } else {
- wvinfo = null;
- }
- }
- }
- if (wvinfo == null) {
- struct.ajAttributes.add(0, wvinfo = new AjAttribute.WeaverVersionInfo());
- }
- }
-
- // basic semantic check
- if (hasAtPrecedenceAnnotation && !hasAtAspectAnnotation) {
- msgHandler.handleMessage(new Message("Found @DeclarePrecedence on a non @Aspect type '" + type.getName() + "'",
- IMessage.WARNING, null, type.getSourceLocation()));
- // bypass what we have read
- return NO_ATTRIBUTES;
- }
-
- // the following block will not detect @Pointcut in non @Aspect types
- // for optimization purpose
- if (!(hasAtAspectAnnotation || isCodeStyleAspect) && !containsPointcut) {
- return NO_ATTRIBUTES;
- }
-
- // FIXME AV - turn on when ajcMightHaveAspect
- // if (hasAtAspectAnnotation && type.isInterface()) {
- // msgHandler.handleMessage(
- // new Message(
- // "Found @Aspect on an interface type '" + type.getName() + "'",
- // IMessage.WARNING,
- // null,
- // type.getSourceLocation()
- // )
- // );
- // // bypass what we have read
- // return EMPTY_LIST;
- // }
-
- // semantic check: @Aspect must be public
- // FIXME AV - do we really want to enforce that?
- // if (hasAtAspectAnnotation && !javaClass.isPublic()) {
- // msgHandler.handleMessage(
- // new Message(
- // "Found @Aspect annotation on a non public class '" +
- // javaClass.getClassName() + "'",
- // IMessage.ERROR,
- // null,
- // type.getSourceLocation()
- // )
- // );
- // return EMPTY_LIST;
- // }
-
- // code style pointcuts are class attributes
- // 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 = null;
- boolean processedPointcut = false;
- Attribute[] mattributes = method.getAttributes();
- for (int j = 0; j < mattributes.length; j++) {
- Attribute mattribute = mattributes[j];
- if (acceptAttribute(mattribute)) {
- // TODO speed all this nonsense up rather than looking
- // through all the annotations every time
- // same for fields
- mstruct = new AjAttributeMethodStruct(method, null, type, context, msgHandler);
- processedPointcut = handlePointcutAnnotation((RuntimeAnnos) mattribute, mstruct);
- if (!processedPointcut) {
- processedPointcut = handleDeclareMixinAnnotation((RuntimeAnnos) mattribute, mstruct);
- }
- // there can only be one RuntimeVisible bytecode attribute
- break;
- }
- }
- if (processedPointcut) {
- struct.ajAttributes.addAll(mstruct.ajAttributes);
- }
- }
-
- // code style declare error / warning / implements / parents are field
- // attributes
- 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);
- Attribute[] fattributes = field.getAttributes();
-
- for (int j = 0; j < fattributes.length; j++) {
- Attribute fattribute = fattributes[j];
- if (acceptAttribute(fattribute)) {
- RuntimeAnnos frvs = (RuntimeAnnos) fattribute;
- if (handleDeclareErrorOrWarningAnnotation(model, frvs, fstruct)
- || handleDeclareParentsAnnotation(frvs, fstruct)) {
- // semantic check - must be in an @Aspect [remove if
- // previous block bypassed in advance]
- if (!type.isAnnotationStyleAspect() && !isCodeStyleAspect) {
- msgHandler.handleMessage(new Message("Found @AspectJ annotations in a non @Aspect type '"
- + type.getName() + "'", IMessage.WARNING, null, type.getSourceLocation()));
- // go ahead
- }
- }
- // there can only be one RuntimeVisible bytecode attribute
- break;
- }
- }
- struct.ajAttributes.addAll(fstruct.ajAttributes);
- }
-
- return struct.ajAttributes;
- }
-
- /**
- * Extract method level annotations and turn them into AjAttributes.
- *
- * @param method
- * @param type
- * @param context
- * @param msgHandler
- * @return list of AjAttributes
- */
- public static List<AjAttribute> readAj5MethodAttributes(Method method, BcelMethod bMethod, ResolvedType type,
- ResolvedPointcutDefinition preResolvedPointcut, ISourceContext context, IMessageHandler msgHandler) {
- if (method.getName().startsWith(NameMangler.PREFIX)) {
- return Collections.emptyList(); // already dealt with by ajc...
- }
-
- AjAttributeMethodStruct struct = new AjAttributeMethodStruct(method, bMethod, type, context, msgHandler);
- Attribute[] attributes = method.getAttributes();
-
- // we remember if we found one @AJ annotation for minimal semantic error
- // reporting
- // the real reporting beeing done thru AJDT and the compiler mapping @AJ
- // to AjAtttribute
- // or thru APT
- //
- // Note: we could actually skip the whole thing if type is not itself an
- // @Aspect
- // but then we would not see any warning. We do bypass for pointcut but
- // not for advice since it would
- // be too silent.
- boolean hasAtAspectJAnnotation = false;
- boolean hasAtAspectJAnnotationMustReturnVoid = false;
- for (int i = 0; i < attributes.length; i++) {
- Attribute attribute = attributes[i];
- try {
- if (acceptAttribute(attribute)) {
- RuntimeAnnos rvs = (RuntimeAnnos) attribute;
- hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid
- || handleBeforeAnnotation(rvs, struct, preResolvedPointcut);
- hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid
- || handleAfterAnnotation(rvs, struct, preResolvedPointcut);
- hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid
- || handleAfterReturningAnnotation(rvs, struct, preResolvedPointcut, bMethod);
- hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid
- || handleAfterThrowingAnnotation(rvs, struct, preResolvedPointcut, bMethod);
- hasAtAspectJAnnotation = hasAtAspectJAnnotation || handleAroundAnnotation(rvs, struct, preResolvedPointcut);
- // there can only be one RuntimeVisible bytecode attribute
- break;
- }
- } catch (ReturningFormalNotDeclaredInAdviceSignatureException e) {
- msgHandler.handleMessage(new Message(WeaverMessages.format(WeaverMessages.RETURNING_FORMAL_NOT_DECLARED_IN_ADVICE,
- e.getFormalName()), IMessage.ERROR, null, bMethod.getSourceLocation()));
- } catch (ThrownFormalNotDeclaredInAdviceSignatureException e) {
- msgHandler.handleMessage(new Message(WeaverMessages.format(WeaverMessages.THROWN_FORMAL_NOT_DECLARED_IN_ADVICE,
- e.getFormalName()), IMessage.ERROR, null, bMethod.getSourceLocation()));
- }
- }
- hasAtAspectJAnnotation = hasAtAspectJAnnotation || hasAtAspectJAnnotationMustReturnVoid;
-
- // semantic check - must be in an @Aspect [remove if previous block
- // bypassed in advance]
- if (hasAtAspectJAnnotation && !type.isAspect()) { // isAnnotationStyleAspect())
- // {
- msgHandler.handleMessage(new Message("Found @AspectJ annotations in a non @Aspect type '" + type.getName() + "'",
- IMessage.WARNING, null, type.getSourceLocation()));
- // go ahead
- }
- // semantic check - advice must be public
- if (hasAtAspectJAnnotation && !struct.method.isPublic()) {
- msgHandler.handleMessage(new Message("Found @AspectJ annotation on a non public advice '"
- + methodToString(struct.method) + "'", IMessage.ERROR, null, type.getSourceLocation()));
- // go ahead
- }
-
- // semantic check - advice must not be static
- if (hasAtAspectJAnnotation && struct.method.isStatic()) {
- msgHandler.handleMessage(MessageUtil.error("Advice cannot be declared static '" + methodToString(struct.method) + "'",
- type.getSourceLocation()));
- // new Message(
- // "Advice cannot be declared static '" +
- // methodToString(struct.method) + "'",
- // IMessage.ERROR,
- // null,
- // type.getSourceLocation()
- // )
- // );
- // go ahead
- }
-
- // semantic check for non around advice must return void
- if (hasAtAspectJAnnotationMustReturnVoid && !Type.VOID.equals(struct.method.getReturnType())) {
- msgHandler.handleMessage(new Message("Found @AspectJ annotation on a non around advice not returning void '"
- + methodToString(struct.method) + "'", IMessage.ERROR, null, type.getSourceLocation()));
- // go ahead
- }
-
- return struct.ajAttributes;
- }
-
- /**
- * Extract field level annotations and turn them into AjAttributes.
- *
- * @param field
- * @param type
- * @param context
- * @param msgHandler
- * @return list of AjAttributes, always empty for now
- */
- public static List<AjAttribute> readAj5FieldAttributes(Field field, BcelField bField, ResolvedType type,
- ISourceContext context, IMessageHandler msgHandler) {
- // Note: field annotation are for ITD and DEOW - processed at class
- // level directly
- return Collections.emptyList();
- }
-
- /**
- * Read @Aspect
- *
- * @param runtimeAnnotations
- * @param struct
- * @return true if found
- */
- private static boolean handleAspectAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeStruct struct) {
- AnnotationGen aspect = getAnnotation(runtimeAnnotations, AjcMemberMaker.ASPECT_ANNOTATION);
- if (aspect != null) {
- // semantic check for inheritance (only one level up)
- boolean extendsAspect = false;
- if (!"java.lang.Object".equals(struct.enclosingType.getSuperclass().getName())) {
- if (!struct.enclosingType.getSuperclass().isAbstract() && struct.enclosingType.getSuperclass().isAspect()) {
- reportError("cannot extend a concrete aspect", struct);
- return false;
- }
- extendsAspect = struct.enclosingType.getSuperclass().isAspect();
- }
-
- NameValuePair aspectPerClause = getAnnotationElement(aspect, VALUE);
- final PerClause perClause;
- if (aspectPerClause == null) {
- // empty value means singleton unless inherited
- if (!extendsAspect) {
- perClause = new PerSingleton();
- } else {
- perClause = new PerFromSuper(struct.enclosingType.getSuperclass().getPerClause().getKind());
- }
- } else {
- String perX = aspectPerClause.getValue().stringifyValue();
- if (perX == null || perX.length() <= 0) {
- perClause = new PerSingleton();
- } else {
- perClause = parsePerClausePointcut(perX, struct);
- }
- }
- if (perClause == null) {
- // could not parse it, ignore the aspect
- return false;
- } else {
- perClause.setLocation(struct.context, -1, -1);// struct.context.getOffset(),
- // struct.context.getOffset()+1);//FIXME
- // AVASM
- // Not setting version here
- // struct.ajAttributes.add(new AjAttribute.WeaverVersionInfo());
- AjAttribute.Aspect aspectAttribute = new AjAttribute.Aspect(perClause);
- struct.ajAttributes.add(aspectAttribute);
- FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
- final IScope binding;
- binding = new BindingScope(struct.enclosingType, struct.context, bindings);
-
- // // we can't resolve here since the perclause typically refers
- // to pointcuts
- // // defined in the aspect that we haven't told the
- // BcelObjectType about yet.
- //
- // perClause.resolve(binding);
-
- // so we prepare to do it later...
- aspectAttribute.setResolutionScope(binding);
- return true;
- }
- }
- return false;
- }
-
- /**
- * Read a perClause, returns null on failure and issue messages
- *
- * @param perClauseString like "pertarget(.....)"
- * @param struct for which we are parsing the per clause
- * @return a PerClause instance
- */
- private static PerClause parsePerClausePointcut(String perClauseString, AjAttributeStruct struct) {
- final String pointcutString;
- Pointcut pointcut = null;
- TypePattern typePattern = null;
- final PerClause perClause;
- if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERCFLOW.getName())) {
- pointcutString = PerClause.KindAnnotationPrefix.PERCFLOW.extractPointcut(perClauseString);
- pointcut = parsePointcut(pointcutString, struct, false);
- perClause = new PerCflow(pointcut, false);
- } else if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERCFLOWBELOW.getName())) {
- pointcutString = PerClause.KindAnnotationPrefix.PERCFLOWBELOW.extractPointcut(perClauseString);
- pointcut = parsePointcut(pointcutString, struct, false);
- perClause = new PerCflow(pointcut, true);
- } else if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERTARGET.getName())) {
- pointcutString = PerClause.KindAnnotationPrefix.PERTARGET.extractPointcut(perClauseString);
- pointcut = parsePointcut(pointcutString, struct, false);
- perClause = new PerObject(pointcut, false);
- } else if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERTHIS.getName())) {
- pointcutString = PerClause.KindAnnotationPrefix.PERTHIS.extractPointcut(perClauseString);
- pointcut = parsePointcut(pointcutString, struct, false);
- perClause = new PerObject(pointcut, true);
- } else if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERTYPEWITHIN.getName())) {
- pointcutString = PerClause.KindAnnotationPrefix.PERTYPEWITHIN.extractPointcut(perClauseString);
- typePattern = parseTypePattern(pointcutString, struct);
- perClause = new PerTypeWithin(typePattern);
- } else if (perClauseString.equalsIgnoreCase(PerClause.SINGLETON.getName() + "()")) {
- perClause = new PerSingleton();
- } else {
- // could not parse the @AJ perclause - fallback to singleton and
- // issue an error
- reportError("@Aspect per clause cannot be read '" + perClauseString + "'", struct);
- return null;
- }
-
- if (!PerClause.SINGLETON.equals(perClause.getKind()) && !PerClause.PERTYPEWITHIN.equals(perClause.getKind())
- && pointcut == null) {
- // we could not parse the pointcut
- return null;
- }
- if (PerClause.PERTYPEWITHIN.equals(perClause.getKind()) && typePattern == null) {
- // we could not parse the type pattern
- return null;
- }
- return perClause;
- }
-
- /**
- * Read @DeclarePrecedence
- *
- * @param runtimeAnnotations
- * @param struct
- * @return true if found
- */
- private static boolean handlePrecedenceAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeStruct struct) {
- AnnotationGen aspect = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREPRECEDENCE_ANNOTATION);
- if (aspect != null) {
- NameValuePair precedence = getAnnotationElement(aspect, VALUE);
- if (precedence != null) {
- String precedencePattern = precedence.getValue().stringifyValue();
- PatternParser parser = new PatternParser(precedencePattern);
- DeclarePrecedence ajPrecedence = parser.parseDominates();
- struct.ajAttributes.add(new AjAttribute.DeclareAttribute(ajPrecedence));
- return true;
- }
- }
- return false;
- }
-
- // /**
- // * Read @DeclareImplements
- // *
- // * @param runtimeAnnotations
- // * @param struct
- // * @return true if found
- // */
- // private static boolean
- // handleDeclareImplementsAnnotation(RuntimeAnnotations runtimeAnnotations,
- // AjAttributeFieldStruct
- // struct) {//, ResolvedPointcutDefinition preResolvedPointcut) {
- // Annotation deci = getAnnotation(runtimeAnnotations,
- // AjcMemberMaker.DECLAREIMPLEMENTS_ANNOTATION);
- // if (deci != null) {
- // ElementNameValuePairGen deciPatternNVP = getAnnotationElement(deci,
- // VALUE);
- // String deciPattern = deciPatternNVP.getValue().stringifyValue();
- // if (deciPattern != null) {
- // TypePattern typePattern = parseTypePattern(deciPattern, struct);
- // ResolvedType fieldType =
- // UnresolvedType.forSignature(struct.field.getSignature()).resolve(struct.enclosingType.getWorld());
- // if (fieldType.isPrimitiveType()) {
- // return false;
- // } else if (fieldType.isInterface()) {
- // TypePattern parent = new
- // ExactTypePattern(UnresolvedType.forSignature(struct.field.getSignature()),
- // false, false);
- // parent.resolve(struct.enclosingType.getWorld());
- // List parents = new ArrayList(1);
- // parents.add(parent);
- // //TODO kick ISourceLocation sl = struct.bField.getSourceLocation(); ??
- // struct.ajAttributes.add(
- // new AjAttribute.DeclareAttribute(
- // new DeclareParents(
- // typePattern,
- // parents,
- // false
- // )
- // )
- // );
- // return true;
- // } else {
- // reportError("@DeclareImplements: can only be used on field whose type is an interface",
- // struct);
- // return false;
- // }
- // }
- // }
- // return false;
- // }
-
- /**
- * Read @DeclareParents
- *
- * @param runtimeAnnotations
- * @param struct
- * @return true if found
- */
- private static boolean handleDeclareParentsAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeFieldStruct struct) {// ,
- // ResolvedPointcutDefinition
- // preResolvedPointcut)
- // {
- AnnotationGen decp = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREPARENTS_ANNOTATION);
- if (decp != null) {
- NameValuePair decpPatternNVP = getAnnotationElement(decp, VALUE);
- String decpPattern = decpPatternNVP.getValue().stringifyValue();
- if (decpPattern != null) {
- TypePattern typePattern = parseTypePattern(decpPattern, struct);
- ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve(
- struct.enclosingType.getWorld());
- if (fieldType.isParameterizedOrRawType()) {
- fieldType = fieldType.getGenericType();
- }
- if (fieldType.isInterface()) {
- TypePattern parent = parseTypePattern(fieldType.getName(), struct);
- FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
- IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);
- // first add the declare implements like
- List<TypePattern> parents = new ArrayList<TypePattern>(1);
- parents.add(parent);
- DeclareParents dp = new DeclareParents(typePattern, parents, false);
- dp.resolve(binding); // resolves the parent and child parts of the decp
-
- // resolve this so that we can use it for the
- // MethodDelegateMungers below.
- // eg. '@Coloured *' will change from a WildTypePattern to
- // an 'AnyWithAnnotationTypePattern' after this resolution
- typePattern = dp.getChild(); // this retrieves the resolved version
- // TODO kick ISourceLocation sl =
- // struct.bField.getSourceLocation(); ??
- // dp.setLocation(dp.getDeclaringType().getSourceContext(),
- // dp.getDeclaringType().getSourceLocation().getOffset(),
- // dp.getDeclaringType().getSourceLocation().getOffset());
- dp.setLocation(struct.context, -1, -1); // not ideal...
- struct.ajAttributes.add(new AjAttribute.DeclareAttribute(dp));
-
- // do we have a defaultImpl=xxx.class (ie implementation)
- String defaultImplClassName = null;
- NameValuePair defaultImplNVP = getAnnotationElement(decp, "defaultImpl");
- if (defaultImplNVP != null) {
- ClassElementValue defaultImpl = (ClassElementValue) defaultImplNVP.getValue();
- defaultImplClassName = UnresolvedType.forSignature(defaultImpl.getClassString()).getName();
- if (defaultImplClassName.equals("org.aspectj.lang.annotation.DeclareParents")) {
- defaultImplClassName = null;
- } else {
- // check public no arg ctor
- ResolvedType impl = struct.enclosingType.getWorld().resolve(defaultImplClassName, false);
- ResolvedMember[] mm = impl.getDeclaredMethods();
- int implModifiers = impl.getModifiers();
- boolean defaultVisibilityImpl = !(Modifier.isPrivate(implModifiers)
- || Modifier.isProtected(implModifiers) || Modifier.isPublic(implModifiers));
- boolean hasNoCtorOrANoArgOne = true;
- ResolvedMember foundOneOfIncorrectVisibility = null;
- for (int i = 0; i < mm.length; i++) {
- ResolvedMember resolvedMember = mm[i];
- if (resolvedMember.getName().equals("<init>")) {
- hasNoCtorOrANoArgOne = false;
-
- if (resolvedMember.getParameterTypes().length == 0) {
- if (defaultVisibilityImpl) { // default visibility implementation
- if (resolvedMember.isPublic() || resolvedMember.isDefault()) {
- hasNoCtorOrANoArgOne = true;
- } else {
- foundOneOfIncorrectVisibility = resolvedMember;
- }
- } else if (Modifier.isPublic(implModifiers)) { // public
- // implementation
- if (resolvedMember.isPublic()) {
- hasNoCtorOrANoArgOne = true;
- } else {
- foundOneOfIncorrectVisibility = resolvedMember;
- }
- }
- }
- }
- if (hasNoCtorOrANoArgOne) {
- break;
- }
- }
- if (!hasNoCtorOrANoArgOne) {
- if (foundOneOfIncorrectVisibility != null) {
- reportError(
- "@DeclareParents: defaultImpl=\""
- + defaultImplClassName
- + "\" has a no argument constructor, but it is of incorrect visibility. It must be at least as visible as the type.",
- struct);
- } else {
- reportError("@DeclareParents: defaultImpl=\"" + defaultImplClassName
- + "\" has no public no-arg constructor", struct);
- }
- }
- if (!fieldType.isAssignableFrom(impl)) {
- reportError("@DeclareParents: defaultImpl=\"" + defaultImplClassName
- + "\" does not implement the interface '" + fieldType.toString() + "'", struct);
- }
- }
-
- }
-
- // then iterate on field interface hierarchy (not object)
- boolean hasAtLeastOneMethod = false;
- Iterator<ResolvedMember> methodIterator = fieldType.getMethodsIncludingIntertypeDeclarations(false, true);
- while (methodIterator.hasNext()) {
- ResolvedMember method = methodIterator.next();
- if (method.isAbstract()) {
- // 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;
- // What we are saying here:
- // We have this method 'method' and we want to put a
- // forwarding method into a type that matches
- // typePattern that should delegate to the version
- // of the method in 'defaultImplClassName'
-
- // Now the method may be from a supertype but the
- // declaring type of the method we pass into the
- // type
- // munger is what is used to determine the type of
- // the field that hosts the delegate instance.
- // So here we create a modified method with an
- // alternative declaring type so that we lookup
- // the right field. See pr164016.
- MethodDelegateTypeMunger mdtm = new MethodDelegateTypeMunger(method, struct.enclosingType, defaultImplClassName, typePattern);
- mdtm.setFieldType(fieldType);
- mdtm.setSourceLocation(struct.enclosingType.getSourceLocation());
- struct.ajAttributes.add(new AjAttribute.TypeMunger(mdtm));
- }
- }
- // successful so far, we thus need a bcel type munger to have
- // a field hosting the mixin in the target type
- if (hasAtLeastOneMethod && defaultImplClassName != null) {
- ResolvedMember fieldHost = AjcMemberMaker.itdAtDeclareParentsField(null, fieldType, struct.enclosingType);
- struct.ajAttributes.add(new AjAttribute.TypeMunger(new MethodDelegateTypeMunger.FieldHostTypeMunger(
- fieldHost, struct.enclosingType, typePattern)));
- }
- return true;
- } else {
- reportError("@DeclareParents: can only be used on a field whose type is an interface", struct);
- return false;
- }
- }
- }
- return false;
- }
-
- /**
- * Return a nicely formatted method string, for example: int X.foo(java.lang.String)
- */
- public static String getMethodForMessage(AjAttributeMethodStruct methodstructure) {
- StringBuffer sb = new StringBuffer();
- sb.append("Method '");
- sb.append(methodstructure.method.getReturnType().toString());
- sb.append(" ").append(methodstructure.enclosingType).append(".").append(methodstructure.method.getName());
- sb.append("(");
- Type[] args = methodstructure.method.getArgumentTypes();
- if (args != null) {
- for (int t = 0; t < args.length; t++) {
- if (t > 0) {
- sb.append(",");
- }
- sb.append(args[t].toString());
- }
- }
- sb.append(")'");
- return sb.toString();
- }
-
- /**
- * Process any @DeclareMixin annotation.
- *
- * Example Declaration <br>
- *
- * @DeclareMixin("Foo+") public I createImpl(Object o) { return new Impl(o); }
- *
- * <br>
- * @param runtimeAnnotations
- * @param struct
- * @return true if found
- */
- private static boolean handleDeclareMixinAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct) {
- AnnotationGen declareMixinAnnotation = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREMIXIN_ANNOTATION);
- if (declareMixinAnnotation == null) {
- // No annotation found
- return false;
- }
- Method annotatedMethod = struct.method;
- World world = struct.enclosingType.getWorld();
- NameValuePair declareMixinPatternNameValuePair = getAnnotationElement(declareMixinAnnotation, VALUE);
-
- // declareMixinPattern could be of the form "Bar*" or "A || B" or "Foo+"
- String declareMixinPattern = declareMixinPatternNameValuePair.getValue().stringifyValue();
- TypePattern targetTypePattern = parseTypePattern(declareMixinPattern, struct);
-
- // Return value of the annotated method is the interface or class that the mixin delegate should have
- ResolvedType methodReturnType = UnresolvedType.forSignature(annotatedMethod.getReturnType().getSignature()).resolve(world);
- if (methodReturnType.isParameterizedOrRawType()) {
- methodReturnType = methodReturnType.getGenericType();
- }
- if (methodReturnType.isPrimitiveType()) {
- reportError(getMethodForMessage(struct) + ": factory methods for a mixin cannot return void or a primitive type",
- struct);
- return false;
- }
-
- if (annotatedMethod.getArgumentTypes().length > 1) {
- reportError(getMethodForMessage(struct) + ": factory methods for a mixin can take a maximum of one parameter", struct);
- return false;
- }
-
- // The set of interfaces to be mixed in is either:
- // supplied as a list in the 'Class[] interfaces' value in the annotation value
- // supplied as just the interface return value of the annotated method
- // supplied as just the class return value of the annotated method
- NameValuePair interfaceListSpecified = getAnnotationElement(declareMixinAnnotation, "interfaces");
-
- List<TypePattern> newParents = new ArrayList<TypePattern>(1);
- List<ResolvedType> newInterfaceTypes = new ArrayList<ResolvedType>(1);
- if (interfaceListSpecified != null) {
- ArrayElementValue arrayOfInterfaceTypes = (ArrayElementValue) interfaceListSpecified.getValue();
- int numberOfTypes = arrayOfInterfaceTypes.getElementValuesArraySize();
- ElementValue[] theTypes = arrayOfInterfaceTypes.getElementValuesArray();
- for (int i = 0; i < numberOfTypes; i++) {
- ClassElementValue interfaceType = (ClassElementValue) theTypes[i];
- // Check: needs to be resolvable
- // TODO crappy replace required
- ResolvedType ajInterfaceType = UnresolvedType.forSignature(interfaceType.getClassString().replace("/", "."))
- .resolve(world);
- if (ajInterfaceType.isMissing() || !ajInterfaceType.isInterface()) {
- reportError(
- "Types listed in the 'interfaces' DeclareMixin annotation value must be valid interfaces. This is invalid: "
- + ajInterfaceType.getName(), struct); // TODO better error location, use the method position
- return false;
- }
- if (!ajInterfaceType.isAssignableFrom(methodReturnType)) {
- reportError(getMethodForMessage(struct) + ": factory method does not return something that implements '"
- + ajInterfaceType.getName() + "'", struct);
- return false;
- }
- newInterfaceTypes.add(ajInterfaceType);
- // Checking that it is a superinterface of the methods return value is done at weave time
- TypePattern newParent = parseTypePattern(ajInterfaceType.getName(), struct);
- newParents.add(newParent);
- }
- } else {
- if (methodReturnType.isClass()) {
- reportError(
- getMethodForMessage(struct)
- + ": factory methods for a mixin must either return an interface type or specify interfaces in the annotation and return a class",
- struct);
- return false;
- }
- // Use the method return type: this might be a class or an interface
- TypePattern newParent = parseTypePattern(methodReturnType.getName(), struct);
- newInterfaceTypes.add(methodReturnType);
- newParents.add(newParent);
- }
- if (newParents.size() == 0) {
- // Warning: did they foolishly put @DeclareMixin(value="Bar+",interfaces={})
- // TODO output warning
- return false;
- }
-
- // Create the declare parents that will add the interfaces to matching targets
- FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
- IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);
- // how do we mark this as a decp due to decmixin?
- DeclareParents dp = new DeclareParentsMixin(targetTypePattern, newParents);
- dp.resolve(binding);
- targetTypePattern = dp.getChild();
-
- dp.setLocation(struct.context, -1, -1); // not ideal...
- struct.ajAttributes.add(new AjAttribute.DeclareAttribute(dp));
-
- // The factory method for building the implementation is the
- // one attached to the annotation:
- // Method implementationFactory = struct.method;
-
- boolean hasAtLeastOneMethod = false;
-
- for (Iterator<ResolvedType> iterator = newInterfaceTypes.iterator(); iterator.hasNext();) {
- ResolvedType typeForDelegation = iterator.next();
- // TODO check for overlapping interfaces. Eg. A implements I, I extends J - if they specify interfaces={I,J} we dont
- // want to do any methods twice
- ResolvedMember[] methods = typeForDelegation.getMethodsWithoutIterator(true, false, false).toArray(
- new ResolvedMember[0]);
- for (int i = 0; i < methods.length; i++) {
- ResolvedMember method = methods[i];
- if (method.isAbstract()) {
- hasAtLeastOneMethod = true;
- if (method.hasBackingGenericMember()) {
- method = method.getBackingGenericMember();
- }
- MethodDelegateTypeMunger mdtm = new MethodDelegateTypeMunger(method, struct.enclosingType, "",
- targetTypePattern, struct.method.getName(), struct.method.getSignature());
- mdtm.setFieldType(methodReturnType);
- mdtm.setSourceLocation(struct.enclosingType.getSourceLocation());
- struct.ajAttributes.add(new AjAttribute.TypeMunger(mdtm));
- }
- }
- }
- // if any method delegate was created then a field to hold the delegate instance must also be added
- if (hasAtLeastOneMethod) {
- ResolvedMember fieldHost = AjcMemberMaker.itdAtDeclareParentsField(null, methodReturnType, struct.enclosingType);
- struct.ajAttributes.add(new AjAttribute.TypeMunger(new MethodDelegateTypeMunger.FieldHostTypeMunger(fieldHost,
- struct.enclosingType, targetTypePattern)));
- }
- return true;
- }
-
- /**
- * Read @Before
- *
- * @param runtimeAnnotations
- * @param struct
- * @return true if found
- */
- private static boolean handleBeforeAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct,
- ResolvedPointcutDefinition preResolvedPointcut) {
- AnnotationGen before = getAnnotation(runtimeAnnotations, AjcMemberMaker.BEFORE_ANNOTATION);
- if (before != null) {
- NameValuePair 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);
- } catch (UnreadableDebugInfoException unreadableDebugInfoException) {
- return false;
- }
- IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);
-
- // joinpoint, staticJoinpoint binding
- int extraArgument = extractExtraArgument(struct.method);
-
- Pointcut pc = null;
- if (preResolvedPointcut != null) {
- pc = preResolvedPointcut.getPointcut();
- // pc.resolve(binding);
- } else {
- pc = parsePointcut(beforeAdvice.getValue().stringifyValue(), struct, false);
- if (pc == null) {
- return false;// parse error
- }
- pc = pc.resolve(binding);
- }
- setIgnoreUnboundBindingNames(pc, bindings);
-
- ISourceLocation sl = struct.context.makeSourceLocation(struct.bMethod.getDeclarationLineNumber(),
- struct.bMethod.getDeclarationOffset());
- struct.ajAttributes.add(new AjAttribute.AdviceAttribute(AdviceKind.Before, pc, extraArgument, sl.getOffset(), sl
- .getOffset() + 1,// FIXME AVASM
- struct.context));
- return true;
- }
- }
- return false;
- }
-
- /**
- * Read @After
- *
- * @param runtimeAnnotations
- * @param struct
- * @return true if found
- */
- private static boolean handleAfterAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct,
- ResolvedPointcutDefinition preResolvedPointcut) {
- AnnotationGen after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTER_ANNOTATION);
- if (after != null) {
- NameValuePair afterAdvice = getAnnotationElement(after, VALUE);
- 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) {
- return false;
- }
- IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);
-
- // joinpoint, staticJoinpoint binding
- int extraArgument = extractExtraArgument(struct.method);
-
- Pointcut pc = null;
- if (preResolvedPointcut != null) {
- pc = preResolvedPointcut.getPointcut();
- } else {
- pc = parsePointcut(afterAdvice.getValue().stringifyValue(), struct, false);
- if (pc == null) {
- return false;// parse error
- }
- pc.resolve(binding);
- }
- setIgnoreUnboundBindingNames(pc, bindings);
-
- ISourceLocation sl = struct.context.makeSourceLocation(struct.bMethod.getDeclarationLineNumber(),
- struct.bMethod.getDeclarationOffset());
- struct.ajAttributes.add(new AjAttribute.AdviceAttribute(AdviceKind.After, pc, extraArgument, sl.getOffset(), sl
- .getOffset() + 1,// FIXME AVASM
- struct.context));
- return true;
- }
- }
- return false;
- }
-
- /**
- * Read @AfterReturning
- *
- * @param runtimeAnnotations
- * @param struct
- * @return true if found
- */
- private static boolean handleAfterReturningAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct,
- ResolvedPointcutDefinition preResolvedPointcut, BcelMethod owningMethod)
- throws ReturningFormalNotDeclaredInAdviceSignatureException {
- AnnotationGen after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTERRETURNING_ANNOTATION);
- if (after != null) {
- NameValuePair annValue = getAnnotationElement(after, VALUE);
- NameValuePair annPointcut = getAnnotationElement(after, POINTCUT);
- NameValuePair annReturned = getAnnotationElement(after, RETURNING);
-
- // extract the pointcut and returned type/binding - do some checks
- String pointcut = null;
- String returned = null;
- if ((annValue != null && annPointcut != null) || (annValue == null && annPointcut == null)) {
- reportError("@AfterReturning: either 'value' or 'poincut' must be provided, not both", struct);
- return false;
- }
- if (annValue != null) {
- pointcut = annValue.getValue().stringifyValue();
- } else {
- pointcut = annPointcut.getValue().stringifyValue();
- }
- if (isNullOrEmpty(pointcut)) {
- reportError("@AfterReturning: either 'value' or 'poincut' must be provided, not both", struct);
- return false;
- }
- if (annReturned != null) {
- returned = annReturned.getValue().stringifyValue();
- if (isNullOrEmpty(returned)) {
- returned = null;
- } else {
- // check that thrownFormal exists as the last parameter in
- // the advice
- String[] pNames = owningMethod.getParameterNames();
- if (pNames == null || pNames.length == 0 || !Arrays.asList(pNames).contains(returned)) {
- throw new ReturningFormalNotDeclaredInAdviceSignatureException(returned);
- }
- }
- }
- 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];
- try {
- bindings = (returned == null ? extractBindings(struct) : extractBindings(struct, returned));
- } catch (UnreadableDebugInfoException unreadableDebugInfoException) {
- return false;
- }
- IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);
-
- // joinpoint, staticJoinpoint binding
- int extraArgument = extractExtraArgument(struct.method);
-
- // return binding
- if (returned != null) {
- extraArgument |= Advice.ExtraArgument;
- }
-
- Pointcut pc = null;
- if (preResolvedPointcut != null) {
- pc = preResolvedPointcut.getPointcut();
- } else {
- pc = parsePointcut(pointcut, struct, false);
- if (pc == null) {
- return false;// parse error
- }
- pc.resolve(binding);
- }
- setIgnoreUnboundBindingNames(pc, bindings);
-
- ISourceLocation sl = struct.context.makeSourceLocation(struct.bMethod.getDeclarationLineNumber(),
- struct.bMethod.getDeclarationOffset());
- struct.ajAttributes.add(new AjAttribute.AdviceAttribute(AdviceKind.AfterReturning, pc, extraArgument, sl.getOffset(),
- sl.getOffset() + 1,// FIXME AVASM
- struct.context));
- return true;
- }
- return false;
- }
-
- /**
- * Read @AfterThrowing
- *
- * @param runtimeAnnotations
- * @param struct
- * @return true if found
- */
- private static boolean handleAfterThrowingAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct,
- ResolvedPointcutDefinition preResolvedPointcut, BcelMethod owningMethod)
- throws ThrownFormalNotDeclaredInAdviceSignatureException {
- AnnotationGen after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTERTHROWING_ANNOTATION);
- if (after != null) {
- NameValuePair annValue = getAnnotationElement(after, VALUE);
- NameValuePair annPointcut = getAnnotationElement(after, POINTCUT);
- NameValuePair annThrown = getAnnotationElement(after, THROWING);
-
- // extract the pointcut and throwned type/binding - do some checks
- String pointcut = null;
- String thrownFormal = null;
- if ((annValue != null && annPointcut != null) || (annValue == null && annPointcut == null)) {
- reportError("@AfterThrowing: either 'value' or 'poincut' must be provided, not both", struct);
- return false;
- }
- if (annValue != null) {
- pointcut = annValue.getValue().stringifyValue();
- } else {
- pointcut = annPointcut.getValue().stringifyValue();
- }
- if (isNullOrEmpty(pointcut)) {
- reportError("@AfterThrowing: either 'value' or 'poincut' must be provided, not both", struct);
- return false;
- }
- if (annThrown != null) {
- thrownFormal = annThrown.getValue().stringifyValue();
- if (isNullOrEmpty(thrownFormal)) {
- thrownFormal = null;
- } else {
- // check that thrownFormal exists as the last parameter in
- // the advice
- String[] pNames = owningMethod.getParameterNames();
- if (pNames == null || pNames.length == 0 || !Arrays.asList(pNames).contains(thrownFormal)) {
- throw new ThrownFormalNotDeclaredInAdviceSignatureException(thrownFormal);
- }
- }
- }
- 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];
- try {
- bindings = (thrownFormal == null ? extractBindings(struct) : extractBindings(struct, thrownFormal));
- } catch (UnreadableDebugInfoException unreadableDebugInfoException) {
- return false;
- }
- IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);
-
- // joinpoint, staticJoinpoint binding
- int extraArgument = extractExtraArgument(struct.method);
-
- // return binding
- if (thrownFormal != null) {
- extraArgument |= Advice.ExtraArgument;
- }
-
- Pointcut pc = null;
- if (preResolvedPointcut != null) {
- pc = preResolvedPointcut.getPointcut();
- } else {
- pc = parsePointcut(pointcut, struct, false);
- if (pc == null) {
- return false;// parse error
- }
- pc.resolve(binding);
- }
- setIgnoreUnboundBindingNames(pc, bindings);
-
- ISourceLocation sl = struct.context.makeSourceLocation(struct.bMethod.getDeclarationLineNumber(),
- struct.bMethod.getDeclarationOffset());
- struct.ajAttributes.add(new AjAttribute.AdviceAttribute(AdviceKind.AfterThrowing, pc, extraArgument, sl.getOffset(), sl
- .getOffset() + 1, struct.context));
- return true;
- }
- return false;
- }
-
- /**
- * Read @Around
- *
- * @param runtimeAnnotations
- * @param struct
- * @return true if found
- */
- private static boolean handleAroundAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct,
- ResolvedPointcutDefinition preResolvedPointcut) {
- AnnotationGen around = getAnnotation(runtimeAnnotations, AjcMemberMaker.AROUND_ANNOTATION);
- if (around != null) {
- NameValuePair aroundAdvice = getAnnotationElement(around, VALUE);
- if (aroundAdvice != null) {
- // 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);
- } catch (UnreadableDebugInfoException unreadableDebugInfoException) {
- return false;
- }
- IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);
-
- // joinpoint, staticJoinpoint binding
- int extraArgument = extractExtraArgument(struct.method);
-
- Pointcut pc = null;
- if (preResolvedPointcut != null) {
- pc = preResolvedPointcut.getPointcut();
- } else {
- pc = parsePointcut(aroundAdvice.getValue().stringifyValue(), struct, false);
- if (pc == null) {
- return false;// parse error
- }
- pc.resolve(binding);
- }
- setIgnoreUnboundBindingNames(pc, bindings);
-
- ISourceLocation sl = struct.context.makeSourceLocation(struct.bMethod.getDeclarationLineNumber(),
- struct.bMethod.getDeclarationOffset());
- struct.ajAttributes.add(new AjAttribute.AdviceAttribute(AdviceKind.Around, pc, extraArgument, sl.getOffset(), sl
- .getOffset() + 1,// FIXME AVASM
- struct.context));
- return true;
- }
- }
- return false;
- }
-
- /**
- * Read @Pointcut and handle the resolving in a lazy way to deal with pointcut references
- *
- * @param runtimeAnnotations
- * @param struct
- * @return true if a pointcut was handled
- */
- private static boolean handlePointcutAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct) {
- AnnotationGen pointcut = getAnnotation(runtimeAnnotations, AjcMemberMaker.POINTCUT_ANNOTATION);
- if (pointcut == null) {
- return false;
- }
- NameValuePair 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
- }
-
- // 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));
- }
- } 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());
- }
-
- 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 false;// stop
- }
- } else {
- if (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;
- }
-
- /**
- * Read @DeclareError, @DeclareWarning
- *
- * @param runtimeAnnotations
- * @param struct
- * @return true if found
- */
- private static boolean handleDeclareErrorOrWarningAnnotation(AsmManager model, RuntimeAnnos runtimeAnnotations,
- AjAttributeFieldStruct struct) {
- AnnotationGen error = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREERROR_ANNOTATION);
- boolean hasError = false;
- if (error != null) {
- NameValuePair declareError = getAnnotationElement(error, VALUE);
- if (declareError != null) {
- if (!STRING_DESC.equals(struct.field.getSignature()) || struct.field.getConstantValue() == null) {
- reportError("@DeclareError used on a non String constant field", struct);
- return false;
- }
- Pointcut pc = parsePointcut(declareError.getValue().stringifyValue(), struct, false);
- if (pc == null) {
- hasError = false;// cannot parse pointcut
- } else {
- DeclareErrorOrWarning deow = new DeclareErrorOrWarning(true, pc, struct.field.getConstantValue().toString());
- setDeclareErrorOrWarningLocation(model, deow, struct);
- struct.ajAttributes.add(new AjAttribute.DeclareAttribute(deow));
- hasError = true;
- }
- }
- }
- AnnotationGen warning = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREWARNING_ANNOTATION);
- boolean hasWarning = false;
- if (warning != null) {
- NameValuePair declareWarning = getAnnotationElement(warning, VALUE);
- if (declareWarning != null) {
- if (!STRING_DESC.equals(struct.field.getSignature()) || struct.field.getConstantValue() == null) {
- reportError("@DeclareWarning used on a non String constant field", struct);
- return false;
- }
- Pointcut pc = parsePointcut(declareWarning.getValue().stringifyValue(), struct, false);
- if (pc == null) {
- hasWarning = false;// cannot parse pointcut
- } else {
- DeclareErrorOrWarning deow = new DeclareErrorOrWarning(false, pc, struct.field.getConstantValue().toString());
- setDeclareErrorOrWarningLocation(model, deow, struct);
- struct.ajAttributes.add(new AjAttribute.DeclareAttribute(deow));
- return hasWarning = true;
- }
- }
- }
- return hasError || hasWarning;
- }
-
- /**
- * Sets the location for the declare error / warning using the corresponding IProgramElement in the structure model. This will
- * only fix bug 120356 if compiled with -emacssym, however, it does mean that the cross references view in AJDT will show the
- * correct information.
- *
- * Other possibilities for fix: 1. using the information in ajcDeclareSoft (if this is set correctly) which will fix the problem
- * if compiled with ajc but not if compiled with javac. 2. creating an AjAttribute called FieldDeclarationLineNumberAttribute
- * (much like MethodDeclarationLineNumberAttribute) which we can ask for the offset. This will again only fix bug 120356 when
- * compiled with ajc.
- *
- * @param deow
- * @param struct
- */
- private static void setDeclareErrorOrWarningLocation(AsmManager model, DeclareErrorOrWarning deow, AjAttributeFieldStruct struct) {
- IHierarchy top = (model == null ? null : model.getHierarchy());
- if (top != null && top.getRoot() != null) {
- IProgramElement ipe = top.findElementForLabel(top.getRoot(), IProgramElement.Kind.FIELD, struct.field.getName());
- if (ipe != null && ipe.getSourceLocation() != null) {
- ISourceLocation sourceLocation = ipe.getSourceLocation();
- int start = sourceLocation.getOffset();
- int end = start + struct.field.getName().length();
- deow.setLocation(struct.context, start, end);
- return;
- }
- }
- deow.setLocation(struct.context, -1, -1);
- }
-
- /**
- * Returns a readable representation of a method. Method.toString() is not suitable.
- *
- * @param method
- * @return a readable representation of a method
- */
- private static String methodToString(Method method) {
- StringBuffer sb = new StringBuffer();
- sb.append(method.getName());
- sb.append(method.getSignature());
- return sb.toString();
- }
-
- /**
- * Build the bindings for a given method (pointcut / advice)
- *
- * @param struct
- * @return null if no debug info is available
- */
- private static FormalBinding[] extractBindings(AjAttributeMethodStruct struct) throws UnreadableDebugInfoException {
- Method method = struct.method;
- String[] argumentNames = struct.getArgumentNames();
-
- // assert debug info was here
- if (argumentNames.length != method.getArgumentTypes().length) {
- reportError(
- "Cannot read debug info for @Aspect to handle formal binding in pointcuts (please compile with 'javac -g' or '<javac debug='true'.../>' in Ant)",
- struct);
- throw new UnreadableDebugInfoException();
- }
-
- List<FormalBinding> bindings = new ArrayList<FormalBinding>();
- for (int i = 0; i < argumentNames.length; i++) {
- String argumentName = argumentNames[i];
- UnresolvedType argumentType = UnresolvedType.forSignature(method.getArgumentTypes()[i].getSignature());
-
- // do not bind JoinPoint / StaticJoinPoint /
- // EnclosingStaticJoinPoint
- // TODO solve me : this means that the JP/SJP/ESJP cannot appear as
- // binding
- // f.e. when applying advice on advice etc
- if ((AjcMemberMaker.TYPEX_JOINPOINT.equals(argumentType)
- || AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.equals(argumentType)
- || AjcMemberMaker.TYPEX_STATICJOINPOINT.equals(argumentType)
- || AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.equals(argumentType) || AjcMemberMaker.AROUND_CLOSURE_TYPE
- .equals(argumentType))) {
- // continue;// skip
- bindings.add(new FormalBinding.ImplicitFormalBinding(argumentType, argumentName, i));
- } else {
- bindings.add(new FormalBinding(argumentType, argumentName, i));
- }
- }
-
- return bindings.toArray(new FormalBinding[] {});
- }
-
- // FIXME alex deal with exclude index
- private static FormalBinding[] extractBindings(AjAttributeMethodStruct struct, String excludeFormal)
- throws UnreadableDebugInfoException {
- FormalBinding[] bindings = extractBindings(struct);
- // int excludeIndex = -1;
- for (int i = 0; i < bindings.length; i++) {
- FormalBinding binding = bindings[i];
- if (binding.getName().equals(excludeFormal)) {
- // excludeIndex = i;
- bindings[i] = new FormalBinding.ImplicitFormalBinding(binding.getType(), binding.getName(), binding.getIndex());
- break;
- }
- }
- return bindings;
- //
- // if (excludeIndex >= 0) {
- // FormalBinding[] bindingsFiltered = new
- // FormalBinding[bindings.length-1];
- // int k = 0;
- // for (int i = 0; i < bindings.length; i++) {
- // if (i == excludeIndex) {
- // ;
- // } else {
- // bindingsFiltered[k] = new FormalBinding(bindings[i].getType(),
- // bindings[i].getName(), k);
- // k++;
- // }
- // }
- // return bindingsFiltered;
- // } else {
- // return bindings;
- // }
- }
-
- /**
- * Compute the flag for the xxxJoinPoint extra argument
- *
- * @param method
- * @return extra arg flag
- */
- private static int extractExtraArgument(Method method) {
- Type[] methodArgs = method.getArgumentTypes();
- String[] sigs = new String[methodArgs.length];
- for (int i = 0; i < methodArgs.length; i++) {
- sigs[i] = methodArgs[i].getSignature();
- }
- return extractExtraArgument(sigs);
- }
-
- /**
- * Compute the flag for the xxxJoinPoint extra argument
- *
- * @param argumentSignatures
- * @return extra arg flag
- */
- public static int extractExtraArgument(String[] argumentSignatures) {
- int extraArgument = 0;
- for (int i = 0; i < argumentSignatures.length; i++) {
- if (AjcMemberMaker.TYPEX_JOINPOINT.getSignature().equals(argumentSignatures[i])) {
- extraArgument |= Advice.ThisJoinPoint;
- } else if (AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(argumentSignatures[i])) {
- extraArgument |= Advice.ThisJoinPoint;
- } else if (AjcMemberMaker.TYPEX_STATICJOINPOINT.getSignature().equals(argumentSignatures[i])) {
- extraArgument |= Advice.ThisJoinPointStaticPart;
- } else if (AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(argumentSignatures[i])) {
- extraArgument |= Advice.ThisEnclosingJoinPointStaticPart;
- }
- }
- return extraArgument;
- }
-
- /**
- * Returns the runtime (RV/RIV) annotation of type annotationType or null if no such annotation
- *
- * @param rvs
- * @param annotationType
- * @return annotation
- */
- private static AnnotationGen getAnnotation(RuntimeAnnos rvs, UnresolvedType annotationType) {
- final String annotationTypeName = annotationType.getName();
- for (AnnotationGen rv : rvs.getAnnotations()) {
- if (annotationTypeName.equals(rv.getTypeName())) {
- return rv;
- }
- }
- return null;
- }
-
- /**
- * Returns the value of a given element of an annotation or null if not found Caution: Does not handles default value.
- *
- * @param annotation
- * @param elementName
- * @return annotation NVP
- */
- private static NameValuePair getAnnotationElement(AnnotationGen annotation, String elementName) {
- for (NameValuePair element : annotation.getValues()) {
- if (elementName.equals(element.getNameString())) {
- return element;
- }
- }
- return null;
- }
-
- /**
- * Return the argNames set for an annotation or null if it is not specified.
- */
- private static String getArgNamesValue(AnnotationGen anno) {
- List<NameValuePair> elements = anno.getValues();
- for (NameValuePair element : elements) {
- 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. 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
- * @param argNamesFromAnnotation
- * @param methodStruct
- * @return method argument names
- */
- private static String[] getMethodArgumentNames(Method method, String argNamesFromAnnotation,
- AjAttributeMethodStruct methodStruct) {
- if (method.getArgumentTypes().length == 0) {
- return EMPTY_STRINGS;
- }
-
- final int startAtStackIndex = method.isStatic() ? 0 : 1;
- final List<MethodArgument> arguments = new ArrayList<MethodArgument>();
- LocalVariableTable lt = method.getLocalVariableTable();
- if (lt != null) {
- LocalVariable[] lvt = lt.getLocalVariableTable();
- for (int j = 0; j < lvt.length; j++) {
- LocalVariable localVariable = lvt[j];
- if (localVariable != null) { // pr348488
- if (localVariable.getStartPC() == 0) {
- if (localVariable.getIndex() >= startAtStackIndex) {
- arguments.add(new MethodArgument(localVariable.getName(), localVariable.getIndex()));
- }
- }
- } else {
- String typename = (methodStruct.enclosingType != null ? methodStruct.enclosingType.getName() : "");
- System.err.println("AspectJ: 348488 debug: unusual local variable table for method " + typename + "."
- + method.getName());
- }
- }
- if (arguments.size() == 0) {
- // The local variable table is causing us trouble, try the annotation value
- // See 539121 for a jacoco variant of the cobertura issue below
- if (argNamesFromAnnotation != null) {
- String[] argNames = extractArgNamesFromAnnotationValue(method, argNamesFromAnnotation, methodStruct);
- if (argNames.length != 0) {
- return argNames;
- }
- }
- // could be cobertura code where some extra bytecode has been stuffed in at the start of the method
- // but the local variable table hasn't been repaired - for example:
- // LocalVariable(start_pc = 6, length = 40, index = 0:com.example.ExampleAspect this)
- // LocalVariable(start_pc = 6, length = 40, index = 1:org.aspectj.lang.ProceedingJoinPoint pjp)
- // LocalVariable(start_pc = 6, length = 40, index = 2:int __cobertura__line__number__)
- // LocalVariable(start_pc = 6, length = 40, index = 3:int __cobertura__branch__number__)
- LocalVariable localVariable = lvt[0];
- if (localVariable != null) { // pr348488
- if (localVariable.getStartPC() != 0) {
- // looks suspicious so let's use this information
- for (int j = 0; j < lvt.length && arguments.size() < method.getArgumentTypes().length; j++) {
- localVariable = lvt[j];
- if (localVariable.getIndex() >= startAtStackIndex) {
- arguments.add(new MethodArgument(localVariable.getName(), localVariable.getIndex()));
- }
- }
- }
- }
- }
- } else {
- if (argNamesFromAnnotation != null) {
- String[] argNames = extractArgNamesFromAnnotationValue(method, argNamesFromAnnotation, methodStruct);
- if (argNames != null) {
- return argNames;
- }
- }
- }
-
- if (arguments.size() != method.getArgumentTypes().length) {
- return EMPTY_STRINGS;
- }
-
- // sort by index
- Collections.sort(arguments, new Comparator<MethodArgument>() {
- public int compare(MethodArgument mo, MethodArgument mo1) {
- if (mo.indexOnStack == mo1.indexOnStack) {
- return 0;
- } else if (mo.indexOnStack > mo1.indexOnStack) {
- return 1;
- } else {
- return -1;
- }
- }
- });
- String[] argumentNames = new String[arguments.size()];
- int i = 0;
- for (MethodArgument methodArgument : arguments) {
- argumentNames[i++] = methodArgument.name;
- }
- return argumentNames;
- }
-
- private static String[] extractArgNamesFromAnnotationValue(Method method, String argNamesFromAnnotation,
- AjAttributeMethodStruct methodStruct) {
- StringTokenizer st = new StringTokenizer(argNamesFromAnnotation, " ,");
- List<String> args = new ArrayList<String>();
- 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 args.toArray(new String[] {});
- }
-
- /**
- * A method argument, used for sorting by indexOnStack (ie order in signature)
- *
- * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
- */
- private static class MethodArgument {
- String name;
- int indexOnStack;
-
- public MethodArgument(String name, int indexOnStack) {
- this.name = name;
- this.indexOnStack = indexOnStack;
- }
- }
-
- /**
- * LazyResolvedPointcutDefinition lazyly resolve the pointcut so that we have time to register all pointcut referenced before
- * pointcut resolution happens
- *
- * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
- */
- public static class LazyResolvedPointcutDefinition extends ResolvedPointcutDefinition {
- private final Pointcut m_pointcutUnresolved; // null for abstract
- // pointcut
- private final IScope m_binding;
-
- private Pointcut m_lazyPointcut = null;
-
- public LazyResolvedPointcutDefinition(UnresolvedType declaringType, int modifiers, String name,
- UnresolvedType[] parameterTypes, UnresolvedType returnType, Pointcut pointcut, IScope binding) {
- super(declaringType, modifiers, name, parameterTypes, returnType, Pointcut.makeMatchesNothing(Pointcut.RESOLVED));
- m_pointcutUnresolved = pointcut;
- m_binding = binding;
- }
-
- @Override
- public Pointcut getPointcut() {
- if (m_lazyPointcut == null && m_pointcutUnresolved == null) {
- m_lazyPointcut = Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
- }
- if (m_lazyPointcut == null && m_pointcutUnresolved != null) {
- m_lazyPointcut = m_pointcutUnresolved.resolve(m_binding);
- m_lazyPointcut.copyLocationFrom(m_pointcutUnresolved);
- }
- return m_lazyPointcut;
- }
- }
-
- /**
- * Helper to test empty strings
- *
- * @param s
- * @return true if empty or null
- */
- private static boolean isNullOrEmpty(String s) {
- return (s == null || s.length() <= 0);
- }
-
- /**
- * Set the pointcut bindings for which to ignore unbound issues, so that we can implicitly bind xxxJoinPoint for @AJ advices
- *
- * @param pointcut
- * @param bindings
- */
- private static void setIgnoreUnboundBindingNames(Pointcut pointcut, FormalBinding[] bindings) {
- // register ImplicitBindings as to be ignored since unbound
- // TODO is it likely to fail in a bad way if f.e. this(jp) etc ?
- List<String> ignores = new ArrayList<String>();
- for (int i = 0; i < bindings.length; i++) {
- FormalBinding formalBinding = bindings[i];
- if (formalBinding instanceof FormalBinding.ImplicitFormalBinding) {
- ignores.add(formalBinding.getName());
- }
- }
- pointcut.m_ignoreUnboundBindingForNames = ignores.toArray(new String[ignores.size()]);
- }
-
- /**
- * A check exception when we cannot read debug info (needed for formal binding)
- */
- private static class UnreadableDebugInfoException extends Exception {
- }
-
- /**
- * Report an error
- *
- * @param message
- * @param location
- */
- private static void reportError(String message, AjAttributeStruct location) {
- if (!location.handler.isIgnoring(IMessage.ERROR)) {
- location.handler.handleMessage(new Message(message, location.enclosingType.getSourceLocation(), true));
- }
- }
-
- // private static void reportError(String message, IMessageHandler handler, ISourceLocation sourceLocation) {
- // if (!handler.isIgnoring(IMessage.ERROR)) {
- // handler.handleMessage(new Message(message, sourceLocation, true));
- // }
- // }
-
- /**
- * Report a warning
- *
- * @param message
- * @param location
- */
- private static void reportWarning(String message, AjAttributeStruct location) {
- if (!location.handler.isIgnoring(IMessage.WARNING)) {
- location.handler.handleMessage(new Message(message, location.enclosingType.getSourceLocation(), false));
- }
- }
-
- /**
- * Parse the given pointcut, return null on failure and issue an error
- *
- * @param pointcutString
- * @param struct
- * @param allowIf
- * @return pointcut, unresolved
- */
- private static Pointcut parsePointcut(String pointcutString, AjAttributeStruct struct, boolean allowIf) {
- try {
- PatternParser parser = new PatternParser(pointcutString, struct.context);
- Pointcut pointcut = parser.parsePointcut();
- parser.checkEof();
- pointcut.check(null, struct.enclosingType.getWorld());
- if (!allowIf && pointcutString.indexOf("if()") >= 0 && hasIf(pointcut)) {
- reportError("if() pointcut is not allowed at this pointcut location '" + pointcutString + "'", struct);
- return null;
- }
- pointcut.setLocation(struct.context, -1, -1);// FIXME -1,-1 is not
- // good enough
- return pointcut;
- } catch (ParserException e) {
- reportError("Invalid pointcut '" + pointcutString + "': " + e.toString()
- + (e.getLocation() == null ? "" : " at position " + e.getLocation().getStart()), struct);
- return null;
- }
- }
-
- private static boolean hasIf(Pointcut pointcut) {
- IfFinder visitor = new IfFinder();
- pointcut.accept(visitor, null);
- return visitor.hasIf;
- }
-
- /**
- * Parse the given type pattern, return null on failure and issue an error
- *
- * @param patternString
- * @param location
- * @return type pattern
- */
- private static TypePattern parseTypePattern(String patternString, AjAttributeStruct location) {
- try {
- TypePattern typePattern = new PatternParser(patternString).parseTypePattern();
- typePattern.setLocation(location.context, -1, -1);// FIXME -1,-1 is
- // not good
- // enough
- return typePattern;
- } catch (ParserException e) {
- reportError("Invalid type pattern'" + patternString + "' : " + e.getLocation(), location);
- return null;
- }
- }
-
- static class ThrownFormalNotDeclaredInAdviceSignatureException extends Exception {
-
- private final String formalName;
-
- public ThrownFormalNotDeclaredInAdviceSignatureException(String formalName) {
- this.formalName = formalName;
- }
-
- public String getFormalName() {
- return formalName;
- }
- }
-
- static class ReturningFormalNotDeclaredInAdviceSignatureException extends Exception {
-
- private final String formalName;
-
- public ReturningFormalNotDeclaredInAdviceSignatureException(String formalName) {
- this.formalName = formalName;
- }
-
- public String getFormalName() {
- return formalName;
- }
- }
-} \ No newline at end of file
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelAccessForInlineMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelAccessForInlineMunger.java
deleted file mode 100644
index b81f7ffb1..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelAccessForInlineMunger.java
+++ /dev/null
@@ -1,386 +0,0 @@
-/*******************************************************************************
- * 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:
- * Alexandre Vasseur initial implementation
- *******************************************************************************/
-package org.aspectj.weaver.bcel;
-
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-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.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionHandle;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.apache.bcel.generic.InvokeDynamic;
-import org.aspectj.apache.bcel.generic.InvokeInstruction;
-import org.aspectj.apache.bcel.generic.Type;
-import org.aspectj.weaver.AjAttribute;
-import org.aspectj.weaver.AjcMemberMaker;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.NameMangler;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.Shadow;
-import org.aspectj.weaver.UnresolvedType;
-
-/**
- * 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.
- * <p/>
- * This munger is used for @AJ aspects for which inlining wrapper is not done at compile time.
- * <p/>
- * Specific state and logic is kept in the munger ala ITD so that call/get/set pointcuts can still be matched on the wrapped member
- * thanks to the EffectiveSignature attribute.
- *
- * @author Alexandre Vasseur
- * @author Andy Clement
- */
-public class BcelAccessForInlineMunger extends BcelTypeMunger {
-
- private Map<String, ResolvedMember> inlineAccessors;
-
- private LazyClassGen aspectGen;
-
- /**
- * The wrapper methods representing any created inlineAccessors
- */
- private Set<LazyMethodGen> inlineAccessorMethodGens;
-
- public BcelAccessForInlineMunger(ResolvedType aspectType) {
- super(null, aspectType);
- if (aspectType.getWorld().isXnoInline()) {
- throw new Error("This should not happen");
- }
- }
-
- @Override
- public boolean munge(BcelClassWeaver weaver) {
- aspectGen = weaver.getLazyClassGen();
- inlineAccessors = new HashMap<String, ResolvedMember>(0);
- inlineAccessorMethodGens = new HashSet<LazyMethodGen>();
-
- // look for all @Around advices
- for (LazyMethodGen methodGen : aspectGen.getMethodGens()) {
- if (methodGen.hasAnnotation(UnresolvedType.forName("org/aspectj/lang/annotation/Around"))) {
- openAroundAdvice(methodGen);
- }
- }
-
- // add the accessors
- for (LazyMethodGen lazyMethodGen : inlineAccessorMethodGens) {
- aspectGen.addMethodGen(lazyMethodGen);
- }
-
- // flush some
- inlineAccessorMethodGens = null;
- // we keep m_inlineAccessorsResolvedMembers for shadow matching
-
- return true;
- }
-
- /**
- * Looks in the wrapper we have added so that we can find their effective signature if needed
- */
- @Override
- public ResolvedMember getMatchingSyntheticMember(Member member) {
- ResolvedMember rm = inlineAccessors.get(member.getName());// + member.getSignature());
-// System.err.println("lookup for " + member.getName() + ":" + member.getSignature() + " = "
-// + (rm == null ? "" : rm.getName()));
- return rm;
- }
-
- @Override
- public ResolvedMember getSignature() {
- return null;
- }
-
- /**
- * Match only the aspect for which we act
- */
- @Override
- public boolean matches(ResolvedType onType) {
- return aspectType.equals(onType);
- }
-
- /**
- * Prepare the around advice, flag it as cannot be inlined if it can't be
- */
- private void openAroundAdvice(LazyMethodGen aroundAdvice) {
- InstructionHandle curr = aroundAdvice.getBody().getStart();
- InstructionHandle end = aroundAdvice.getBody().getEnd();
- ConstantPool cpg = aroundAdvice.getEnclosingClass().getConstantPool();
- InstructionFactory factory = aroundAdvice.getEnclosingClass().getFactory();
-
- boolean realizedCannotInline = false;
- while (curr != end) {
- if (realizedCannotInline) {
- // we know we cannot inline this advice so no need for futher handling
- break;
- }
- InstructionHandle next = curr.getNext();
- Instruction inst = curr.getInstruction();
-
- // open-up method call
- if ((inst instanceof InvokeInstruction)) {
- InvokeInstruction invoke = (InvokeInstruction) inst;
- if (invoke instanceof InvokeDynamic) {
- realizedCannotInline = true;
- break;
- }
- ResolvedType callee = aspectGen.getWorld().resolve(UnresolvedType.forName(invoke.getClassName(cpg)));
-
- // look in the whole method list and not just declared for super calls and alike
- List<ResolvedMember> methods = callee.getMethodsWithoutIterator(false, true, false);
- for (ResolvedMember resolvedMember : methods) {
- if (invoke.getName(cpg).equals(resolvedMember.getName())
- && invoke.getSignature(cpg).equals(resolvedMember.getSignature()) && !resolvedMember.isPublic()) {
- if ("<init>".equals(invoke.getName(cpg))) {
- // skipping open up for private constructor
- // can occur when aspect new a private inner type
- // too complex to handle new + dup + .. + invokespecial here.
- aroundAdvice.setCanInline(false);
- realizedCannotInline = true;
- } else {
- // specific handling for super.foo() calls, where foo is non public
- ResolvedType memberType = aspectGen.getWorld().resolve(resolvedMember.getDeclaringType());
- if (!aspectType.equals(memberType) && memberType.isAssignableFrom(aspectType)) {
- // old test was...
- // if (aspectType.getSuperclass() != null
- // && aspectType.getSuperclass().getName().equals(resolvedMember.getDeclaringType().getName())) {
- ResolvedMember accessor = createOrGetInlineAccessorForSuperDispatch(resolvedMember);
- InvokeInstruction newInst = factory.createInvoke(aspectType.getName(), accessor.getName(),
- BcelWorld.makeBcelType(accessor.getReturnType()),
- BcelWorld.makeBcelTypes(accessor.getParameterTypes()), Constants.INVOKEVIRTUAL);
- curr.setInstruction(newInst);
- } else {
- ResolvedMember accessor = createOrGetInlineAccessorForMethod(resolvedMember);
- InvokeInstruction newInst = factory.createInvoke(aspectType.getName(), accessor.getName(),
- BcelWorld.makeBcelType(accessor.getReturnType()),
- BcelWorld.makeBcelTypes(accessor.getParameterTypes()), Constants.INVOKESTATIC);
- curr.setInstruction(newInst);
- }
- }
-
- break;// ok we found a matching callee member and swapped the instruction with the accessor
- }
- }
- } else if (inst instanceof FieldInstruction) {
- FieldInstruction invoke = (FieldInstruction) inst;
- ResolvedType callee = aspectGen.getWorld().resolve(UnresolvedType.forName(invoke.getClassName(cpg)));
- for (int i = 0; i < callee.getDeclaredJavaFields().length; i++) {
- ResolvedMember resolvedMember = callee.getDeclaredJavaFields()[i];
- if (invoke.getName(cpg).equals(resolvedMember.getName())
- && invoke.getSignature(cpg).equals(resolvedMember.getSignature()) && !resolvedMember.isPublic()) {
- final ResolvedMember accessor;
- if ((inst.opcode == Constants.GETFIELD) || (inst.opcode == Constants.GETSTATIC)) {
- accessor = createOrGetInlineAccessorForFieldGet(resolvedMember);
- } else {
- accessor = createOrGetInlineAccessorForFieldSet(resolvedMember);
- }
- InvokeInstruction newInst = factory.createInvoke(aspectType.getName(), accessor.getName(),
- BcelWorld.makeBcelType(accessor.getReturnType()),
- BcelWorld.makeBcelTypes(accessor.getParameterTypes()), Constants.INVOKESTATIC);
- curr.setInstruction(newInst);
-
- break;// ok we found a matching callee member and swapped the instruction with the accessor
- }
- }
- }
-
- curr = next;
- }
-
- // no reason for not inlining this advice
- // since it is used for @AJ advice that cannot be inlined by defauilt
- // make sure we set inline to true since we have done this analysis
- if (!realizedCannotInline) {
- aroundAdvice.setCanInline(true);
- }
- }
-
- /**
- * Find (or add if not yet created) an inline wrapper for a non public method call
- */
- private ResolvedMember createOrGetInlineAccessorForMethod(ResolvedMember resolvedMember) {
- String accessorName = NameMangler.inlineAccessMethodForMethod(resolvedMember.getName(), resolvedMember.getDeclaringType(),
- aspectType);
- String key = accessorName;// new StringBuilder(accessorName).append(resolvedMember.getSignature()).toString();
- ResolvedMember inlineAccessor = inlineAccessors.get(key);
-// System.err.println(key + " accessor=" + inlineAccessor);
- if (inlineAccessor == null) {
- // add static method to aspect
- inlineAccessor = AjcMemberMaker.inlineAccessMethodForMethod(aspectType, resolvedMember);
-
- // add new accessor method to aspect bytecode
- InstructionFactory factory = aspectGen.getFactory();
- LazyMethodGen method = makeMethodGen(aspectGen, inlineAccessor);
- method.makeSynthetic();
- List<AjAttribute> methodAttributes = new ArrayList<AjAttribute>();
- methodAttributes.add(new AjAttribute.AjSynthetic());
- methodAttributes.add(new AjAttribute.EffectiveSignatureAttribute(resolvedMember, Shadow.MethodCall, false));
- method.addAttribute(Utility.bcelAttribute(methodAttributes.get(0), aspectGen.getConstantPool()));
- // flag the effective signature, so that we can deobfuscate the signature to apply method call pointcut
- method.addAttribute(Utility.bcelAttribute(methodAttributes.get(1), aspectGen.getConstantPool()));
-
- inlineAccessorMethodGens.add(method);
-
- InstructionList il = method.getBody();
- int register = 0;
- for (int i = 0, max = inlineAccessor.getParameterTypes().length; i < max; i++) {
- UnresolvedType ptype = inlineAccessor.getParameterTypes()[i];
- Type type = BcelWorld.makeBcelType(ptype);
- il.append(InstructionFactory.createLoad(type, register));
- register += type.getSize();
- }
- il.append(Utility.createInvoke(factory, Modifier.isStatic(resolvedMember.getModifiers()) ? Constants.INVOKESTATIC
- : Constants.INVOKEVIRTUAL, resolvedMember));
- il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(inlineAccessor.getReturnType())));
-
- inlineAccessors.put(key, new BcelMethod(aspectGen.getBcelObjectType(), method.getMethod(), methodAttributes));
- }
- return inlineAccessor;
- }
-
- /**
- * Add an inline wrapper for a non public super.method call
- */
- private ResolvedMember createOrGetInlineAccessorForSuperDispatch(ResolvedMember resolvedMember) {
- String accessor = NameMangler.superDispatchMethod(aspectType, resolvedMember.getName());
-
- String key = accessor;
- ResolvedMember inlineAccessor = inlineAccessors.get(key);
-
- if (inlineAccessor == null) {
- // add super accessor method to class:
- inlineAccessor = AjcMemberMaker.superAccessMethod(aspectType, resolvedMember);
-
- // add new accessor method to aspect bytecode
- InstructionFactory factory = aspectGen.getFactory();
- LazyMethodGen method = makeMethodGen(aspectGen, inlineAccessor);
- // flag it synthetic, AjSynthetic
- method.makeSynthetic();
- List<AjAttribute> methodAttributes = new ArrayList<AjAttribute>();
- methodAttributes.add(new AjAttribute.AjSynthetic());
- methodAttributes.add(new AjAttribute.EffectiveSignatureAttribute(resolvedMember, Shadow.MethodCall, false));
- method.addAttribute(Utility.bcelAttribute(methodAttributes.get(0), aspectGen.getConstantPool()));
- // flag the effective signature, so that we can deobfuscate the signature to apply method call pointcut
- method.addAttribute(Utility.bcelAttribute(methodAttributes.get(1), aspectGen.getConstantPool()));
-
- inlineAccessorMethodGens.add(method);
-
- InstructionList il = method.getBody();
- il.append(InstructionConstants.ALOAD_0);
- int register = 1;
- for (int i = 0; i < inlineAccessor.getParameterTypes().length; i++) {
- UnresolvedType typeX = inlineAccessor.getParameterTypes()[i];
- Type type = BcelWorld.makeBcelType(typeX);
- il.append(InstructionFactory.createLoad(type, register));
- register += type.getSize();
- }
- il.append(Utility.createInvoke(factory, Constants.INVOKESPECIAL, resolvedMember));
- il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(inlineAccessor.getReturnType())));
-
- inlineAccessors.put(key, new BcelMethod(aspectGen.getBcelObjectType(), method.getMethod(), methodAttributes));
- }
- return inlineAccessor;
- }
-
- /**
- * Add an inline wrapper for a non public field get
- */
- private ResolvedMember createOrGetInlineAccessorForFieldGet(ResolvedMember resolvedMember) {
- String accessor = NameMangler.inlineAccessMethodForFieldGet(resolvedMember.getName(), resolvedMember.getDeclaringType(),
- aspectType);
- String key = accessor;
- ResolvedMember inlineAccessor = inlineAccessors.get(key);
-
- if (inlineAccessor == null) {
- // add static method to aspect
- inlineAccessor = AjcMemberMaker.inlineAccessMethodForFieldGet(aspectType, resolvedMember);
-
- // add new accessor method to aspect bytecode
- InstructionFactory factory = aspectGen.getFactory();
- LazyMethodGen method = makeMethodGen(aspectGen, inlineAccessor);
- // flag it synthetic, AjSynthetic
- method.makeSynthetic();
- List<AjAttribute> methodAttributes = new ArrayList<AjAttribute>();
- methodAttributes.add(new AjAttribute.AjSynthetic());
- methodAttributes.add(new AjAttribute.EffectiveSignatureAttribute(resolvedMember, Shadow.FieldGet, false));
- // flag the effective signature, so that we can deobfuscate the signature to apply method call pointcut
- method.addAttribute(Utility.bcelAttribute(methodAttributes.get(0), aspectGen.getConstantPool()));
- method.addAttribute(Utility.bcelAttribute(methodAttributes.get(1), aspectGen.getConstantPool()));
-
- inlineAccessorMethodGens.add(method);
-
- InstructionList il = method.getBody();
- if (Modifier.isStatic(resolvedMember.getModifiers())) {
- // field accessed is static so no "this" as accessor sole parameter
- } else {
- il.append(InstructionConstants.ALOAD_0);
- }
- il.append(Utility.createGet(factory, resolvedMember));
- il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(inlineAccessor.getReturnType())));
-
- inlineAccessors.put(key, new BcelMethod(aspectGen.getBcelObjectType(), method.getMethod(), methodAttributes));
- }
- return inlineAccessor;
- }
-
- /**
- * Add an inline wrapper for a non public field set
- */
- private ResolvedMember createOrGetInlineAccessorForFieldSet(ResolvedMember resolvedMember) {
- String accessor = NameMangler.inlineAccessMethodForFieldSet(resolvedMember.getName(), resolvedMember.getDeclaringType(),
- aspectType);
- String key = accessor;
- ResolvedMember inlineAccessor = inlineAccessors.get(key);
-
- if (inlineAccessor == null) {
- // add static method to aspect
- inlineAccessor = AjcMemberMaker.inlineAccessMethodForFieldSet(aspectType, resolvedMember);
-
- // add new accessor method to aspect bytecode
- InstructionFactory factory = aspectGen.getFactory();
- LazyMethodGen method = makeMethodGen(aspectGen, inlineAccessor);
- // flag it synthetic, AjSynthetic
- method.makeSynthetic();
- List<AjAttribute> methodAttributes = new ArrayList<AjAttribute>();
- methodAttributes.add(new AjAttribute.AjSynthetic());
- methodAttributes.add(new AjAttribute.EffectiveSignatureAttribute(resolvedMember, Shadow.FieldSet, false));
- method.addAttribute(Utility.bcelAttribute(methodAttributes.get(0), aspectGen.getConstantPool()));
- // flag the effective signature, so that we can deobfuscate the signature to apply method call pointcut
- method.addAttribute(Utility.bcelAttribute(methodAttributes.get(1), aspectGen.getConstantPool()));
-
- inlineAccessorMethodGens.add(method);
-
- InstructionList il = method.getBody();
- if (Modifier.isStatic(resolvedMember.getModifiers())) {
- // field accessed is static so sole parameter is field value to be set
- il.append(InstructionFactory.createLoad(BcelWorld.makeBcelType(resolvedMember.getReturnType()), 0));
- } else {
- il.append(InstructionConstants.ALOAD_0);
- il.append(InstructionFactory.createLoad(BcelWorld.makeBcelType(resolvedMember.getReturnType()), 1));
- }
- il.append(Utility.createSet(factory, resolvedMember));
- il.append(InstructionConstants.RETURN);
- inlineAccessors.put(key, new BcelMethod(aspectGen.getBcelObjectType(), method.getMethod(), methodAttributes));
- }
- return inlineAccessor;
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java b/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java
deleted file mode 100644
index d22b17d12..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java
+++ /dev/null
@@ -1,801 +0,0 @@
-/* *******************************************************************
- * 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
- * Alexandre Vasseur support for @AJ aspects
- * ******************************************************************/
-
-package org.aspectj.weaver.bcel;
-
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-
-import org.aspectj.apache.bcel.Constants;
-import org.aspectj.apache.bcel.classfile.LocalVariable;
-import org.aspectj.apache.bcel.classfile.LocalVariableTable;
-import org.aspectj.apache.bcel.generic.InstructionConstants;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionHandle;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.apache.bcel.generic.LineNumberTag;
-import org.aspectj.apache.bcel.generic.LocalVariableTag;
-import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.bridge.Message;
-import org.aspectj.weaver.Advice;
-import org.aspectj.weaver.AdviceKind;
-import org.aspectj.weaver.AjAttribute;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.IEclipseSourceContext;
-import org.aspectj.weaver.ISourceContext;
-import org.aspectj.weaver.Lint;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.ReferenceType;
-import org.aspectj.weaver.ReferenceTypeDelegate;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedMemberImpl;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.Shadow;
-import org.aspectj.weaver.ShadowMunger;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.WeaverMessages;
-import org.aspectj.weaver.World;
-import org.aspectj.weaver.ast.Literal;
-import org.aspectj.weaver.ast.Test;
-import org.aspectj.weaver.patterns.ExactTypePattern;
-import org.aspectj.weaver.patterns.ExposedState;
-import org.aspectj.weaver.patterns.PerClause;
-import org.aspectj.weaver.patterns.Pointcut;
-
-/**
- * Advice implemented for BCEL
- *
- * @author Erik Hilsdale
- * @author Jim Hugunin
- * @author Andy Clement
- */
-class BcelAdvice extends Advice {
-
- /**
- * If a match is not entirely statically determinable, this captures the runtime test that must succeed in order for the advice
- * to run.
- */
- private Test runtimeTest;
- private ExposedState exposedState;
- private int containsInvokedynamic = 0;// 0 = dontknow, 1=no, 2=yes
-
- public BcelAdvice(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member adviceSignature, ResolvedType concreteAspect) {
- super(attribute, pointcut, simplify(attribute.getKind(), adviceSignature));
- this.concreteAspect = concreteAspect;
- }
-
- /**
- * A heavyweight BcelMethod object is only required for around advice that will be inlined. For other kinds of advice it is
- * possible to save some space.
- */
- private static Member simplify(AdviceKind kind, Member adviceSignature) {
- if (adviceSignature != null) {
- UnresolvedType adviceDeclaringType = adviceSignature.getDeclaringType();
- // if it isnt around advice or it is but inlining is turned off then shrink it to a ResolvedMemberImpl
- if (kind != AdviceKind.Around
- || ((adviceDeclaringType instanceof ResolvedType) && ((ResolvedType) adviceDeclaringType).getWorld()
- .isXnoInline())) {
- if (adviceSignature instanceof BcelMethod) {
- BcelMethod bm = (BcelMethod) adviceSignature;
- if (bm.getMethod() != null && bm.getMethod().getAnnotations() != null) {
- return adviceSignature;
- }
- ResolvedMemberImpl simplermember = new ResolvedMemberImpl(bm.getKind(), bm.getDeclaringType(),
- bm.getModifiers(), bm.getReturnType(), bm.getName(), bm.getParameterTypes());// ,bm.getExceptions(),bm.getBackingGenericMember()
- // );
- simplermember.setParameterNames(bm.getParameterNames());
- return simplermember;
- }
- }
- }
- return adviceSignature;
- }
-
- @Override
- public ShadowMunger concretize(ResolvedType fromType, World world, PerClause clause) {
- if (!world.areAllLintIgnored()) {
- suppressLintWarnings(world);
- }
- ShadowMunger ret = super.concretize(fromType, world, clause);
- if (!world.areAllLintIgnored()) {
- clearLintSuppressions(world, this.suppressedLintKinds);
- }
- IfFinder ifinder = new IfFinder();
- ret.getPointcut().accept(ifinder, null);
- boolean hasGuardTest = ifinder.hasIf && getKind() != AdviceKind.Around;
- boolean isAround = getKind() == AdviceKind.Around;
- if ((getExtraParameterFlags() & ThisJoinPoint) != 0) {
- if (!isAround && !hasGuardTest && world.getLint().noGuardForLazyTjp.isEnabled()) {
- // can't build tjp lazily, no suitable test...
- // ... only want to record it once against the advice(bug 133117)
- world.getLint().noGuardForLazyTjp.signal("", getSourceLocation());
- }
- }
- return ret;
- }
-
- @Override
- public ShadowMunger parameterizeWith(ResolvedType declaringType, Map<String, UnresolvedType> typeVariableMap) {
- Pointcut pc = getPointcut().parameterizeWith(typeVariableMap, declaringType.getWorld());
-
- BcelAdvice ret = null;
- Member adviceSignature = signature;
- // allows for around advice where the return value is a type variable (see pr115250)
- if (signature instanceof ResolvedMember && signature.getDeclaringType().isGenericType()) {
- adviceSignature = ((ResolvedMember) signature).parameterizedWith(declaringType.getTypeParameters(), declaringType,
- declaringType.isParameterizedType());
- }
- ret = new BcelAdvice(this.attribute, pc, adviceSignature, this.concreteAspect);
- return ret;
- }
-
- @Override
- public boolean match(Shadow shadow, World world) {
- if (world.areAllLintIgnored()) {
- return super.match(shadow, world);
- } else {
- suppressLintWarnings(world);
- boolean ret = super.match(shadow, world);
- clearLintSuppressions(world, this.suppressedLintKinds);
- return ret;
- }
- }
-
- @Override
- public void specializeOn(Shadow shadow) {
- if (getKind() == AdviceKind.Around) {
- ((BcelShadow) shadow).initializeForAroundClosure();
- }
-
- // XXX this case is just here for supporting lazy test code
- if (getKind() == null) {
- exposedState = new ExposedState(0);
- return;
- }
- if (getKind().isPerEntry()) {
- exposedState = new ExposedState(0);
- } else if (getKind().isCflow()) {
- exposedState = new ExposedState(nFreeVars);
- } else if (getSignature() != null) {
- exposedState = new ExposedState(getSignature());
- } else {
- exposedState = new ExposedState(0);
- return; // XXX this case is just here for supporting lazy test code
- }
-
- World world = shadow.getIWorld();
- if (!world.areAllLintIgnored()) {
- suppressLintWarnings(world);
- }
- exposedState.setConcreteAspect(concreteAspect);
- runtimeTest = getPointcut().findResidue(shadow, exposedState);
- if (!world.areAllLintIgnored()) {
- clearLintSuppressions(world, this.suppressedLintKinds);
- }
-
- // these initializations won't be performed by findResidue, but need to be
- // so that the joinpoint is primed for weaving
- if (getKind() == AdviceKind.PerThisEntry) {
- shadow.getThisVar();
- } else if (getKind() == AdviceKind.PerTargetEntry) {
- shadow.getTargetVar();
- }
-
- // make sure thisJoinPoint parameters are initialized
- if ((getExtraParameterFlags() & ThisJoinPointStaticPart) != 0) {
- ((BcelShadow) shadow).getThisJoinPointStaticPartVar();
- ((BcelShadow) shadow).getEnclosingClass().warnOnAddedStaticInitializer(shadow, getSourceLocation());
- }
-
- if ((getExtraParameterFlags() & ThisJoinPoint) != 0) {
- boolean hasGuardTest = runtimeTest != Literal.TRUE && getKind() != AdviceKind.Around;
- boolean isAround = getKind() == AdviceKind.Around;
- ((BcelShadow) shadow).requireThisJoinPoint(hasGuardTest, isAround);
- ((BcelShadow) shadow).getEnclosingClass().warnOnAddedStaticInitializer(shadow, getSourceLocation());
- if (!hasGuardTest && world.getLint().multipleAdviceStoppingLazyTjp.isEnabled()) {
- // collect up the problematic advice
- ((BcelShadow) shadow).addAdvicePreventingLazyTjp(this);
- }
- }
-
- if ((getExtraParameterFlags() & ThisEnclosingJoinPointStaticPart) != 0) {
- ((BcelShadow) shadow).getThisEnclosingJoinPointStaticPartVar();
- ((BcelShadow) shadow).getEnclosingClass().warnOnAddedStaticInitializer(shadow, getSourceLocation());
- }
- }
-
- private boolean canInline(Shadow s) {
- if (attribute.isProceedInInners()) {
- return false;
- }
- // XXX this guard seems to only be needed for bad test cases
- if (concreteAspect == null || concreteAspect.isMissing()) {
- return false;
- }
-
- if (concreteAspect.getWorld().isXnoInline()) {
- return false;
- }
- // System.err.println("isWoven? " + ((BcelObjectType)concreteAspect).getLazyClassGen().getWeaverState());
- BcelObjectType boType = BcelWorld.getBcelObjectType(concreteAspect);
- if (boType == null) {
- // Could be a symptom that the aspect failed to build last build... return the default answer of false
- return false;
- }
- // Need isJava8 check
- // Does the advice contain invokedynamic...
- if (boType.javaClass.getMajor() == Constants.MAJOR_1_8) {
- if (containsInvokedynamic == 0) {
- containsInvokedynamic = 1;
- LazyMethodGen lmg = boType.getLazyClassGen().getLazyMethodGen(this.signature.getName(), this.signature.getSignature(), true);
- // Check Java8 supertypes
- ResolvedType searchType = concreteAspect;
- while (lmg == null) {
- searchType = searchType.getSuperclass();
- if (searchType == null) break;
- ReferenceTypeDelegate rtd = ((ReferenceType)searchType).getDelegate();
- if (rtd instanceof BcelObjectType) {
- BcelObjectType bot = (BcelObjectType)rtd;
- if (bot.javaClass.getMajor() < Constants.MAJOR_1_8) {
- break;
- }
- lmg = bot.getLazyClassGen().getLazyMethodGen(this.signature.getName(), this.signature.getSignature(), true);
- }
- }
- if (lmg != null) {
- InstructionList ilist = lmg.getBody();
- for (InstructionHandle src = ilist.getStart(); src != null; src = src.getNext()) {
- if (src.getInstruction().opcode == Constants.INVOKEDYNAMIC) {
- containsInvokedynamic = 2;
- break;
- }
- }
- }
- }
- }
- if (containsInvokedynamic == 2) {
- return false;
- }
- return boType.getLazyClassGen().isWoven();
- }
-
- private boolean aspectIsBroken() {
- if (concreteAspect instanceof ReferenceType) {
- ReferenceTypeDelegate rtDelegate = ((ReferenceType) concreteAspect).getDelegate();
- if (!(rtDelegate instanceof BcelObjectType)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean implementOn(Shadow s) {
- hasMatchedAtLeastOnce = true;
-
- // pr263323 - if the aspect is broken then the delegate will not be usable for weaving
- if (aspectIsBroken()) {
- return false;
- }
-
- BcelShadow shadow = (BcelShadow) s;
-
- // remove any unnecessary exceptions if the compiler option is set to
- // error or warning and if this piece of advice throws exceptions
- // (bug 129282). This may be expanded to include other compiler warnings
- // at the moment it only deals with 'declared exception is not thrown'
- if (!shadow.getWorld().isIgnoringUnusedDeclaredThrownException() && !getThrownExceptions().isEmpty()) {
- Member member = shadow.getSignature();
- if (member instanceof BcelMethod) {
- removeUnnecessaryProblems((BcelMethod) member, ((BcelMethod) member).getDeclarationLineNumber());
- } else {
- // we're in a call shadow therefore need the line number of the
- // declared method (which may be in a different type). However,
- // we want to remove the problems from the CompilationResult
- // held within the current type's EclipseSourceContext so need
- // the enclosing shadow too
- ResolvedMember resolvedMember = shadow.getSignature().resolve(shadow.getWorld());
- if (resolvedMember instanceof BcelMethod && shadow.getEnclosingShadow() instanceof BcelShadow) {
- Member enclosingMember = shadow.getEnclosingShadow().getSignature();
- if (enclosingMember instanceof BcelMethod) {
- removeUnnecessaryProblems((BcelMethod) enclosingMember,
- ((BcelMethod) resolvedMember).getDeclarationLineNumber());
- }
- }
- }
- }
-
- if (shadow.getIWorld().isJoinpointSynchronizationEnabled() && shadow.getKind() == Shadow.MethodExecution
- && (s.getSignature().getModifiers() & Modifier.SYNCHRONIZED) != 0) {
- shadow.getIWorld().getLint().advisingSynchronizedMethods.signal(new String[] { shadow.toString() },
- shadow.getSourceLocation(), new ISourceLocation[] { getSourceLocation() });
- }
-
- // FIXME AV - see #75442, this logic is not enough so for now comment it out until we fix the bug
- // // callback for perObject AJC MightHaveAspect postMunge (#75442)
- // if (getConcreteAspect() != null
- // && getConcreteAspect().getPerClause() != null
- // && PerClause.PEROBJECT.equals(getConcreteAspect().getPerClause().getKind())) {
- // final PerObject clause;
- // if (getConcreteAspect().getPerClause() instanceof PerFromSuper) {
- // clause = (PerObject)((PerFromSuper) getConcreteAspect().getPerClause()).lookupConcretePerClause(getConcreteAspect());
- // } else {
- // clause = (PerObject) getConcreteAspect().getPerClause();
- // }
- // if (clause.isThis()) {
- // PerObjectInterfaceTypeMunger.registerAsAdvisedBy(s.getThisVar().getType(), getConcreteAspect());
- // } else {
- // PerObjectInterfaceTypeMunger.registerAsAdvisedBy(s.getTargetVar().getType(), getConcreteAspect());
- // }
- // }
- if (runtimeTest == Literal.FALSE) { // not usually allowed, except in one case (260384)
- Member sig = shadow.getSignature();
- if (sig.getArity() == 0 && shadow.getKind() == Shadow.MethodCall && sig.getName().charAt(0) == 'c'
- && sig.getReturnType().equals(ResolvedType.OBJECT) && sig.getName().equals("clone")) {
- return false;
- }
- }
-
- if (getKind() == AdviceKind.Before) {
- shadow.weaveBefore(this);
- } else if (getKind() == AdviceKind.AfterReturning) {
- shadow.weaveAfterReturning(this);
- } else if (getKind() == AdviceKind.AfterThrowing) {
- UnresolvedType catchType = hasExtraParameter() ? getExtraParameterType() : UnresolvedType.THROWABLE;
- shadow.weaveAfterThrowing(this, catchType);
- } else if (getKind() == AdviceKind.After) {
- shadow.weaveAfter(this);
- } else if (getKind() == AdviceKind.Around) {
- // Note: under regular LTW the aspect is usually loaded after the first use of any class affected by it.
- // This means that as long as the aspect has not been thru the LTW, it's woven state is unknown
- // and thus canInline(s) will return false.
- // To force inlining (test), ones can do Class aspect = FQNAspect.class in the clinit of the target class
- // FIXME AV : for AJC compiled @AJ aspect (or any code style aspect), the woven state can never be known
- // if the aspect belongs to a parent classloader. In that case the aspect will never be inlined.
- // It might be dangerous to change that especially for @AJ aspect non compiled with AJC since if those
- // are not weaved (f.e. use of some limited LTW etc) then they cannot be prepared for inlining.
- // One solution would be to flag @AJ aspect with an annotation as "prepared" and query that one.
- LazyClassGen enclosingClass = shadow.getEnclosingClass();
- if (enclosingClass != null && enclosingClass.isInterface() && shadow.getEnclosingMethod().getName().charAt(0) == '<') {
- // Do not add methods with bodies to an interface (252198, 163005)
- shadow.getWorld().getLint().cannotAdviseJoinpointInInterfaceWithAroundAdvice.signal(shadow.toString(),
- shadow.getSourceLocation());
- return false;
- }
- if (!canInline(s)) {
- shadow.weaveAroundClosure(this, hasDynamicTests());
- } else {
- shadow.weaveAroundInline(this, hasDynamicTests());
- }
- } else if (getKind() == AdviceKind.InterInitializer) {
- shadow.weaveAfterReturning(this);
- } else if (getKind().isCflow()) {
- shadow.weaveCflowEntry(this, getSignature());
- } else if (getKind() == AdviceKind.PerThisEntry) {
- shadow.weavePerObjectEntry(this, (BcelVar) shadow.getThisVar());
- } else if (getKind() == AdviceKind.PerTargetEntry) {
- shadow.weavePerObjectEntry(this, (BcelVar) shadow.getTargetVar());
- } else if (getKind() == AdviceKind.Softener) {
- shadow.weaveSoftener(this, ((ExactTypePattern) exceptionType).getType());
- } else if (getKind() == AdviceKind.PerTypeWithinEntry) {
- // PTWIMPL Entry to ptw is the static initialization of a type that matched the ptw type pattern
- shadow.weavePerTypeWithinAspectInitialization(this, shadow.getEnclosingType());
- } else {
- throw new BCException("unimplemented kind: " + getKind());
- }
- return true;
- }
-
- private void removeUnnecessaryProblems(BcelMethod method, int problemLineNumber) {
- ISourceContext sourceContext = method.getSourceContext();
- if (sourceContext instanceof IEclipseSourceContext) {
- ((IEclipseSourceContext) sourceContext).removeUnnecessaryProblems(method, problemLineNumber);
- }
- }
-
- // ---- implementations
-
- private Collection<ResolvedType> collectCheckedExceptions(UnresolvedType[] excs) {
- if (excs == null || excs.length == 0) {
- return Collections.emptyList();
- }
-
- Collection<ResolvedType> ret = new ArrayList<ResolvedType>();
- World world = concreteAspect.getWorld();
- ResolvedType runtimeException = world.getCoreType(UnresolvedType.RUNTIME_EXCEPTION);
- ResolvedType error = world.getCoreType(UnresolvedType.ERROR);
-
- for (int i = 0, len = excs.length; i < len; i++) {
- ResolvedType t = world.resolve(excs[i], true);
- if (t.isMissing()) {
- world.getLint().cantFindType
- .signal(WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_EXCEPTION_TYPE, excs[i].getName()),
- getSourceLocation());
- // IMessage msg = new Message(
- // WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_EXCEPTION_TYPE,excs[i].getName()),
- // "",IMessage.ERROR,getSourceLocation(),null,null);
- // world.getMessageHandler().handleMessage(msg);
- }
- if (!(runtimeException.isAssignableFrom(t) || error.isAssignableFrom(t))) {
- ret.add(t);
- }
- }
-
- return ret;
- }
-
- private Collection<ResolvedType> thrownExceptions = null;
-
- @Override
- public Collection<ResolvedType> getThrownExceptions() {
- if (thrownExceptions == null) {
- // ??? can we really lump in Around here, how does this interact with Throwable
- if (concreteAspect != null && concreteAspect.getWorld() != null && // null tests for test harness
- (getKind().isAfter() || getKind() == AdviceKind.Before || getKind() == AdviceKind.Around)) {
- World world = concreteAspect.getWorld();
- ResolvedMember m = world.resolve(signature);
- if (m == null) {
- thrownExceptions = Collections.emptyList();
- } else {
- thrownExceptions = collectCheckedExceptions(m.getExceptions());
- }
- } else {
- thrownExceptions = Collections.emptyList();
- }
- }
- return thrownExceptions;
- }
-
- /**
- * The munger must not check for the advice exceptions to be declared by the shadow in the case of @AJ aspects so that around
- * can throws Throwable
- *
- * @return
- */
- @Override
- public boolean mustCheckExceptions() {
- if (getConcreteAspect() == null) {
- return true;
- }
- return !getConcreteAspect().isAnnotationStyleAspect();
- }
-
- // only call me after prepare has been called
- @Override
- public boolean hasDynamicTests() {
- // if (hasExtraParameter() && getKind() == AdviceKind.AfterReturning) {
- // UnresolvedType extraParameterType = getExtraParameterType();
- // if (! extraParameterType.equals(UnresolvedType.OBJECT)
- // && ! extraParameterType.isPrimitive())
- // return true;
- // }
-
- return runtimeTest != null && !(runtimeTest == Literal.TRUE);// || pointcutTest == Literal.NO_TEST);
- }
-
- /**
- * get the instruction list for the really simple version of this advice. Is broken apart for other advice, but if you want it
- * in one block, this is the method to call.
- *
- * @param s The shadow around which these instructions will eventually live.
- * @param extraArgVar The var that will hold the return value or thrown exception for afterX advice
- * @param ifNoAdvice The instructionHandle to jump to if the dynamic tests for this munger fails.
- */
- InstructionList getAdviceInstructions(BcelShadow s, BcelVar extraArgVar, InstructionHandle ifNoAdvice) {
- BcelShadow shadow = s;
- InstructionFactory fact = shadow.getFactory();
- BcelWorld world = shadow.getWorld();
-
- InstructionList il = new InstructionList();
-
- // we test to see if we have the right kind of thing...
- // after throwing does this just by the exception mechanism.
- if (hasExtraParameter() && getKind() == AdviceKind.AfterReturning) {
- UnresolvedType extraParameterType = getExtraParameterType();
- if (!extraParameterType.equals(UnresolvedType.OBJECT) && !extraParameterType.isPrimitiveType()) {
- il.append(BcelRenderer.renderTest(fact, world,
- Test.makeInstanceof(extraArgVar, getExtraParameterType().resolve(world)), null, ifNoAdvice, null));
- }
- }
- il.append(getAdviceArgSetup(shadow, extraArgVar, null));
- il.append(getNonTestAdviceInstructions(shadow));
-
- InstructionHandle ifYesAdvice = il.getStart();
- il.insert(getTestInstructions(shadow, ifYesAdvice, ifNoAdvice, ifYesAdvice));
-
- // If inserting instructions at the start of a method, we need a nice line number for this entry
- // in the stack trace
- if (shadow.getKind() == Shadow.MethodExecution && getKind() == AdviceKind.Before) {
- int lineNumber = 0;
- // Uncomment this code if you think we should use the method decl line number when it exists...
- // // If the advised join point is in a class built by AspectJ, we can use the declaration line number
- // boolean b = shadow.getEnclosingMethod().getMemberView().hasDeclarationLineNumberInfo();
- // if (b) {
- // lineNumber = shadow.getEnclosingMethod().getMemberView().getDeclarationLineNumber();
- // } else { // If it wasn't, the best we can do is the line number of the first instruction in the method
- lineNumber = shadow.getEnclosingMethod().getMemberView().getLineNumberOfFirstInstruction();
- // }
- InstructionHandle start = il.getStart();
- if (lineNumber > 0) {
- start.addTargeter(new LineNumberTag(lineNumber));
- }
- // Fix up the local variables: find any that have a startPC of 0 and ensure they target the new start of the method
- LocalVariableTable lvt = shadow.getEnclosingMethod().getMemberView().getMethod().getLocalVariableTable();
- if (lvt != null) {
- LocalVariable[] lvTable = lvt.getLocalVariableTable();
- for (int i = 0; i < lvTable.length; i++) {
- LocalVariable lv = lvTable[i];
- if (lv.getStartPC() == 0) {
- start.addTargeter(new LocalVariableTag(lv.getSignature(), lv.getName(), lv.getIndex(), 0));
- }
- }
- }
- }
-
- return il;
- }
-
- public InstructionList getAdviceArgSetup(BcelShadow shadow, BcelVar extraVar, InstructionList closureInstantiation) {
- InstructionFactory fact = shadow.getFactory();
- BcelWorld world = shadow.getWorld();
- InstructionList il = new InstructionList();
-
- // if (targetAspectField != null) {
- // il.append(fact.createFieldAccess(
- // targetAspectField.getDeclaringType().getName(),
- // targetAspectField.getName(),
- // BcelWorld.makeBcelType(targetAspectField.getType()),
- // Constants.GETSTATIC));
- // }
- //
- // System.err.println("BcelAdvice: " + exposedState);
-
- if (exposedState.getAspectInstance() != null) {
- il.append(BcelRenderer.renderExpr(fact, world, exposedState.getAspectInstance()));
- }
- // pr121385
- boolean x = this.getDeclaringAspect().resolve(world).isAnnotationStyleAspect();
- final boolean isAnnotationStyleAspect = getConcreteAspect() != null && getConcreteAspect().isAnnotationStyleAspect() && x;
- boolean previousIsClosure = false;
- for (int i = 0, len = exposedState.size(); i < len; i++) {
- if (exposedState.isErroneousVar(i)) {
- continue; // Erroneous vars have already had error msgs reported!
- }
- BcelVar v = (BcelVar) exposedState.get(i);
-
- if (v == null) {
- // if not @AJ aspect, go on with the regular binding handling
- if (!isAnnotationStyleAspect) {
-
- } else {
- // ATAJ: for @AJ aspects, handle implicit binding of xxJoinPoint
- // if (getKind() == AdviceKind.Around) {
- // previousIsClosure = true;
- // il.append(closureInstantiation);
- if ("Lorg/aspectj/lang/ProceedingJoinPoint;".equals(getSignature().getParameterTypes()[i].getSignature())) {
- // make sure we are in an around, since we deal with the closure, not the arg here
- if (getKind() != AdviceKind.Around) {
- previousIsClosure = false;
- getConcreteAspect()
- .getWorld()
- .getMessageHandler()
- .handleMessage(
- new Message("use of ProceedingJoinPoint is allowed only on around advice (" + "arg "
- + i + " in " + toString() + ")", this.getSourceLocation(), true));
- // try to avoid verify error and pass in null
- il.append(InstructionConstants.ACONST_NULL);
- } else {
- if (previousIsClosure) {
- il.append(InstructionConstants.DUP);
- } else {
- previousIsClosure = true;
- il.append(closureInstantiation.copy());
- }
- }
- } else if ("Lorg/aspectj/lang/JoinPoint$StaticPart;".equals(getSignature().getParameterTypes()[i]
- .getSignature())) {
- previousIsClosure = false;
- if ((getExtraParameterFlags() & ThisJoinPointStaticPart) != 0) {
- shadow.getThisJoinPointStaticPartBcelVar().appendLoad(il, fact);
- }
- } else if ("Lorg/aspectj/lang/JoinPoint;".equals(getSignature().getParameterTypes()[i].getSignature())) {
- previousIsClosure = false;
- if ((getExtraParameterFlags() & ThisJoinPoint) != 0) {
- il.append(shadow.loadThisJoinPoint());
- }
- } else if ("Lorg/aspectj/lang/JoinPoint$EnclosingStaticPart;".equals(getSignature().getParameterTypes()[i]
- .getSignature())) {
- previousIsClosure = false;
- if ((getExtraParameterFlags() & ThisEnclosingJoinPointStaticPart) != 0) {
- shadow.getThisEnclosingJoinPointStaticPartBcelVar().appendLoad(il, fact);
- }
- } else if (hasExtraParameter()) {
- previousIsClosure = false;
- extraVar.appendLoadAndConvert(il, fact, getExtraParameterType().resolve(world));
- } else {
- previousIsClosure = false;
- getConcreteAspect()
- .getWorld()
- .getMessageHandler()
- .handleMessage(
- new Message("use of ProceedingJoinPoint is allowed only on around advice (" + "arg " + i
- + " in " + toString() + ")", this.getSourceLocation(), true));
- // try to avoid verify error and pass in null
- il.append(InstructionConstants.ACONST_NULL);
- }
- }
- } else {
- UnresolvedType desiredTy = getBindingParameterTypes()[i];
- v.appendLoadAndConvert(il, fact, desiredTy.resolve(world));
- }
- }
-
- // ATAJ: for code style aspect, handles the extraFlag as usual ie not
- // in the middle of the formal bindings but at the end, in a rock solid ordering
- if (!isAnnotationStyleAspect) {
- if (getKind() == AdviceKind.Around) {
- il.append(closureInstantiation);
- } else if (hasExtraParameter()) {
- extraVar.appendLoadAndConvert(il, fact, getExtraParameterType().resolve(world));
- }
-
- // handle thisJoinPoint parameters
- // these need to be in that same order as parameters in
- // org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration
- if ((getExtraParameterFlags() & ThisJoinPointStaticPart) != 0) {
- shadow.getThisJoinPointStaticPartBcelVar().appendLoad(il, fact);
- }
-
- if ((getExtraParameterFlags() & ThisJoinPoint) != 0) {
- il.append(shadow.loadThisJoinPoint());
- }
-
- if ((getExtraParameterFlags() & ThisEnclosingJoinPointStaticPart) != 0) {
- shadow.getThisEnclosingJoinPointStaticPartBcelVar().appendLoad(il, fact);
- }
- }
-
- return il;
- }
-
- public InstructionList getNonTestAdviceInstructions(BcelShadow shadow) {
- return new InstructionList(Utility.createInvoke(shadow.getFactory(), shadow.getWorld(), getOriginalSignature()));
- }
-
- @Override
- public Member getOriginalSignature() {
- Member sig = getSignature();
- if (sig instanceof ResolvedMember) {
- ResolvedMember rsig = (ResolvedMember) sig;
- if (rsig.hasBackingGenericMember()) {
- return rsig.getBackingGenericMember();
- }
- }
- return sig;
- }
-
- public InstructionList getTestInstructions(BcelShadow shadow, InstructionHandle sk, InstructionHandle fk, InstructionHandle next) {
- // System.err.println("test: " + pointcutTest);
- return BcelRenderer.renderTest(shadow.getFactory(), shadow.getWorld(), runtimeTest, sk, fk, next);
- }
-
- public int compareTo(Object other) {
- if (!(other instanceof BcelAdvice)) {
- return 0;
- }
- BcelAdvice o = (BcelAdvice) other;
-
- // System.err.println("compareTo: " + this + ", " + o);
- if (kind.getPrecedence() != o.kind.getPrecedence()) {
- if (kind.getPrecedence() > o.kind.getPrecedence()) {
- return +1;
- } else {
- return -1;
- }
- }
-
- if (kind.isCflow()) {
- // System.err.println("sort: " + this + " innerCflowEntries " + innerCflowEntries);
- // System.err.println(" " + o + " innerCflowEntries " + o.innerCflowEntries);
- boolean isBelow = (kind == AdviceKind.CflowBelowEntry);
-
- if (this.innerCflowEntries.contains(o)) {
- return isBelow ? +1 : -1;
- } else if (o.innerCflowEntries.contains(this)) {
- return isBelow ? -1 : +1;
- } else {
- return 0;
- }
- }
-
- if (kind.isPerEntry() || kind == AdviceKind.Softener) {
- return 0;
- }
-
- // System.out.println("compare: " + this + " with " + other);
- World world = concreteAspect.getWorld();
-
- int ret = concreteAspect.getWorld().compareByPrecedence(concreteAspect, o.concreteAspect);
- if (ret != 0) {
- return ret;
- }
-
- ResolvedType declaringAspect = getDeclaringAspect().resolve(world);
- ResolvedType o_declaringAspect = o.getDeclaringAspect().resolve(world);
-
- if (declaringAspect == o_declaringAspect) {
- if (kind.isAfter() || o.kind.isAfter()) {
- return this.getStart() < o.getStart() ? -1 : +1;
- } else {
- return this.getStart() < o.getStart() ? +1 : -1;
- }
- } else if (declaringAspect.isAssignableFrom(o_declaringAspect)) {
- return -1;
- } else if (o_declaringAspect.isAssignableFrom(declaringAspect)) {
- return +1;
- } else {
- return 0;
- }
- }
-
- public BcelVar[] getExposedStateAsBcelVars(boolean isAround) {
- // ATAJ aspect
- if (isAround) {
- // the closure instantiation has the same mapping as the extracted method from wich it is called
- if (getConcreteAspect() != null && getConcreteAspect().isAnnotationStyleAspect()) {
- return BcelVar.NONE;
- }
- }
-
- // System.out.println("vars: " + Arrays.asList(exposedState.vars));
- if (exposedState == null) {
- return BcelVar.NONE;
- }
- int len = exposedState.vars.length;
- BcelVar[] ret = new BcelVar[len];
- for (int i = 0; i < len; i++) {
- ret[i] = (BcelVar) exposedState.vars[i];
- }
- return ret; // (BcelVar[]) exposedState.vars;
- }
-
- protected void suppressLintWarnings(World inWorld) {
- if (suppressedLintKinds == null) {
- if (signature instanceof BcelMethod) {
- this.suppressedLintKinds = Utility.getSuppressedWarnings(signature.getAnnotations(), inWorld.getLint());
- } else {
- this.suppressedLintKinds = Collections.emptyList();
- return;
- }
- }
- inWorld.getLint().suppressKinds(suppressedLintKinds);
- }
-
- protected void clearLintSuppressions(World inWorld, Collection<Lint.Kind> toClear) {
- inWorld.getLint().clearSuppressions(toClear);
- }
-
- /**
- * For testing only
- */
- 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.emptyList(); // !!! interaction with unit tests
- }
-
-} \ No newline at end of file
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelAnnotation.java b/weaver/src/org/aspectj/weaver/bcel/BcelAnnotation.java
deleted file mode 100644
index 275eae512..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelAnnotation.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/* *******************************************************************
- * 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
- *
- * ******************************************************************/
-package org.aspectj.weaver.bcel;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
-import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValue;
-import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
-import org.aspectj.apache.bcel.classfile.annotation.EnumElementValue;
-import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
-import org.aspectj.weaver.AbstractAnnotationAJ;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.World;
-
-/**
- * Wraps a Bcel Annotation object and uses it to answer AnnotationAJ method calls. This is cheaper than translating all Bcel
- * annotations into AnnotationAJ objects.
- *
- * @author AndyClement
- */
-public class BcelAnnotation extends AbstractAnnotationAJ {
-
- private final AnnotationGen bcelAnnotation;
-
- public BcelAnnotation(AnnotationGen theBcelAnnotation, World world) {
- super(UnresolvedType.forSignature(theBcelAnnotation.getTypeSignature()).resolve(world));
- this.bcelAnnotation = theBcelAnnotation;
- }
-
- public BcelAnnotation(AnnotationGen theBcelAnnotation, ResolvedType resolvedAnnotationType) {
- super(resolvedAnnotationType);
- this.bcelAnnotation = theBcelAnnotation;
- }
-
- public String toString() {
- StringBuffer sb = new StringBuffer();
- List<NameValuePair> nvPairs = bcelAnnotation.getValues();
- sb.append("Anno[" + getTypeSignature() + " " + (isRuntimeVisible() ? "rVis" : "rInvis"));
- if (nvPairs.size() > 0) {
- sb.append(" ");
- int i = 0;
- for (NameValuePair element : nvPairs) {
- if (i > 0) {
- sb.append(',');
- }
- sb.append(element.getNameString()).append("=").append(element.getValue().toString());
- i++;
- }
- }
- sb.append("]");
- return sb.toString();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Set<String> getTargets() {
- if (!type.equals(UnresolvedType.AT_TARGET)) {
- return Collections.emptySet();
- }
- List<NameValuePair> values = bcelAnnotation.getValues();
- NameValuePair envp = values.get(0);
- ArrayElementValue aev = (ArrayElementValue) envp.getValue();
- ElementValue[] evs = aev.getElementValuesArray();
- Set<String> targets = new HashSet<String>();
- for (int i = 0; i < evs.length; i++) {
- EnumElementValue ev = (EnumElementValue) evs[i];
- targets.add(ev.getEnumValueString());
- }
- return targets;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean hasNameValuePair(String name, String value) {
- return bcelAnnotation.hasNameValuePair(name, value);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean hasNamedValue(String name) {
- return bcelAnnotation.hasNamedValue(name);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String stringify() {
- StringBuffer sb = new StringBuffer();
- sb.append("@").append(type.getClassName());
- List<NameValuePair> values = bcelAnnotation.getValues();
- if (values != null && values.size() != 0) {
- sb.append("(");
- for (NameValuePair nvPair : values) {
- sb.append(nvPair.getNameString()).append("=").append(nvPair.getValue().stringifyValue());
- }
- sb.append(")");
- }
- return sb.toString();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean isRuntimeVisible() {
- return this.bcelAnnotation.isRuntimeVisible();
- }
-
- /**
- * @return return the real bcel annotation being wrapped
- */
- public AnnotationGen getBcelAnnotation() {
- return bcelAnnotation;
- }
-
- /**
- * {@inheritDoc}
- */
- public String getStringFormOfValue(String name) {
- List<NameValuePair> annotationValues = this.bcelAnnotation.getValues();
- if (annotationValues == null || annotationValues.size() == 0) {
- return null;
- } else {
- for (NameValuePair nvPair : annotationValues) {
- if (nvPair.getNameString().equals(name)) {
- return nvPair.getValue().stringifyValue();
- }
- }
- return null;
- }
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelCflowAccessVar.java b/weaver/src/org/aspectj/weaver/bcel/BcelCflowAccessVar.java
deleted file mode 100644
index 2640edd95..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelCflowAccessVar.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/* *******************************************************************
- * 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 org.aspectj.apache.bcel.Constants;
-import org.aspectj.apache.bcel.generic.Instruction;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.apache.bcel.generic.Type;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.NameMangler;
-import org.aspectj.weaver.ResolvedType;
-
-/**
- * XXX Erik and I need to discuss this hierarchy. Having FieldRef extend Var is convenient, but hopefully there's a better design.
- *
- * This is always a static reference.
- */
-public class BcelCflowAccessVar extends BcelVar {
-
- private Member stackField;
- private int index;
-
- /**
- * @param type The type to convert to from Object
- * @param stackField the member containing the CFLOW_STACK_TYPE
- * @param index yeah yeah
- */
- public BcelCflowAccessVar(ResolvedType type, Member stackField, int index) {
- super(type, 0);
- this.stackField = stackField;
- this.index = index;
- }
-
- public String toString() {
- return "BcelCflowAccessVar(" + getType() + " " + stackField + "." + index + ")";
- }
-
- 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));
- }
-
- public InstructionList createLoadInstructions(ResolvedType toType, InstructionFactory fact) {
- InstructionList il = new InstructionList();
-
- il.append(Utility.createGet(fact, stackField));
- il.append(Utility.createConstant(fact, index));
- il.append(fact.createInvoke(NameMangler.CFLOW_STACK_TYPE, "get", Type.OBJECT, new Type[] { Type.INT },
- Constants.INVOKEVIRTUAL));
- il.append(Utility.createConversion(fact, Type.OBJECT, BcelWorld.makeBcelType(toType)));
-
- return il;
-
- }
-
- 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));
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelCflowCounterFieldAdder.java b/weaver/src/org/aspectj/weaver/bcel/BcelCflowCounterFieldAdder.java
deleted file mode 100644
index a70a5d8a9..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelCflowCounterFieldAdder.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*******************************************************************************
- * 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:
- * IBM Corporation - initial API and implementation
- * (Andy Clement)
- *******************************************************************************/
-
-package org.aspectj.weaver.bcel;
-
-import org.aspectj.apache.bcel.Constants;
-import org.aspectj.apache.bcel.generic.FieldGen;
-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.NameMangler;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedType;
-
-/**
- * This type munger will modify a given class (see the munge() method) to include a field representing a CflowCounter object.
- */
-public class BcelCflowCounterFieldAdder extends BcelTypeMunger {
- private ResolvedMember cflowCounterField;
-
- public BcelCflowCounterFieldAdder(ResolvedMember cflowCounterField) {
- super(null, (ResolvedType) cflowCounterField.getDeclaringType());
- this.cflowCounterField = cflowCounterField;
- }
-
- public boolean munge(BcelClassWeaver weaver) {
- LazyClassGen gen = weaver.getLazyClassGen();
-
- // Only munge one type!
- if (!gen.getType().equals(cflowCounterField.getDeclaringType()))
- return false;
-
- // Create the field declaration.
- // Something like: "public static final CflowCounter ajc$cflowCounter$0;"
- FieldGen f = new FieldGen(cflowCounterField.getModifiers(), BcelWorld.makeBcelType(cflowCounterField.getReturnType()),
- cflowCounterField.getName(), gen.getConstantPool());
-
- gen.addField(f, getSourceLocation());
-
- // Modify the ajc$preClinit() method to initialize it.
- // Something like: "ajc$cflowCounter$0 = new CflowCounter();"
- LazyMethodGen clinit = gen.getAjcPreClinit(); // StaticInitializer();
- InstructionList setup = new InstructionList();
- InstructionFactory fact = gen.getFactory();
-
- setup.append(fact.createNew(new ObjectType(NameMangler.CFLOW_COUNTER_TYPE)));
- setup.append(InstructionFactory.createDup(1));
- setup.append(fact.createInvoke(NameMangler.CFLOW_COUNTER_TYPE, "<init>", Type.VOID, new Type[0], Constants.INVOKESPECIAL));
-
- setup.append(Utility.createSet(fact, cflowCounterField));
- clinit.getBody().insert(setup);
-
- return true;
- }
-
- public ResolvedMember getMatchingSyntheticMember(Member member) {
- return null;
- }
-
- public ResolvedMember getSignature() {
- return cflowCounterField;
- }
-
- public boolean matches(ResolvedType onType) {
- return onType.equals(cflowCounterField.getDeclaringType());
- }
-
- public boolean existsToSupportShadowMunging() {
- return true;
- }
-
- public String toString() {
- return "(BcelTypeMunger: CflowField " + cflowCounterField.getDeclaringType().getName() + " " + cflowCounterField.getName()
- + ")";
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelCflowStackFieldAdder.java b/weaver/src/org/aspectj/weaver/bcel/BcelCflowStackFieldAdder.java
deleted file mode 100644
index 455edd174..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelCflowStackFieldAdder.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/* *******************************************************************
- * 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 org.aspectj.apache.bcel.Constants;
-import org.aspectj.apache.bcel.generic.FieldGen;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.apache.bcel.generic.Type;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.NameMangler;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedType;
-
-public class BcelCflowStackFieldAdder extends BcelTypeMunger {
- private ResolvedMember cflowStackField;
-
- public BcelCflowStackFieldAdder(ResolvedMember cflowStackField) {
- super(null, (ResolvedType) cflowStackField.getDeclaringType());
- this.cflowStackField = cflowStackField;
- }
-
- @Override
- public boolean munge(BcelClassWeaver weaver) {
- LazyClassGen gen = weaver.getLazyClassGen();
- if (!gen.getType().equals(cflowStackField.getDeclaringType())) {
- return false;
- }
- FieldGen f = new FieldGen(cflowStackField.getModifiers(), BcelWorld.makeBcelType(cflowStackField.getReturnType()),
- cflowStackField.getName(), gen.getConstantPool());
- gen.addField(f, getSourceLocation());
-
- LazyMethodGen clinit = gen.getAjcPreClinit(); // StaticInitializer();
- InstructionList setup = new InstructionList();
- InstructionFactory fact = gen.getFactory();
-
- setup.append(fact.createNew(NameMangler.CFLOW_STACK_TYPE));
- setup.append(InstructionFactory.createDup(1));
- setup.append(fact.createInvoke(NameMangler.CFLOW_STACK_TYPE, "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
-
- setup.append(Utility.createSet(fact, cflowStackField));
- clinit.getBody().insert(setup);
-
- return true;
- }
-
- @Override
- public ResolvedMember getMatchingSyntheticMember(Member member) {
- return null;
- }
-
- @Override
- public ResolvedMember getSignature() {
- return cflowStackField;
- }
-
- @Override
- public boolean matches(ResolvedType onType) {
- return onType.equals(cflowStackField.getDeclaringType());
- }
-
- @Override
- public boolean existsToSupportShadowMunging() {
- return true;
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
deleted file mode 100644
index 83919ed50..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
+++ /dev/null
@@ -1,3377 +0,0 @@
-/* *******************************************************************
- * 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.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
-import org.aspectj.apache.bcel.Constants;
-import org.aspectj.apache.bcel.classfile.BootstrapMethods;
-import org.aspectj.apache.bcel.classfile.ConstantPool;
-import org.aspectj.apache.bcel.classfile.Method;
-import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
-import org.aspectj.apache.bcel.generic.FieldGen;
-import org.aspectj.apache.bcel.generic.FieldInstruction;
-import org.aspectj.apache.bcel.generic.Instruction;
-import org.aspectj.apache.bcel.generic.InstructionBranch;
-import org.aspectj.apache.bcel.generic.InstructionCP;
-import org.aspectj.apache.bcel.generic.InstructionConstants;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionHandle;
-import org.aspectj.apache.bcel.generic.InstructionLV;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.apache.bcel.generic.InstructionSelect;
-import org.aspectj.apache.bcel.generic.InstructionTargeter;
-import org.aspectj.apache.bcel.generic.InvokeInstruction;
-import org.aspectj.apache.bcel.generic.LineNumberTag;
-import org.aspectj.apache.bcel.generic.LocalVariableTag;
-import org.aspectj.apache.bcel.generic.MULTIANEWARRAY;
-import org.aspectj.apache.bcel.generic.MethodGen;
-import org.aspectj.apache.bcel.generic.ObjectType;
-import org.aspectj.apache.bcel.generic.RET;
-import org.aspectj.apache.bcel.generic.Tag;
-import org.aspectj.apache.bcel.generic.Type;
-import org.aspectj.asm.AsmManager;
-import org.aspectj.bridge.IMessage;
-import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.bridge.Message;
-import org.aspectj.bridge.MessageUtil;
-import org.aspectj.bridge.WeaveMessage;
-import org.aspectj.bridge.context.CompilationAndWeavingContext;
-import org.aspectj.bridge.context.ContextToken;
-import org.aspectj.util.PartialOrder;
-import org.aspectj.weaver.AjAttribute;
-import org.aspectj.weaver.AjcMemberMaker;
-import org.aspectj.weaver.AnnotationAJ;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.ConcreteTypeMunger;
-import org.aspectj.weaver.IClassWeaver;
-import org.aspectj.weaver.IntMap;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.MissingResolvedTypeWithKnownSignature;
-import org.aspectj.weaver.NameMangler;
-import org.aspectj.weaver.NewConstructorTypeMunger;
-import org.aspectj.weaver.NewFieldTypeMunger;
-import org.aspectj.weaver.NewMethodTypeMunger;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedMemberImpl;
-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.UnresolvedTypeVariableReferenceType;
-import org.aspectj.weaver.WeaverStateInfo;
-import org.aspectj.weaver.World;
-import org.aspectj.weaver.model.AsmRelationshipProvider;
-import org.aspectj.weaver.patterns.DeclareAnnotation;
-import org.aspectj.weaver.patterns.ExactTypePattern;
-import org.aspectj.weaver.tools.Trace;
-import org.aspectj.weaver.tools.TraceFactory;
-
-class BcelClassWeaver implements IClassWeaver {
-
- private static Trace trace = TraceFactory.getTraceFactory().getTrace(BcelClassWeaver.class);
-
- public static boolean weave(BcelWorld world, LazyClassGen clazz, List<ShadowMunger> shadowMungers,
- List<ConcreteTypeMunger> typeMungers, List<ConcreteTypeMunger> lateTypeMungers, boolean inReweavableMode) {
- BcelClassWeaver classWeaver = new BcelClassWeaver(world, clazz, shadowMungers, typeMungers, lateTypeMungers);
- classWeaver.setReweavableMode(inReweavableMode);
- boolean b = classWeaver.weave();
- return b;
- }
-
- // --------------------------------------------
-
- private final LazyClassGen clazz;
- private final List<ShadowMunger> shadowMungers;
- private final List<ConcreteTypeMunger> typeMungers;
- private final List<ConcreteTypeMunger> lateTypeMungers;
-
- private List<ShadowMunger>[] indexedShadowMungers;
- private boolean canMatchBodyShadows = false;
-
- private final BcelObjectType ty; // alias of clazz.getType()
- private final BcelWorld world; // alias of ty.getWorld()
- private final ConstantPool cpg; // alias of clazz.getConstantPoolGen()
- private final InstructionFactory fact; // alias of clazz.getFactory();
-
- private final List<LazyMethodGen> addedLazyMethodGens = new ArrayList<LazyMethodGen>();
- private final Set<ResolvedMember> addedDispatchTargets = new HashSet<ResolvedMember>();
-
- private boolean inReweavableMode = false;
-
- private List<IfaceInitList> addedSuperInitializersAsList = null;
- private final Map<ResolvedType, IfaceInitList> addedSuperInitializers = new HashMap<ResolvedType, IfaceInitList>();
- private final List<ConcreteTypeMunger> addedThisInitializers = new ArrayList<ConcreteTypeMunger>();
- private final List<ConcreteTypeMunger> addedClassInitializers = new ArrayList<ConcreteTypeMunger>();
-
- private final Map<ResolvedMember, ResolvedMember> mapToAnnotationHolder = new HashMap<ResolvedMember, ResolvedMember>();
-
- // private BcelShadow clinitShadow = null;
-
- /**
- * This holds the initialization and pre-initialization shadows for this class that were actually matched by mungers (if no
- * match, then we don't even create the shadows really).
- */
- private final List<BcelShadow> initializationShadows = new ArrayList<BcelShadow>();
-
- private BcelClassWeaver(BcelWorld world, LazyClassGen clazz, List<ShadowMunger> shadowMungers,
- List<ConcreteTypeMunger> typeMungers, List<ConcreteTypeMunger> lateTypeMungers) {
- super();
- this.world = world;
- this.clazz = clazz;
- this.shadowMungers = shadowMungers;
- this.typeMungers = typeMungers;
- this.lateTypeMungers = lateTypeMungers;
- this.ty = clazz.getBcelObjectType();
- this.cpg = clazz.getConstantPool();
- this.fact = clazz.getFactory();
-
- indexShadowMungers();
-
- initializeSuperInitializerMap(ty.getResolvedTypeX());
- if (!checkedXsetForLowLevelContextCapturing) {
- Properties p = world.getExtraConfiguration();
- if (p != null) {
- String s = p.getProperty(World.xsetCAPTURE_ALL_CONTEXT, "false");
- captureLowLevelContext = s.equalsIgnoreCase("true");
- if (captureLowLevelContext) {
- world.getMessageHandler().handleMessage(
- MessageUtil.info("[" + World.xsetCAPTURE_ALL_CONTEXT
- + "=true] Enabling collection of low level context for debug/crash messages"));
- }
- }
- checkedXsetForLowLevelContextCapturing = true;
- }
- }
-
- private boolean canMatch(Shadow.Kind kind) {
- return indexedShadowMungers[kind.getKey()] != null;
- }
-
- // private void fastMatchShadowMungers(List shadowMungers, ArrayList
- // mungers, Kind kind) {
- // FastMatchInfo info = new FastMatchInfo(clazz.getType(), kind);
- // for (Iterator i = shadowMungers.iterator(); i.hasNext();) {
- // ShadowMunger munger = (ShadowMunger) i.next();
- // FuzzyBoolean fb = munger.getPointcut().fastMatch(info);
- // WeaverMetrics.recordFastMatchResult(fb);// Could pass:
- // munger.getPointcut().toString()
- // if (fb.maybeTrue()) mungers.add(munger);
- // }
- // }
-
- private void initializeSuperInitializerMap(ResolvedType child) {
- ResolvedType[] superInterfaces = child.getDeclaredInterfaces();
- for (int i = 0, len = superInterfaces.length; i < len; i++) {
- if (ty.getResolvedTypeX().isTopmostImplementor(superInterfaces[i])) {
- if (addSuperInitializer(superInterfaces[i])) {
- initializeSuperInitializerMap(superInterfaces[i]);
- }
- }
- }
- }
-
- /**
- * Process the shadow mungers into array 'buckets', each bucket represents a shadow kind and contains a list of shadowmungers
- * that could potentially apply at that shadow kind.
- */
- private void indexShadowMungers() {
- // beware the annoying property that SHADOW_KINDS[i].getKey == (i+1) !
- indexedShadowMungers = new List[Shadow.MAX_SHADOW_KIND + 1];
- for (ShadowMunger shadowMunger : shadowMungers) {
- int couldMatchKinds = shadowMunger.getPointcut().couldMatchKinds();
- for (Shadow.Kind kind : Shadow.SHADOW_KINDS) {
- if (kind.isSet(couldMatchKinds)) {
- byte k = kind.getKey();
- if (indexedShadowMungers[k] == null) {
- indexedShadowMungers[k] = new ArrayList<ShadowMunger>();
- if (!kind.isEnclosingKind()) {
- canMatchBodyShadows = true;
- }
- }
- indexedShadowMungers[k].add(shadowMunger);
- }
- }
- }
- }
-
- private boolean addSuperInitializer(ResolvedType onType) {
- if (onType.isRawType() || onType.isParameterizedType()) {
- onType = onType.getGenericType();
- }
- IfaceInitList l = addedSuperInitializers.get(onType);
- if (l != null) {
- return false;
- }
- l = new IfaceInitList(onType);
- addedSuperInitializers.put(onType, l);
- return true;
- }
-
- public void addInitializer(ConcreteTypeMunger cm) {
- NewFieldTypeMunger m = (NewFieldTypeMunger) cm.getMunger();
- ResolvedType onType = m.getSignature().getDeclaringType().resolve(world);
- if (onType.isRawType()) {
- onType = onType.getGenericType();
- }
-
- if (Modifier.isStatic(m.getSignature().getModifiers())) {
- addedClassInitializers.add(cm);
- } else {
- if (onType == ty.getResolvedTypeX()) {
- addedThisInitializers.add(cm);
- } else {
- IfaceInitList l = addedSuperInitializers.get(onType);
- l.list.add(cm);
- }
- }
- }
-
- private static class IfaceInitList implements PartialOrder.PartialComparable {
- final ResolvedType onType;
- List<ConcreteTypeMunger> list = new ArrayList<ConcreteTypeMunger>();
-
- IfaceInitList(ResolvedType onType) {
- this.onType = onType;
- }
-
- public int compareTo(Object other) {
- IfaceInitList o = (IfaceInitList) other;
- if (onType.isAssignableFrom(o.onType)) {
- return +1;
- } else if (o.onType.isAssignableFrom(onType)) {
- return -1;
- } else {
- return 0;
- }
- }
-
- public int fallbackCompareTo(Object other) {
- return 0;
- }
- }
-
- // XXX this is being called, but the result doesn't seem to be being used
- public boolean addDispatchTarget(ResolvedMember m) {
- return addedDispatchTargets.add(m);
- }
-
- public void addLazyMethodGen(LazyMethodGen gen) {
- addedLazyMethodGens.add(gen);
- }
-
- public void addOrReplaceLazyMethodGen(LazyMethodGen mg) {
- if (alreadyDefined(clazz, mg)) {
- return;
- }
-
- for (Iterator<LazyMethodGen> i = addedLazyMethodGens.iterator(); i.hasNext();) {
- LazyMethodGen existing = i.next();
- if (signaturesMatch(mg, existing)) {
- if (existing.definingType == null) {
- // this means existing was introduced on the class itself
- return;
- } else if (mg.definingType.isAssignableFrom(existing.definingType)) {
- // existing is mg's subtype and dominates mg
- return;
- } else if (existing.definingType.isAssignableFrom(mg.definingType)) {
- // mg is existing's subtype and dominates existing
- i.remove();
- addedLazyMethodGens.add(mg);
- return;
- } else {
- throw new BCException("conflict between: " + mg + " and " + existing);
- }
- }
- }
- addedLazyMethodGens.add(mg);
- }
-
- private boolean alreadyDefined(LazyClassGen clazz, LazyMethodGen mg) {
- for (Iterator<LazyMethodGen> i = clazz.getMethodGens().iterator(); i.hasNext();) {
- LazyMethodGen existing = i.next();
- if (signaturesMatch(mg, existing)) {
- if (!mg.isAbstract() && existing.isAbstract()) {
- i.remove();
- return false;
- }
- return true;
- }
- }
- return false;
- }
-
- private boolean signaturesMatch(LazyMethodGen mg, LazyMethodGen existing) {
- return mg.getName().equals(existing.getName()) && mg.getSignature().equals(existing.getSignature());
- }
-
- protected static LazyMethodGen makeBridgeMethod(LazyClassGen gen, ResolvedMember member) {
-
- // remove abstract modifier
- int mods = member.getModifiers();
- if (Modifier.isAbstract(mods)) {
- mods = mods - Modifier.ABSTRACT;
- }
-
- LazyMethodGen ret = new LazyMethodGen(mods, BcelWorld.makeBcelType(member.getReturnType()), member.getName(),
- BcelWorld.makeBcelTypes(member.getParameterTypes()), UnresolvedType.getNames(member.getExceptions()), gen);
-
- // 43972 : Static crosscutting makes interfaces unusable for javac
- // ret.makeSynthetic();
- return ret;
- }
-
- /**
- * Create a single bridge method called 'theBridgeMethod' that bridges to 'whatToBridgeTo'
- */
- private static void createBridgeMethod(BcelWorld world, LazyMethodGen whatToBridgeToMethodGen, LazyClassGen clazz, ResolvedMember theBridgeMethod) {
- InstructionList body;
- InstructionFactory fact;
- int pos = 0;
-
- ResolvedMember whatToBridgeTo = whatToBridgeToMethodGen.getMemberView();
-
- if (whatToBridgeTo == null) {
- whatToBridgeTo = new ResolvedMemberImpl(Member.METHOD, whatToBridgeToMethodGen.getEnclosingClass().getType(),
- whatToBridgeToMethodGen.getAccessFlags(), whatToBridgeToMethodGen.getName(),
- whatToBridgeToMethodGen.getSignature());
- }
- // The bridge method in this type will have the same signature as the one in the supertype
- LazyMethodGen bridgeMethod = makeBridgeMethod(clazz, theBridgeMethod);
- int newflags = bridgeMethod.getAccessFlags() | Constants.ACC_BRIDGE | Constants.ACC_SYNTHETIC ;// BRIDGE = 0x00000040
-
- if ((newflags & 0x00000100) != 0) {
- newflags = newflags - 0x100;// NATIVE = 0x00000100 - need to clear it
- }
-
- bridgeMethod.setAccessFlags(newflags);
- Type returnType = BcelWorld.makeBcelType(theBridgeMethod.getReturnType());
- Type[] paramTypes = BcelWorld.makeBcelTypes(theBridgeMethod.getParameterTypes());
- Type[] newParamTypes = whatToBridgeToMethodGen.getArgumentTypes();
- body = bridgeMethod.getBody();
- fact = clazz.getFactory();
-
- if (!whatToBridgeToMethodGen.isStatic()) {
- body.append(InstructionFactory.createThis());
- pos++;
- }
- for (int i = 0, len = paramTypes.length; i < len; i++) {
- Type paramType = paramTypes[i];
- body.append(InstructionFactory.createLoad(paramType, pos));
- if (!newParamTypes[i].equals(paramTypes[i])) {
- if (world.forDEBUG_bridgingCode) {
- System.err.println("Bridging: Cast " + newParamTypes[i] + " from " + paramTypes[i]);
- }
- body.append(fact.createCast(paramTypes[i], newParamTypes[i]));
- }
- pos += paramType.getSize();
- }
-
- body.append(Utility.createInvoke(fact, world, whatToBridgeTo));
- body.append(InstructionFactory.createReturn(returnType));
- clazz.addMethodGen(bridgeMethod);
- }
-
- /**
- * Weave a class and indicate through the return value whether the class was modified.
- *
- * @return true if the class was modified
- */
- public boolean weave() {
- if (clazz.isWoven() && !clazz.isReweavable()) {
- if (world.getLint().nonReweavableTypeEncountered.isEnabled()) {
- world.getLint().nonReweavableTypeEncountered.signal(clazz.getType().getName(), ty.getSourceLocation());
- }
- // Integer uniqueID = new Integer(rm.hashCode() * deca.hashCode());
- // if (!reportedProblems.contains(uniqueID)) {
- // reportedProblems.add(uniqueID);
- // world.getLint().elementAlreadyAnnotated.signal(new String[] { rm.toString(),
- // world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.ALREADY_WOVEN, clazz.getType().getName()),
- // ty.getSourceLocation(), null);
- return false;
- }
-
- Set<String> aspectsAffectingType = null;
- if (inReweavableMode || clazz.getType().isAspect()) {
- aspectsAffectingType = new HashSet<String>();
- }
-
- boolean isChanged = false;
-
- // we want to "touch" all aspects
- if (clazz.getType().isAspect()) {
- isChanged = true;
- }
-
- WeaverStateInfo typeWeaverState = (world.isOverWeaving() ? getLazyClassGen().getType().getWeaverState() : null);
- // start by munging all typeMungers
- for (ConcreteTypeMunger o : typeMungers) {
- if (!(o instanceof BcelTypeMunger)) {
- // ???System.err.println("surprising: " + o);
- continue;
- }
- BcelTypeMunger munger = (BcelTypeMunger) o;
-
- if (typeWeaverState != null && typeWeaverState.isAspectAlreadyApplied(munger.getAspectType())) {
- continue;
- }
- boolean typeMungerAffectedType = munger.munge(this);
- if (typeMungerAffectedType) {
- isChanged = true;
- if (inReweavableMode || clazz.getType().isAspect()) {
- aspectsAffectingType.add(munger.getAspectType().getSignature());
- }
- }
- }
-
- // Weave special half type/half shadow mungers...
- isChanged = weaveDeclareAtMethodCtor(clazz) || isChanged;
- isChanged = weaveDeclareAtField(clazz) || isChanged;
-
- // XXX do major sort of stuff
- // sort according to: Major: type hierarchy
- // within each list: dominates
- // don't forget to sort addedThisInitialiers according to dominates
- addedSuperInitializersAsList = new ArrayList<IfaceInitList>(addedSuperInitializers.values());
- addedSuperInitializersAsList = PartialOrder.sort(addedSuperInitializersAsList);
- if (addedSuperInitializersAsList == null) {
- throw new BCException("circularity in inter-types");
- }
-
- // this will create a static initializer if there isn't one
- // this is in just as bad taste as NOPs
- LazyMethodGen staticInit = clazz.getStaticInitializer();
- staticInit.getBody().insert(genInitInstructions(addedClassInitializers, true));
-
- // now go through each method, and match against each method. This
- // sets up each method's {@link LazyMethodGen#matchedShadows} field,
- // and it also possibly adds to {@link #initializationShadows}.
- List<LazyMethodGen> methodGens = new ArrayList<LazyMethodGen>(clazz.getMethodGens());
- for (LazyMethodGen member : methodGens) {
- if (!member.hasBody()) {
- continue;
- }
- if (world.isJoinpointSynchronizationEnabled() && world.areSynchronizationPointcutsInUse()
- && member.getMethod().isSynchronized()) {
- transformSynchronizedMethod(member);
- }
- boolean shadowMungerMatched = match(member);
- if (shadowMungerMatched) {
- // For matching mungers, add their declaring aspects to the list
- // that affected this type
- if (inReweavableMode || clazz.getType().isAspect()) {
- aspectsAffectingType.addAll(findAspectsForMungers(member));
- }
- isChanged = true;
- }
- }
-
- // now we weave all but the initialization shadows
- for (LazyMethodGen methodGen : methodGens) {
- if (!methodGen.hasBody()) {
- continue;
- }
- implement(methodGen);
- }
-
- // if we matched any initialization shadows, we inline and weave
- if (!initializationShadows.isEmpty()) {
- // Repeat next step until nothing left to inline...cant go on
- // infinetly as compiler will have detected and reported
- // "Recursive constructor invocation"
- List<LazyMethodGen> recursiveCtors = new ArrayList<LazyMethodGen>();
- while (inlineSelfConstructors(methodGens, recursiveCtors)) {
- }
- positionAndImplement(initializationShadows);
- }
-
- // now proceed with late type mungers
- if (lateTypeMungers != null) {
- for (Iterator<ConcreteTypeMunger> i = lateTypeMungers.iterator(); i.hasNext();) {
- BcelTypeMunger munger = (BcelTypeMunger) i.next();
- if (munger.matches(clazz.getType())) {
- boolean typeMungerAffectedType = munger.munge(this);
- if (typeMungerAffectedType) {
- isChanged = true;
- if (inReweavableMode || clazz.getType().isAspect()) {
- aspectsAffectingType.add(munger.getAspectType().getSignature());
- }
- }
- }
- }
- }
-
- // FIXME AV - see #75442, for now this is not enough to fix the bug,
- // comment that out until we really fix it
- // // flush to save some memory
- // PerObjectInterfaceTypeMunger.unregisterFromAsAdvisedBy(clazz.getType()
- // );
-
- // finally, if we changed, we add in the introduced methods.
- if (isChanged) {
- clazz.getOrCreateWeaverStateInfo(inReweavableMode);
- weaveInAddedMethods();
- }
-
- if (inReweavableMode) {
- WeaverStateInfo wsi = clazz.getOrCreateWeaverStateInfo(true);
- wsi.addAspectsAffectingType(aspectsAffectingType);
- if (!world.isOverWeaving()) {
- wsi.setUnwovenClassFileData(ty.getJavaClass().getBytes());
- wsi.setReweavable(true);
- } else {
- wsi.markOverweavingInUse();
- }
- } else {
- clazz.getOrCreateWeaverStateInfo(false).setReweavable(false);
- }
-
- // tidyup, reduce ongoing memory usage of BcelMethods that hang around
- for (LazyMethodGen mg : methodGens) {
- BcelMethod method = mg.getMemberView();
- if (method != null) {
- method.wipeJoinpointSignatures();
- }
- }
-
- return isChanged;
- }
-
- // **************************** start of bridge method creation code
- // *****************
-
- // FIXASC tidy this lot up !!
- // FIXASC refactor into ResolvedType or even ResolvedMember?
- /**
- * Check if a particular method is overriding another - refactored into this helper so it can be used from multiple places.
- * @return method that is overriding if it
- */
- private static ResolvedMember isOverriding(ResolvedType typeToCheck, ResolvedMember methodThatMightBeGettingOverridden,
- String mname, String mrettype, int mmods, boolean inSamePackage, UnresolvedType[] methodParamsArray) {
- // Check if we can be an override...
- if (Modifier.isStatic(methodThatMightBeGettingOverridden.getModifiers())) {
- // we can't be overriding a static method
- return null;
- }
- if (Modifier.isPrivate(methodThatMightBeGettingOverridden.getModifiers())) {
- // we can't be overriding a private method
- return null;
- }
- if (!methodThatMightBeGettingOverridden.getName().equals(mname)) {
- // names do not match (this will also skip <init> and <clinit>)
- return null;
- }
- if (methodThatMightBeGettingOverridden.getParameterTypes().length != methodParamsArray.length) {
- // not the same number of parameters
- return null;
- }
- if (!isVisibilityOverride(mmods, methodThatMightBeGettingOverridden, inSamePackage)) {
- // not override from visibility point of view
- return null;
- }
-
- if (typeToCheck.getWorld().forDEBUG_bridgingCode) {
- System.err.println(" Bridging:seriously considering this might be getting overridden '"
- + methodThatMightBeGettingOverridden + "'");
- }
-
- World w = typeToCheck.getWorld();
-
- // Look at erasures of parameters (List<String> erased is List)
- boolean sameParams = true;
- for (int p = 0, max = methodThatMightBeGettingOverridden.getParameterTypes().length; p < max; p++) {
-
- UnresolvedType mtmbgoParameter = methodThatMightBeGettingOverridden.getParameterTypes()[p];
- UnresolvedType ptype = methodParamsArray[p];
-
- if (mtmbgoParameter.isTypeVariableReference()) {
- if (!mtmbgoParameter.resolve(w).isAssignableFrom(ptype.resolve(w))) {
- sameParams = false;
- }
- } else {
- // old condition:
- boolean b = !methodThatMightBeGettingOverridden.getParameterTypes()[p].getErasureSignature().equals(
- methodParamsArray[p].getErasureSignature());
-
- UnresolvedType parameterType = methodThatMightBeGettingOverridden.getParameterTypes()[p];
-
- // Collapse to first bound (isn't that the same as erasure!
- if (parameterType instanceof UnresolvedTypeVariableReferenceType) {
- parameterType = ((UnresolvedTypeVariableReferenceType) parameterType).getTypeVariable().getFirstBound();
- }
-
- if (b) { // !parameterType.resolve(w).equals(parameterType2.resolve(w))) {
- sameParams = false;
- }
- }
- //
- // if (!ut.getErasureSignature().equals(ut2.getErasureSignature()))
- // sameParams = false;
- }
-
- // If the 'typeToCheck' represents a parameterized type then the method
- // will be the parameterized form of the
- // generic method in the generic type. So if the method was 'void
- // m(List<T> lt, T t)' and the parameterized type here
- // is I<String> then the method we are looking at will be 'void
- // m(List<String> lt, String t)' which when erased
- // is 'void m(List lt,String t)' - so if the parameters *do* match then
- // there is a generic method we are
- // overriding
-
- // FIXASC Why bother with the return type? If it is incompatible then the code has other problems!
- if (sameParams) {
- if (typeToCheck.isParameterizedType()) {
- return methodThatMightBeGettingOverridden.getBackingGenericMember();
- } else if (!methodThatMightBeGettingOverridden.getReturnType().getErasureSignature().equals(mrettype)) {
- // addressing the wierd situation from bug 147801
- // just check whether these things are in the right relationship
- // for covariance...
- ResolvedType superReturn = typeToCheck.getWorld().resolve(
- UnresolvedType.forSignature(methodThatMightBeGettingOverridden.getReturnType().getErasureSignature()));
- ResolvedType subReturn = typeToCheck.getWorld().resolve(UnresolvedType.forSignature(mrettype));
- if (superReturn.isAssignableFrom(subReturn)) {
- return methodThatMightBeGettingOverridden;
- }
- // } else if (typeToCheck.isParameterizedType()) {
- // return methodThatMightBeGettingOverridden.getBackingGenericMember();
- } else {
- return methodThatMightBeGettingOverridden;
- }
- }
- return null;
- }
-
- /**
- * Looks at the visibility modifiers between two methods, and knows whether they are from classes in the same package, and
- * decides whether one overrides the other.
- *
- * @return true if there is an overrides rather than a 'hides' relationship
- */
- static boolean isVisibilityOverride(int methodMods, ResolvedMember inheritedMethod, boolean inSamePackage) {
- int inheritedModifiers = inheritedMethod.getModifiers();
- if (Modifier.isStatic(inheritedModifiers)) {
- return false;
- }
- if (methodMods == inheritedModifiers) {
- return true;
- }
-
- if (Modifier.isPrivate(inheritedModifiers)) {
- return false;
- }
-
- boolean isPackageVisible = !Modifier.isPrivate(inheritedModifiers) && !Modifier.isProtected(inheritedModifiers)
- && !Modifier.isPublic(inheritedModifiers);
- if (isPackageVisible && !inSamePackage) {
- return false;
- }
-
- return true;
- }
-
- /**
- * This method recurses up a specified type looking for a method that overrides the one passed in.
- *
- * @return the method being overridden or null if none is found
- */
- public static void checkForOverride(ResolvedType typeToCheck, String mname, String mparams, String mrettype,
- int mmods, String mpkg, UnresolvedType[] methodParamsArray, List<ResolvedMember> overriddenMethodsCollector) {
-
- if (typeToCheck == null) {
- return;
- }
- if (typeToCheck instanceof MissingResolvedTypeWithKnownSignature) {
- return; // we just can't tell !
- }
-
-
- if (typeToCheck.getWorld().forDEBUG_bridgingCode) {
- System.err.println(" Bridging:checking for override of " + mname + " in " + typeToCheck);
- }
-
- String packageName = typeToCheck.getPackageName();
- if (packageName == null) {
- packageName = "";
- }
- // used when looking at visibility rules
- boolean inSamePackage = packageName.equals(mpkg);
-
- ResolvedMember[] methods = typeToCheck.getDeclaredMethods();
- for (int ii = 0; ii < methods.length; ii++) {
- // the method we are going to check
- ResolvedMember methodThatMightBeGettingOverridden = methods[ii];
- ResolvedMember isOverriding = isOverriding(typeToCheck, methodThatMightBeGettingOverridden, mname, mrettype, mmods,
- inSamePackage, methodParamsArray);
- if (isOverriding != null) {
- overriddenMethodsCollector.add(isOverriding);
- }
- }
- // was: List l = typeToCheck.getInterTypeMungers();
- List<ConcreteTypeMunger> l = (typeToCheck.isRawType() ? typeToCheck.getGenericType().getInterTypeMungers() : typeToCheck
- .getInterTypeMungers());
- for (Iterator<ConcreteTypeMunger> iterator = l.iterator(); iterator.hasNext();) {
- ConcreteTypeMunger o = iterator.next();
- // FIXME asc if its not a BcelTypeMunger then its an
- // EclipseTypeMunger ... do I need to worry about that?
- if (o instanceof BcelTypeMunger) {
- BcelTypeMunger element = (BcelTypeMunger) o;
- if (element.getMunger() instanceof NewMethodTypeMunger) {
- if (typeToCheck.getWorld().forDEBUG_bridgingCode) {
- System.err.println("Possible ITD candidate " + element);
- }
- ResolvedMember aMethod = element.getSignature();
- ResolvedMember isOverriding = isOverriding(typeToCheck, aMethod, mname, mrettype, mmods, inSamePackage,
- methodParamsArray);
- if (isOverriding != null) {
- overriddenMethodsCollector.add(isOverriding);
- }
- }
- }
- }
-
- if (typeToCheck.equals(UnresolvedType.OBJECT)) {
- return;
- }
-
- ResolvedType superclass = typeToCheck.getSuperclass();
- checkForOverride(superclass, mname, mparams, mrettype, mmods, mpkg, methodParamsArray,overriddenMethodsCollector);
-
- ResolvedType[] interfaces = typeToCheck.getDeclaredInterfaces();
- for (int i = 0; i < interfaces.length; i++) {
- ResolvedType anInterface = interfaces[i];
- checkForOverride(anInterface, mname, mparams, mrettype, mmods, mpkg, methodParamsArray,overriddenMethodsCollector);
- }
- }
-
- /**
- * We need to determine if any methods in this type require bridge methods - this method should only be called if necessary to
- * do this calculation, i.e. we are on a 1.5 VM (where covariance/generics exist) and the type hierarchy for the specified class
- * has changed (via decp/itd).
- *
- * See pr108101
- */
- public static boolean calculateAnyRequiredBridgeMethods(BcelWorld world, LazyClassGen clazz) {
- world.ensureAdvancedConfigurationProcessed();
-
- if (!world.isInJava5Mode()) {
- return false; // just double check... the caller should have already
- }
- if (clazz.isInterface()) {
- return false; // dont bother if we are an interface
- }
-
- boolean didSomething = false; // set if we build any bridge methods
- // So what methods do we have right now in this class?
- List<LazyMethodGen> methods = clazz.getMethodGens();
-
- // Keep a set of all methods from this type - it'll help us to check if bridge methods
- // have already been created, we don't want to do it twice!
- Set<String> methodsSet = new HashSet<String>();
- for (int i = 0; i < methods.size(); i++) {
- LazyMethodGen aMethod = methods.get(i);
- StringBuilder sb = new StringBuilder(aMethod.getName());
- sb.append(aMethod.getSignature());
- methodsSet.add(sb.toString()); // e.g. "foo(Ljava/lang/String;)V"
- }
-
- // Now go through all the methods in this type
- for (int i = 0; i < methods.size(); i++) {
- // This is the local method that we *might* have to bridge to
- LazyMethodGen bridgeToCandidate = methods.get(i);
- if (bridgeToCandidate.isBridgeMethod()) {
- continue; // Doh!
- }
- String name = bridgeToCandidate.getName();
- String psig = bridgeToCandidate.getParameterSignature();
- String rsig = bridgeToCandidate.getReturnType().getSignature();
-
- // if (bridgeToCandidate.isAbstract()) continue;
- if (bridgeToCandidate.isStatic()) {
- continue; // ignore static methods
- }
- if (name.endsWith("init>")) {
- continue; // Skip constructors and static initializers
- }
-
- if (world.forDEBUG_bridgingCode) {
- System.err.println("Bridging: Determining if we have to bridge to " + clazz.getName() + "." + name + "" + bridgeToCandidate.getSignature());
- }
-
- // Let's take a look at the superclass
- ResolvedType theSuperclass = clazz.getSuperClass();
- if (world.forDEBUG_bridgingCode) {
- System.err.println("Bridging: Checking supertype " + theSuperclass);
- }
- String pkgName = clazz.getPackageName();
- UnresolvedType[] bm = BcelWorld.fromBcel(bridgeToCandidate.getArgumentTypes());
- List<ResolvedMember> overriddenMethodsCollector = new ArrayList<ResolvedMember>();
- checkForOverride(theSuperclass, name, psig, rsig, bridgeToCandidate.getAccessFlags(), pkgName, bm, overriddenMethodsCollector);
- if (overriddenMethodsCollector.size() != 0) {
- for (ResolvedMember overriddenMethod: overriddenMethodsCollector) {
- String key = new StringBuilder(overriddenMethod.getName()).append(overriddenMethod.getSignatureErased()).toString(); // pr237419
- boolean alreadyHaveABridgeMethod = methodsSet.contains(key);
- if (!alreadyHaveABridgeMethod) {
- if (world.forDEBUG_bridgingCode) {
- System.err.println("Bridging:bridging to '" + overriddenMethod + "'");
- }
- createBridgeMethod(world, bridgeToCandidate, clazz, overriddenMethod);
- methodsSet.add(key);
- didSomething = true;
- }
- }
- }
-
- // Check superinterfaces
- String[] interfaces = clazz.getInterfaceNames();
- for (int j = 0; j < interfaces.length; j++) {
- if (world.forDEBUG_bridgingCode) {
- System.err.println("Bridging:checking superinterface " + interfaces[j]);
- }
- ResolvedType interfaceType = world.resolve(interfaces[j]);
- overriddenMethodsCollector.clear();
- checkForOverride(interfaceType, name, psig, rsig, bridgeToCandidate.getAccessFlags(),
- clazz.getPackageName(), bm, overriddenMethodsCollector);
- for (ResolvedMember overriddenMethod: overriddenMethodsCollector) {
- String key = new StringBuffer().append(overriddenMethod.getName()).append(overriddenMethod.getSignatureErased()).toString(); // pr237419
- boolean alreadyHaveABridgeMethod = methodsSet.contains(key);
- if (!alreadyHaveABridgeMethod) {
- createBridgeMethod(world, bridgeToCandidate, clazz, overriddenMethod);
- methodsSet.add(key);
- didSomething = true;
- if (world.forDEBUG_bridgingCode) {
- System.err.println("Bridging:bridging to " + overriddenMethod);
- }
- }
- }
- }
- }
-
- return didSomething;
- }
-
- // **************************** end of bridge method creation code *****************
-
- /**
- * Weave any declare @method/@ctor statements into the members of the supplied class
- */
- private boolean weaveDeclareAtMethodCtor(LazyClassGen clazz) {
- List<Integer> reportedProblems = new ArrayList<Integer>();
-
- List<DeclareAnnotation> allDecams = world.getDeclareAnnotationOnMethods();
- if (allDecams.isEmpty()) {
- return false;
- }
-
- boolean isChanged = false;
-
- // deal with ITDs
- List<ConcreteTypeMunger> itdMethodsCtors = getITDSubset(clazz, ResolvedTypeMunger.Method);
- itdMethodsCtors.addAll(getITDSubset(clazz, ResolvedTypeMunger.Constructor));
- if (!itdMethodsCtors.isEmpty()) {
- // Can't use the subset called 'decaMs' as it won't be right for
- // ITDs...
- isChanged = weaveAtMethodOnITDSRepeatedly(allDecams, itdMethodsCtors, reportedProblems);
- }
-
- List<DeclareAnnotation> decaMs = getMatchingSubset(allDecams, clazz.getType());
- if (decaMs.isEmpty()) {
- return false; // nothing to do
- }
-
- Set<DeclareAnnotation> unusedDecams = new HashSet<DeclareAnnotation>();
- unusedDecams.addAll(decaMs);
-
- // These methods may have been targeted with declare annotation. Example: ITD on an interface
- // where the top most implementor gets a real method. The top most implementor method
- // is an 'addedLazyMethodGen'
- if (addedLazyMethodGens!=null) {
- for (LazyMethodGen method: addedLazyMethodGens) {
- // They have no resolvedmember of their own, conjure one up for matching purposes
- ResolvedMember resolvedmember =
- new ResolvedMemberImpl(ResolvedMember.METHOD,method.getEnclosingClass().getType(),method.getAccessFlags(),
- BcelWorld.fromBcel(method.getReturnType()),method.getName(),
- BcelWorld.fromBcel(method.getArgumentTypes()),UnresolvedType.forNames(method.getDeclaredExceptions()));
- resolvedmember.setAnnotationTypes(method.getAnnotationTypes());
- resolvedmember.setAnnotations(method.getAnnotations());
-
- List<DeclareAnnotation> worthRetrying = new ArrayList<DeclareAnnotation>();
- boolean modificationOccured = false;
- for (DeclareAnnotation decam: decaMs) {
- if (decam.matches(resolvedmember, world)) {
- if (doesAlreadyHaveAnnotation(resolvedmember, decam, reportedProblems,false)) {
- // remove the declare @method since don't want an error when the annotation is already there
- unusedDecams.remove(decam);
- continue;
- }
-
- AnnotationGen a = ((BcelAnnotation) decam.getAnnotation()).getBcelAnnotation();
- // create copy to get the annotation type into the right constant pool
- AnnotationAJ aj = new BcelAnnotation(new AnnotationGen(a, clazz.getConstantPool(), true),world);
- method.addAnnotation(aj);
- resolvedmember.addAnnotation(decam.getAnnotation());
-
- AsmRelationshipProvider.addDeclareAnnotationMethodRelationship(decam.getSourceLocation(),
- clazz.getName(), resolvedmember, world.getModelAsAsmManager());
- reportMethodCtorWeavingMessage(clazz, resolvedmember, decam, method.getDeclarationLineNumber());
- isChanged = true;
- modificationOccured = true;
- unusedDecams.remove(decam);
- } else if (!decam.isStarredAnnotationPattern()) {
- // an annotation is specified that might be put on by a subsequent decaf
- worthRetrying.add(decam);
- }
- }
-
- // Multiple secondary passes
- while (!worthRetrying.isEmpty() && modificationOccured) {
- modificationOccured = false;
- // lets have another go
- List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>();
- for (DeclareAnnotation decam : worthRetrying) {
- if (decam.matches(resolvedmember, world)) {
- if (doesAlreadyHaveAnnotation(resolvedmember, decam, reportedProblems,false)) {
- // remove the declare @method since don't
- // want an error when
- // the annotation is already there
- unusedDecams.remove(decam);
- continue; // skip this one...
- }
- AnnotationGen a = ((BcelAnnotation) decam.getAnnotation()).getBcelAnnotation();
- // create copy to get the annotation type into the right constant pool
- AnnotationAJ aj = new BcelAnnotation(new AnnotationGen(a, clazz.getConstantPool(), true),world);
- method.addAnnotation(aj);
- resolvedmember.addAnnotation(decam.getAnnotation());
- AsmRelationshipProvider.addDeclareAnnotationMethodRelationship(decam.getSourceLocation(),
- clazz.getName(), resolvedmember, world.getModelAsAsmManager());// getMethod());
- isChanged = true;
- modificationOccured = true;
- forRemoval.add(decam);
- unusedDecams.remove(decam);
- }
- }
- worthRetrying.removeAll(forRemoval);
- }
- }
- }
-
-
- // deal with all the other methods...
- List<LazyMethodGen> members = clazz.getMethodGens();
- if (!members.isEmpty()) {
- for (int memberCounter = 0; memberCounter < members.size(); memberCounter++) {
- LazyMethodGen mg = members.get(memberCounter);
- if (!mg.getName().startsWith(NameMangler.PREFIX)) {
-
- // Single first pass
- List<DeclareAnnotation> worthRetrying = new ArrayList<DeclareAnnotation>();
- boolean modificationOccured = false;
- List<AnnotationGen> annotationsToAdd = null;
- for (DeclareAnnotation decaM : decaMs) {
-
- if (decaM.matches(mg.getMemberView(), world)) {
- if (doesAlreadyHaveAnnotation(mg.getMemberView(), decaM, reportedProblems,true)) {
- // remove the declare @method since don't want
- // an error when the annotation is already there
- unusedDecams.remove(decaM);
- continue; // skip this one...
- }
-
- if (annotationsToAdd == null) {
- annotationsToAdd = new ArrayList<AnnotationGen>();
- }
- AnnotationGen a = ((BcelAnnotation) decaM.getAnnotation()).getBcelAnnotation();
- AnnotationGen ag = new AnnotationGen(a, clazz.getConstantPool(), true);
- annotationsToAdd.add(ag);
- mg.addAnnotation(decaM.getAnnotation());
-
- AsmRelationshipProvider.addDeclareAnnotationMethodRelationship(decaM.getSourceLocation(),
- clazz.getName(), mg.getMemberView(), world.getModelAsAsmManager());// getMethod());
- reportMethodCtorWeavingMessage(clazz, mg.getMemberView(), decaM, mg.getDeclarationLineNumber());
- isChanged = true;
- modificationOccured = true;
- // remove the declare @method since have matched
- // against it
- unusedDecams.remove(decaM);
- } else {
- if (!decaM.isStarredAnnotationPattern()) {
- worthRetrying.add(decaM); // an annotation is
- // specified that
- // might be put on
- // by a subsequent
- // decaf
- }
- }
- }
-
- // Multiple secondary passes
- while (!worthRetrying.isEmpty() && modificationOccured) {
- modificationOccured = false;
- // lets have another go
- List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>();
- for (DeclareAnnotation decaM : worthRetrying) {
- if (decaM.matches(mg.getMemberView(), world)) {
- if (doesAlreadyHaveAnnotation(mg.getMemberView(), decaM, reportedProblems,true)) {
- // remove the declare @method since don't
- // want an error when
- // the annotation is already there
- unusedDecams.remove(decaM);
- continue; // skip this one...
- }
-
- if (annotationsToAdd == null) {
- annotationsToAdd = new ArrayList<AnnotationGen>();
- }
- AnnotationGen a = ((BcelAnnotation) decaM.getAnnotation()).getBcelAnnotation();
- // create copy to get the annotation type into the right constant pool
- AnnotationGen ag = new AnnotationGen(a, clazz.getConstantPool(), true);
- annotationsToAdd.add(ag);
- mg.addAnnotation(decaM.getAnnotation());
- AsmRelationshipProvider.addDeclareAnnotationMethodRelationship(decaM.getSourceLocation(),
- clazz.getName(), mg.getMemberView(), world.getModelAsAsmManager());// getMethod());
- isChanged = true;
- modificationOccured = true;
- forRemoval.add(decaM);
- // remove the declare @method since have matched
- // against it
- unusedDecams.remove(decaM);
- }
- }
- worthRetrying.removeAll(forRemoval);
- }
- if (annotationsToAdd != null) {
- Method oldMethod = mg.getMethod();
- MethodGen myGen = new MethodGen(oldMethod, clazz.getClassName(), clazz.getConstantPool(), false);
- for (AnnotationGen a : annotationsToAdd) {
- myGen.addAnnotation(a);
- }
- Method newMethod = myGen.getMethod();
- members.set(memberCounter, new LazyMethodGen(newMethod, clazz));
- }
-
- }
- }
- checkUnusedDeclareAts(unusedDecams, false);
- }
- return isChanged;
- }
-
- // TAG: WeavingMessage
- private void reportMethodCtorWeavingMessage(LazyClassGen clazz, ResolvedMember member, DeclareAnnotation decaM,
- int memberLineNumber) {
- if (!getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
- StringBuffer parmString = new StringBuffer("(");
- UnresolvedType[] paramTypes = member.getParameterTypes();
- for (int i = 0; i < paramTypes.length; i++) {
- UnresolvedType type = paramTypes[i];
- String s = org.aspectj.apache.bcel.classfile.Utility.signatureToString(type.getSignature());
- if (s.lastIndexOf('.') != -1) {
- s = s.substring(s.lastIndexOf('.') + 1);
- }
- parmString.append(s);
- if ((i + 1) < paramTypes.length) {
- parmString.append(",");
- }
- }
- parmString.append(")");
- String methodName = member.getName();
- StringBuffer sig = new StringBuffer();
- sig.append(org.aspectj.apache.bcel.classfile.Utility.accessToString(member.getModifiers()));
- sig.append(" ");
- sig.append(member.getReturnType().toString());
- sig.append(" ");
- sig.append(member.getDeclaringType().toString());
- sig.append(".");
- sig.append(methodName.equals("<init>") ? "new" : methodName);
- sig.append(parmString);
-
- StringBuffer loc = new StringBuffer();
- if (clazz.getFileName() == null) {
- loc.append("no debug info available");
- } else {
- loc.append(clazz.getFileName());
- if (memberLineNumber != -1) {
- loc.append(":" + memberLineNumber);
- }
- }
- getWorld().getMessageHandler().handleMessage(
- WeaveMessage.constructWeavingMessage(
- WeaveMessage.WEAVEMESSAGE_ANNOTATES,
- new String[] { sig.toString(), loc.toString(), decaM.getAnnotationString(),
- methodName.startsWith("<init>") ? "constructor" : "method", decaM.getAspect().toString(),
- Utility.beautifyLocation(decaM.getSourceLocation()) }));
- }
- }
-
- /**
- * Looks through a list of declare annotation statements and only returns those that could possibly match on a field/method/ctor
- * in type.
- */
- private List<DeclareAnnotation> getMatchingSubset(List<DeclareAnnotation> declareAnnotations, ResolvedType type) {
- List<DeclareAnnotation> subset = new ArrayList<DeclareAnnotation>();
- for (DeclareAnnotation da : declareAnnotations) {
- if (da.couldEverMatch(type)) {
- subset.add(da);
- }
- }
- return subset;
- }
-
- /**
- * Get a subset of all the type mungers defined on this aspect
- */
- private List<ConcreteTypeMunger> getITDSubset(LazyClassGen clazz, ResolvedTypeMunger.Kind wantedKind) {
- List<ConcreteTypeMunger> subset = new ArrayList<ConcreteTypeMunger>();
- for (ConcreteTypeMunger typeMunger : clazz.getBcelObjectType().getTypeMungers()) {
- if (typeMunger.getMunger().getKind() == wantedKind) {
- subset.add(typeMunger);
- }
- }
- return subset;
- }
-
- public LazyMethodGen locateAnnotationHolderForFieldMunger(LazyClassGen clazz, ConcreteTypeMunger fieldMunger) {
- NewFieldTypeMunger newFieldMunger = (NewFieldTypeMunger) fieldMunger.getMunger();
- ResolvedMember lookingFor = AjcMemberMaker.interFieldInitializer(newFieldMunger.getSignature(), clazz.getType());
- for (LazyMethodGen method : clazz.getMethodGens()) {
- if (method.getName().equals(lookingFor.getName())) {
- return method;
- }
- }
- return null;
- }
-
- // FIXME asc refactor this to neaten it up
- public LazyMethodGen locateAnnotationHolderForMethodCtorMunger(LazyClassGen clazz, ConcreteTypeMunger methodCtorMunger) {
- ResolvedTypeMunger rtMunger = methodCtorMunger.getMunger();
- ResolvedMember lookingFor = null;
- if (rtMunger instanceof NewMethodTypeMunger) {
- NewMethodTypeMunger nftm = (NewMethodTypeMunger) rtMunger;
- lookingFor = AjcMemberMaker.interMethodDispatcher(nftm.getSignature(), methodCtorMunger.getAspectType());
- } else if (rtMunger instanceof NewConstructorTypeMunger) {
- NewConstructorTypeMunger nftm = (NewConstructorTypeMunger) rtMunger;
- lookingFor = AjcMemberMaker.postIntroducedConstructor(methodCtorMunger.getAspectType(), nftm.getSignature()
- .getDeclaringType(), nftm.getSignature().getParameterTypes());
- } else {
- throw new BCException("Not sure what this is: " + methodCtorMunger);
- }
- String name = lookingFor.getName();
- String paramSignature = lookingFor.getParameterSignature();
- for (LazyMethodGen member : clazz.getMethodGens()) {
- if (member.getName().equals(name) && member.getParameterSignature().equals(paramSignature)) {
- return member;
- }
- }
- return null;
- }
-
- /**
- * Applies some set of declare @field constructs (List<DeclareAnnotation>) to some bunch of ITDfields (List<BcelTypeMunger>. It
- * will iterate over the fields repeatedly until everything has been applied.
- *
- */
- private boolean weaveAtFieldRepeatedly(List<DeclareAnnotation> decaFs, List<ConcreteTypeMunger> itdFields,
- List<Integer> reportedErrors) {
- boolean isChanged = false;
- for (Iterator<ConcreteTypeMunger> iter = itdFields.iterator(); iter.hasNext();) {
- BcelTypeMunger fieldMunger = (BcelTypeMunger) iter.next();
- ResolvedMember itdIsActually = fieldMunger.getSignature();
- Set<DeclareAnnotation> worthRetrying = new LinkedHashSet<DeclareAnnotation>();
- boolean modificationOccured = false;
-
- for (Iterator<DeclareAnnotation> iter2 = decaFs.iterator(); iter2.hasNext();) {
- DeclareAnnotation decaF = iter2.next();
- if (decaF.matches(itdIsActually, world)) {
- if (decaF.isRemover()) {
- LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
- if (annotationHolder.hasAnnotation(decaF.getAnnotationType())) {
- isChanged = true;
- // something to remove
- annotationHolder.removeAnnotation(decaF.getAnnotationType());
- AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(),
- decaF.getSourceLocation(), itdIsActually.getSourceLocation(), true);
- } else {
- worthRetrying.add(decaF);
- }
- } else {
-
- LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
- if (doesAlreadyHaveAnnotation(annotationHolder, itdIsActually, decaF, reportedErrors)) {
- continue; // skip this one...
- }
- annotationHolder.addAnnotation(decaF.getAnnotation());
- AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(),
- decaF.getSourceLocation(), itdIsActually.getSourceLocation(), false);
- isChanged = true;
- modificationOccured = true;
- }
- } else {
- if (!decaF.isStarredAnnotationPattern()) {
- worthRetrying.add(decaF); // an annotation is specified
- // that might be put on by a
- // subsequent decaf
- }
- }
- }
-
- while (!worthRetrying.isEmpty() && modificationOccured) {
- modificationOccured = false;
- List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>();
- for (Iterator<DeclareAnnotation> iter2 = worthRetrying.iterator(); iter2.hasNext();) {
- DeclareAnnotation decaF = iter2.next();
- if (decaF.matches(itdIsActually, world)) {
- if (decaF.isRemover()) {
- LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
- if (annotationHolder.hasAnnotation(decaF.getAnnotationType())) {
- isChanged = true;
- // something to remove
- annotationHolder.removeAnnotation(decaF.getAnnotationType());
- AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(),
- decaF.getSourceLocation(), itdIsActually.getSourceLocation(), true);
- forRemoval.add(decaF);
- }
- } else {
- LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
- if (doesAlreadyHaveAnnotation(annotationHolder, itdIsActually, decaF, reportedErrors)) {
- continue; // skip this one...
- }
- annotationHolder.addAnnotation(decaF.getAnnotation());
- AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(),
- decaF.getSourceLocation(), itdIsActually.getSourceLocation(), false);
- isChanged = true;
- modificationOccured = true;
- forRemoval.add(decaF);
- }
- }
- }
- worthRetrying.removeAll(forRemoval);
- }
- }
- return isChanged;
- }
-
- /**
- * Applies some set of declare @method/@ctor constructs (List<DeclareAnnotation>) to some bunch of ITDmembers
- * (List<BcelTypeMunger>. It will iterate over the fields repeatedly until everything has been applied.
- */
- private boolean weaveAtMethodOnITDSRepeatedly(List<DeclareAnnotation> decaMCs,
- List<ConcreteTypeMunger> itdsForMethodAndConstructor, List<Integer> reportedErrors) {
- boolean isChanged = false;
- AsmManager asmManager = world.getModelAsAsmManager();
- for (ConcreteTypeMunger methodctorMunger : itdsForMethodAndConstructor) {
- // for (Iterator iter = itdsForMethodAndConstructor.iterator(); iter.hasNext();) {
- // BcelTypeMunger methodctorMunger = (BcelTypeMunger) iter.next();
- ResolvedMember unMangledInterMethod = methodctorMunger.getSignature();
- List<DeclareAnnotation> worthRetrying = new ArrayList<DeclareAnnotation>();
- boolean modificationOccured = false;
-
- for (Iterator<DeclareAnnotation> iter2 = decaMCs.iterator(); iter2.hasNext();) {
- DeclareAnnotation decaMC = iter2.next();
- if (decaMC.matches(unMangledInterMethod, world)) {
- LazyMethodGen annotationHolder = locateAnnotationHolderForMethodCtorMunger(clazz, methodctorMunger);
- if (annotationHolder == null
- || doesAlreadyHaveAnnotation(annotationHolder, unMangledInterMethod, decaMC, reportedErrors)) {
- continue; // skip this one...
- }
- annotationHolder.addAnnotation(decaMC.getAnnotation());
- isChanged = true;
- AsmRelationshipProvider.addDeclareAnnotationRelationship(asmManager, decaMC.getSourceLocation(),
- unMangledInterMethod.getSourceLocation(), false);
- reportMethodCtorWeavingMessage(clazz, unMangledInterMethod, decaMC, -1);
- modificationOccured = true;
- } else {
- // If an annotation is specified, it might be added by one of the other declare annotation statements
- if (!decaMC.isStarredAnnotationPattern()) {
- worthRetrying.add(decaMC);
- }
- }
- }
-
- while (!worthRetrying.isEmpty() && modificationOccured) {
- modificationOccured = false;
- List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>();
- for (Iterator<DeclareAnnotation> iter2 = worthRetrying.iterator(); iter2.hasNext();) {
- DeclareAnnotation decaMC = iter2.next();
- if (decaMC.matches(unMangledInterMethod, world)) {
- LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, methodctorMunger);
- if (doesAlreadyHaveAnnotation(annotationHolder, unMangledInterMethod, decaMC, reportedErrors)) {
- continue; // skip this one...
- }
- annotationHolder.addAnnotation(decaMC.getAnnotation());
- unMangledInterMethod.addAnnotation(decaMC.getAnnotation());
- AsmRelationshipProvider.addDeclareAnnotationRelationship(asmManager, decaMC.getSourceLocation(),
- unMangledInterMethod.getSourceLocation(), false);
- isChanged = true;
- modificationOccured = true;
- forRemoval.add(decaMC);
- }
- worthRetrying.removeAll(forRemoval);
- }
- }
- }
- return isChanged;
- }
-
- private boolean dontAddTwice(DeclareAnnotation decaF, AnnotationAJ[] dontAddMeTwice) {
- for (AnnotationAJ ann : dontAddMeTwice) {
- if (ann != null && decaF.getAnnotation().getTypeName().equals(ann.getTypeName())) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Remove an annotation from the supplied array, if it is in there.
- */
- private AnnotationAJ[] removeFromAnnotationsArray(AnnotationAJ[] annotations,AnnotationAJ annotation) {
- for (int i=0;i<annotations.length;i++) {
- if (annotations[i] != null && annotation.getTypeName().equals(annotations[i].getTypeName())) {
- // Remove it!
- AnnotationAJ[] newArray = new AnnotationAJ[annotations.length-1];
- int index=0;
- for (int j=0;j<annotations.length;j++) {
- if (j!=i) {
- newArray[index++]=annotations[j];
- }
- }
- return newArray;
- }
- }
- return annotations;
- }
-
- // BUGWARNING not getting enough warnings out on declare @field ? There is a potential problem here with warnings not
- // coming out - this will occur if they are created on the second iteration round this loop.
- // We currently deactivate error reporting for the second time round. A possible solution is to record what annotations
- // were added by what decafs and check that to see if an error needs to be reported - this would be expensive so lets
- // skip it for now
- /**
- * Weave any declare @field statements into the fields of the supplied class. This will attempt to apply them to the ITDs too.
- *
- * Interesting case relating to public ITDd fields. The annotations are really stored against the interfieldinit method in the
- * aspect, but the public field is placed in the target type and then is processed in the 2nd pass over fields that occurs. I
- * think it would be more expensive to avoid putting the annotation on that inserted public field than just to have it put there
- * as well as on the interfieldinit method.
- */
- private boolean weaveDeclareAtField(LazyClassGen clazz) {
- List<Integer> reportedProblems = new ArrayList<Integer>();
- List<DeclareAnnotation> allDecafs = world.getDeclareAnnotationOnFields();
- if (allDecafs.isEmpty()) {
- return false;
- }
- boolean typeIsChanged = false;
- List<ConcreteTypeMunger> relevantItdFields = getITDSubset(clazz, ResolvedTypeMunger.Field);
- if (relevantItdFields != null) {
- typeIsChanged = weaveAtFieldRepeatedly(allDecafs, relevantItdFields, reportedProblems);
- }
-
- List<DeclareAnnotation> decafs = getMatchingSubset(allDecafs, clazz.getType());
- if (decafs.isEmpty()) {
- return typeIsChanged;
- }
-
- List<BcelField> fields = clazz.getFieldGens();
- if (fields != null) {
- Set<DeclareAnnotation> unusedDecafs = new HashSet<DeclareAnnotation>();
- unusedDecafs.addAll(decafs);
- for (BcelField field : fields) {
- if (!field.getName().startsWith(NameMangler.PREFIX)) {
- // Single first pass
- Set<DeclareAnnotation> worthRetrying = new LinkedHashSet<DeclareAnnotation>();
- boolean modificationOccured = false;
- AnnotationAJ[] dontAddMeTwice = field.getAnnotations();
-
- // go through all the declare @field statements
- for (DeclareAnnotation decaf : decafs) {
- if (decaf.getAnnotation() == null) {
- return false;
- }
- if (decaf.matches(field, world)) {
- if (decaf.isRemover()) {
- AnnotationAJ annotation = decaf.getAnnotation();
- if (field.hasAnnotation(annotation.getType())) {
- // something to remove
- typeIsChanged = true;
- field.removeAnnotation(annotation);
- AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(),
- decaf.getSourceLocation(), clazz.getName(), field, true);
- reportFieldAnnotationWeavingMessage(clazz, field, decaf, true);
- dontAddMeTwice = removeFromAnnotationsArray(dontAddMeTwice, annotation);
- } else {
- worthRetrying.add(decaf);
- }
- unusedDecafs.remove(decaf);
- } else {
- if (!dontAddTwice(decaf, dontAddMeTwice)) {
- if (doesAlreadyHaveAnnotation(field, decaf, reportedProblems,true )) {
- // remove the declare @field since don't want an error when the annotation is already there
- unusedDecafs.remove(decaf);
- continue;
- }
- field.addAnnotation(decaf.getAnnotation());
- }
- AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(),
- decaf.getSourceLocation(), clazz.getName(), field, false);
- reportFieldAnnotationWeavingMessage(clazz, field, decaf, false);
- typeIsChanged = true;
- modificationOccured = true;
- unusedDecafs.remove(decaf);
- }
- } else if (!decaf.isStarredAnnotationPattern() || decaf.isRemover()) {
- worthRetrying.add(decaf); // an annotation is specified that might be put on by a subsequent decaf
- }
- }
-
- // Multiple secondary passes
- while (!worthRetrying.isEmpty() && modificationOccured) {
- modificationOccured = false;
- // lets have another go with any remaining ones
- List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>();
- for (Iterator<DeclareAnnotation> iter = worthRetrying.iterator(); iter.hasNext();) {
- DeclareAnnotation decaF = iter.next();
-
- if (decaF.matches(field, world)) {
- if (decaF.isRemover()) {
- AnnotationAJ annotation = decaF.getAnnotation();
- if (field.hasAnnotation(annotation.getType())) {
- // something to remove
- typeIsChanged = modificationOccured = true;
- forRemoval.add(decaF);
- field.removeAnnotation(annotation);
- AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(),
- decaF.getSourceLocation(), clazz.getName(), field, true);
- reportFieldAnnotationWeavingMessage(clazz, field, decaF, true);
- }
- } else {
- // below code is for recursive things
- unusedDecafs.remove(decaF);
- if (doesAlreadyHaveAnnotation(field, decaF, reportedProblems,true)) {
- continue;
- }
- field.addAnnotation(decaF.getAnnotation());
- AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(),
- decaF.getSourceLocation(), clazz.getName(), field, false);
- typeIsChanged = modificationOccured = true;
- forRemoval.add(decaF);
- }
- }
- }
- worthRetrying.removeAll(forRemoval);
- }
- }
- }
- checkUnusedDeclareAts(unusedDecafs, true);
- }
- return typeIsChanged;
- }
-
- // bug 99191 - put out an error message if the type doesn't exist
- /**
- * Report an error if the reason a "declare @method/ctor/field" was not used was because the member specified does not exist.
- * This method is passed some set of declare statements that didn't match and a flag indicating whether the set contains declare @field
- * or declare @method/ctor entries.
- */
- private void checkUnusedDeclareAts(Set<DeclareAnnotation> unusedDecaTs, boolean isDeclareAtField) {
- for (DeclareAnnotation declA : unusedDecaTs) {
-
- // Error if an exact type pattern was specified
- boolean shouldCheck = declA.isExactPattern() || declA.getSignaturePattern().getExactDeclaringTypes().size() != 0;
-
- if (shouldCheck && declA.getKind() != DeclareAnnotation.AT_CONSTRUCTOR) {
- if (declA.getSignaturePattern().isMatchOnAnyName()) {
- shouldCheck = false;
- } else {
- List<ExactTypePattern> declaringTypePatterns = declA.getSignaturePattern().getExactDeclaringTypes();
- if (declaringTypePatterns.size() == 0) {
- shouldCheck = false;
- } else {
- for (ExactTypePattern exactTypePattern : declaringTypePatterns) {
- if (exactTypePattern.isIncludeSubtypes()) {
- shouldCheck = false;
- break;
- }
- }
- }
- }
- }
- if (shouldCheck) {
- // Quickly check if an ITD supplies the 'missing' member
- boolean itdMatch = false;
- List<ConcreteTypeMunger> lst = clazz.getType().getInterTypeMungers();
- for (Iterator<ConcreteTypeMunger> iterator = lst.iterator(); iterator.hasNext() && !itdMatch;) {
- ConcreteTypeMunger element = iterator.next();
- if (element.getMunger() instanceof NewFieldTypeMunger) {
- NewFieldTypeMunger nftm = (NewFieldTypeMunger) element.getMunger();
- itdMatch = declA.matches(nftm.getSignature(), world);
- } else if (element.getMunger() instanceof NewMethodTypeMunger) {
- NewMethodTypeMunger nmtm = (NewMethodTypeMunger) element.getMunger();
- itdMatch = declA.matches(nmtm.getSignature(), world);
- } else if (element.getMunger() instanceof NewConstructorTypeMunger) {
- NewConstructorTypeMunger nctm = (NewConstructorTypeMunger) element.getMunger();
- itdMatch = declA.matches(nctm.getSignature(), world);
- }
- }
- if (!itdMatch) {
- IMessage message = null;
- if (isDeclareAtField) {
- message = new Message("The field '" + declA.getSignaturePattern().toString() + "' does not exist",
- declA.getSourceLocation(), true);
- } else {
- message = new Message("The method '" + declA.getSignaturePattern().toString() + "' does not exist",
- declA.getSourceLocation(), true);
- }
- world.getMessageHandler().handleMessage(message);
- }
- }
- }
- }
-
- // TAG: WeavingMessage
- private void reportFieldAnnotationWeavingMessage(LazyClassGen clazz, BcelField theField, DeclareAnnotation decaf,
- boolean isRemove) {
- if (!getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
- world.getMessageHandler().handleMessage(
- WeaveMessage.constructWeavingMessage(
- isRemove ? WeaveMessage.WEAVEMESSAGE_REMOVES_ANNOTATION : WeaveMessage.WEAVEMESSAGE_ANNOTATES,
- new String[] { theField.getFieldAsIs().toString() + "' of type '" + clazz.getName(),
- clazz.getFileName(), decaf.getAnnotationString(), "field", decaf.getAspect().toString(),
- Utility.beautifyLocation(decaf.getSourceLocation()) }));
- }
- }
-
- /**
- * Check if a resolved member (field/method/ctor) already has an annotation, if it does then put out a warning and return true
- */
- private boolean doesAlreadyHaveAnnotation(ResolvedMember rm, DeclareAnnotation deca, List<Integer> reportedProblems, boolean reportError) {
- if (rm.hasAnnotation(deca.getAnnotationType())) {
- if (reportError && world.getLint().elementAlreadyAnnotated.isEnabled()) {
- Integer uniqueID = new Integer(rm.hashCode() * deca.hashCode());
- if (!reportedProblems.contains(uniqueID)) {
- reportedProblems.add(uniqueID);
- world.getLint().elementAlreadyAnnotated.signal(new String[] { rm.toString(),
- deca.getAnnotationType().toString() }, rm.getSourceLocation(),
- new ISourceLocation[] { deca.getSourceLocation() });
- }
- }
- return true;
- }
- return false;
- }
-
- private boolean doesAlreadyHaveAnnotation(LazyMethodGen rm, ResolvedMember itdfieldsig, DeclareAnnotation deca,
- List<Integer> reportedProblems) {
- if (rm != null && rm.hasAnnotation(deca.getAnnotationType())) {
- if (world.getLint().elementAlreadyAnnotated.isEnabled()) {
- Integer uniqueID = new Integer(rm.hashCode() * deca.hashCode());
- if (!reportedProblems.contains(uniqueID)) {
- reportedProblems.add(uniqueID);
- reportedProblems.add(new Integer(itdfieldsig.hashCode() * deca.hashCode()));
- world.getLint().elementAlreadyAnnotated.signal(new String[] { itdfieldsig.toString(),
- deca.getAnnotationType().toString() }, rm.getSourceLocation(),
- new ISourceLocation[] { deca.getSourceLocation() });
- }
- }
- return true;
- }
- return false;
- }
-
- private Set<String> findAspectsForMungers(LazyMethodGen mg) {
- Set<String> aspectsAffectingType = new HashSet<String>();
- for (BcelShadow shadow : mg.matchedShadows) {
- for (ShadowMunger munger : shadow.getMungers()) {
- if (munger instanceof BcelAdvice) {
- BcelAdvice bcelAdvice = (BcelAdvice) munger;
- if (bcelAdvice.getConcreteAspect() != null) {
- aspectsAffectingType.add(bcelAdvice.getConcreteAspect().getSignature());
- }
- } else {
- // It is a 'Checker' - we don't need to remember aspects
- // that only contributed Checkers...
- }
- }
- }
- return aspectsAffectingType;
- }
-
- private boolean inlineSelfConstructors(List<LazyMethodGen> methodGens, List<LazyMethodGen> recursiveCtors) {
- boolean inlinedSomething = false;
- List<LazyMethodGen> newRecursiveCtors = new ArrayList<LazyMethodGen>();
- for (LazyMethodGen methodGen : methodGens) {
- if (!methodGen.getName().equals("<init>")) {
- continue;
- }
- InstructionHandle ih = findSuperOrThisCall(methodGen);
- if (ih != null && isThisCall(ih)) {
- LazyMethodGen donor = getCalledMethod(ih);
- if (donor.equals(methodGen)) {
- newRecursiveCtors.add(donor);
- } else {
- if (!recursiveCtors.contains(donor)) {
- inlineMethod(donor, methodGen, ih);
- inlinedSomething = true;
- }
- }
- }
- }
- recursiveCtors.addAll(newRecursiveCtors);
- return inlinedSomething;
- }
-
- private void positionAndImplement(List<BcelShadow> initializationShadows) {
- for (BcelShadow s : initializationShadows) {
- positionInitializationShadow(s);
- // s.getEnclosingMethod().print();
- s.implement();
- }
- }
-
- private void positionInitializationShadow(BcelShadow s) {
- LazyMethodGen mg = s.getEnclosingMethod();
- InstructionHandle call = findSuperOrThisCall(mg);
- InstructionList body = mg.getBody();
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- if (s.getKind() == Shadow.PreInitialization) {
- // XXX assert first instruction is an ALOAD_0.
- // a pre shadow goes from AFTER the first instruction (which we
- // believe to
- // be an ALOAD_0) to just before the call to super
- r.associateWithTargets(Range.genStart(body, body.getStart().getNext()), Range.genEnd(body, call.getPrev()));
- } else {
- // assert s.getKind() == Shadow.Initialization
- r.associateWithTargets(Range.genStart(body, call.getNext()), Range.genEnd(body));
- }
- }
-
- private boolean isThisCall(InstructionHandle ih) {
- InvokeInstruction inst = (InvokeInstruction) ih.getInstruction();
- return inst.getClassName(cpg).equals(clazz.getName());
- }
-
- /**
- * inline a particular call in bytecode.
- *
- * @param donor the method we want to inline
- * @param recipient the method containing the call we want to inline
- * @param call the instructionHandle in recipient's body holding the call we want to inline.
- */
- public static void inlineMethod(LazyMethodGen donor, LazyMethodGen recipient, InstructionHandle call) {
- // assert recipient.contains(call)
-
- /*
- * Implementation notes:
- *
- * We allocate two slots for every tempvar so we don't screw up longs and doubles which may share space. This could be
- * conservatively avoided (no reference to a long/double instruction, don't do it) or packed later. Right now we don't
- * bother to pack.
- *
- * Allocate a new var for each formal param of the inlined. Fill with stack contents. Then copy the inlined instructions in
- * with the appropriate remap table. Any framelocs used by locals in inlined are reallocated to top of frame,
- */
- final InstructionFactory fact = recipient.getEnclosingClass().getFactory();
-
- IntMap frameEnv = new IntMap();
-
- // this also sets up the initial environment
- InstructionList argumentStores = genArgumentStores(donor, recipient, frameEnv, fact);
-
- InstructionList inlineInstructions = genInlineInstructions(donor, recipient, frameEnv, fact, false);
-
- inlineInstructions.insert(argumentStores);
-
- recipient.getBody().append(call, inlineInstructions);
- Utility.deleteInstruction(call, recipient);
- }
-
- // public BcelVar genTempVar(UnresolvedType typeX) {
- // return new BcelVar(typeX.resolve(world),
- // genTempVarIndex(typeX.getSize()));
- // }
- //
- // private int genTempVarIndex(int size) {
- // return enclosingMethod.allocateLocal(size);
- // }
-
- /**
- * Input method is a synchronized method, we remove the bit flag for synchronized and then insert a try..finally block
- *
- * Some jumping through firey hoops required - depending on the input code level (1.5 or not) we may or may not be able to use
- * the LDC instruction that takes a class literal (doesnt on <1.5).
- *
- * FIXME asc Before promoting -Xjoinpoints:synchronization to be a standard option, this needs a bunch of tidying up - there is
- * some duplication that can be removed.
- */
- public static void transformSynchronizedMethod(LazyMethodGen synchronizedMethod) {
- if (trace.isTraceEnabled()) {
- trace.enter("transformSynchronizedMethod", synchronizedMethod);
- }
- // System.err.println("DEBUG: Transforming synchronized method: "+
- // synchronizedMethod.getName());
- final InstructionFactory fact = synchronizedMethod.getEnclosingClass().getFactory();
- InstructionList body = synchronizedMethod.getBody();
- InstructionList prepend = new InstructionList();
- Type enclosingClassType = BcelWorld.makeBcelType(synchronizedMethod.getEnclosingClass().getType());
-
- // STATIC METHOD TRANSFORMATION
- if (synchronizedMethod.isStatic()) {
-
- // What to do here depends on the level of the class file!
- // LDC can handle class literals in Java5 and above *sigh*
- if (synchronizedMethod.getEnclosingClass().isAtLeastJava5()) {
- // MONITORENTER logic:
- // 0: ldc #2; //class C
- // 2: dup
- // 3: astore_0
- // 4: monitorenter
- int slotForLockObject = synchronizedMethod.allocateLocal(enclosingClassType);
- prepend.append(fact.createConstant(enclosingClassType));
- prepend.append(InstructionFactory.createDup(1));
- prepend.append(InstructionFactory.createStore(enclosingClassType, slotForLockObject));
- prepend.append(InstructionFactory.MONITORENTER);
-
- // MONITOREXIT logic:
-
- // We basically need to wrap the code from the method in a
- // finally block that
- // will ensure monitorexit is called. Content on the finally
- // block seems to
- // be always:
- //
- // E1: ALOAD_1
- // MONITOREXIT
- // ATHROW
- //
- // so lets build that:
- InstructionList finallyBlock = new InstructionList();
- finallyBlock.append(InstructionFactory.createLoad(Type.getType(java.lang.Class.class), slotForLockObject));
- finallyBlock.append(InstructionConstants.MONITOREXIT);
- finallyBlock.append(InstructionConstants.ATHROW);
-
- // finally -> E1
- // | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line
- // 21)
- // | LDC "hello"
- // | INVOKEVIRTUAL java.io.PrintStream.println
- // (Ljava/lang/String;)V
- // | ALOAD_1 (line 20)
- // | MONITOREXIT
- // finally -> E1
- // GOTO L0
- // finally -> E1
- // | E1: ALOAD_1
- // | MONITOREXIT
- // finally -> E1
- // ATHROW
- // L0: RETURN (line 23)
-
- // search for 'returns' and make them jump to the
- // aload_<n>,monitorexit
- InstructionHandle walker = body.getStart();
- List<InstructionHandle> rets = new ArrayList<InstructionHandle>();
- while (walker != null) {
- if (walker.getInstruction().isReturnInstruction()) {
- rets.add(walker);
- }
- walker = walker.getNext();
- }
- if (!rets.isEmpty()) {
- // need to ensure targeters for 'return' now instead target
- // the load instruction
- // (so we never jump over the monitorexit logic)
-
- for (Iterator<InstructionHandle> iter = rets.iterator(); iter.hasNext();) {
- InstructionHandle element = iter.next();
- InstructionList monitorExitBlock = new InstructionList();
- monitorExitBlock.append(InstructionFactory.createLoad(enclosingClassType, slotForLockObject));
- monitorExitBlock.append(InstructionConstants.MONITOREXIT);
- // monitorExitBlock.append(Utility.copyInstruction(element
- // .getInstruction()));
- // element.setInstruction(InstructionFactory.createLoad(
- // classType,slotForThis));
- InstructionHandle monitorExitBlockStart = body.insert(element, monitorExitBlock);
-
- // now move the targeters from the RET to the start of
- // the monitorexit block
- for (InstructionTargeter targeter : element.getTargetersCopy()) {
- // what kinds are there?
- if (targeter instanceof LocalVariableTag) {
- // 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 InstructionBranch) {
- // move it
- targeter.updateTarget(element, monitorExitBlockStart);
- } else {
- throw new BCException("Unexpected targeter encountered during transform: " + targeter);
- }
- }
- }
- }
-
- // now the magic, putting the finally block around the code
- InstructionHandle finallyStart = finallyBlock.getStart();
-
- InstructionHandle tryPosition = body.getStart();
- InstructionHandle catchPosition = body.getEnd();
- body.insert(body.getStart(), prepend); // now we can put the
- // monitorenter stuff on
- synchronizedMethod.getBody().append(finallyBlock);
- synchronizedMethod.addExceptionHandler(tryPosition, catchPosition, finallyStart, null/* ==finally */, false);
- synchronizedMethod.addExceptionHandler(finallyStart, finallyStart.getNext(), finallyStart, null, false);
- } else {
-
- // TRANSFORMING STATIC METHOD ON PRE JAVA5
-
- // Hideous nightmare, class literal references prior to Java5
-
- // YIKES! this is just the code for MONITORENTER !
- // 0: getstatic #59; //Field class$1:Ljava/lang/Class;
- // 3: dup
- // 4: ifnonnull 32
- // 7: pop
- // try
- // 8: ldc #61; //String java.lang.String
- // 10: invokestatic #44; //Method
- // java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
- // 13: dup
- // catch
- // 14: putstatic #59; //Field class$1:Ljava/lang/Class;
- // 17: goto 32
- // 20: new #46; //class java/lang/NoClassDefFoundError
- // 23: dup_x1
- // 24: swap
- // 25: invokevirtual #52; //Method
- // java/lang/Throwable.getMessage:()Ljava/lang/String;
- // 28: invokespecial #54; //Method
- // java/lang/NoClassDefFoundError."<init>":(Ljava/lang/String;)V
- // 31: athrow
- // 32: dup <-- partTwo (branch target)
- // 33: astore_0
- // 34: monitorenter
- //
- // plus exceptiontable entry!
- // 8 13 20 Class java/lang/ClassNotFoundException
- Type classType = BcelWorld.makeBcelType(synchronizedMethod.getEnclosingClass().getType());
- Type clazzType = Type.getType(Class.class);
-
- InstructionList parttwo = new InstructionList();
- parttwo.append(InstructionFactory.createDup(1));
- int slotForThis = synchronizedMethod.allocateLocal(classType);
- parttwo.append(InstructionFactory.createStore(clazzType, slotForThis)); // ? should be the real type ? String or
- // something?
- parttwo.append(InstructionFactory.MONITORENTER);
-
- String fieldname = synchronizedMethod.getEnclosingClass().allocateField("class$");
- FieldGen f = new FieldGen(Modifier.STATIC | Modifier.PRIVATE, Type.getType(Class.class), fieldname,
- synchronizedMethod.getEnclosingClass().getConstantPool());
- synchronizedMethod.getEnclosingClass().addField(f, null);
-
- // 10: invokestatic #44; //Method
- // java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
- // 13: dup
- // 14: putstatic #59; //Field class$1:Ljava/lang/Class;
- // 17: goto 32
- // 20: new #46; //class java/lang/NoClassDefFoundError
- // 23: dup_x1
- // 24: swap
- // 25: invokevirtual #52; //Method
- // java/lang/Throwable.getMessage:()Ljava/lang/String;
- // 28: invokespecial #54; //Method
- // java/lang/NoClassDefFoundError."<init>":(Ljava/lang/String;)V
- // 31: athrow
- String name = synchronizedMethod.getEnclosingClass().getName();
-
- prepend.append(fact.createGetStatic(name, fieldname, Type.getType(Class.class)));
- prepend.append(InstructionFactory.createDup(1));
- prepend.append(InstructionFactory.createBranchInstruction(Constants.IFNONNULL, parttwo.getStart()));
- prepend.append(InstructionFactory.POP);
-
- prepend.append(fact.createConstant(name));
- InstructionHandle tryInstruction = prepend.getEnd();
- prepend.append(fact.createInvoke("java.lang.Class", "forName", clazzType,
- new Type[] { Type.getType(String.class) }, Constants.INVOKESTATIC));
- InstructionHandle catchInstruction = prepend.getEnd();
- prepend.append(InstructionFactory.createDup(1));
-
- prepend.append(fact.createPutStatic(synchronizedMethod.getEnclosingClass().getType().getName(), fieldname,
- Type.getType(Class.class)));
- prepend.append(InstructionFactory.createBranchInstruction(Constants.GOTO, parttwo.getStart()));
-
- // start of catch block
- InstructionList catchBlockForLiteralLoadingFail = new InstructionList();
- catchBlockForLiteralLoadingFail.append(fact.createNew((ObjectType) Type.getType(NoClassDefFoundError.class)));
- catchBlockForLiteralLoadingFail.append(InstructionFactory.createDup_1(1));
- catchBlockForLiteralLoadingFail.append(InstructionFactory.SWAP);
- catchBlockForLiteralLoadingFail.append(fact.createInvoke("java.lang.Throwable", "getMessage",
- Type.getType(String.class), new Type[] {}, Constants.INVOKEVIRTUAL));
- catchBlockForLiteralLoadingFail.append(fact.createInvoke("java.lang.NoClassDefFoundError", "<init>", Type.VOID,
- new Type[] { Type.getType(String.class) }, Constants.INVOKESPECIAL));
- catchBlockForLiteralLoadingFail.append(InstructionFactory.ATHROW);
- InstructionHandle catchBlockStart = catchBlockForLiteralLoadingFail.getStart();
- prepend.append(catchBlockForLiteralLoadingFail);
- prepend.append(parttwo);
- // MONITORENTER
- // pseudocode: load up 'this' (var0), dup it, store it in a new
- // local var (for use with monitorexit) and call
- // monitorenter:
- // ALOAD_0, DUP, ASTORE_<n>, MONITORENTER
- // prepend.append(InstructionFactory.createLoad(classType,0));
- // prepend.append(InstructionFactory.createDup(1));
- // int slotForThis =
- // synchronizedMethod.allocateLocal(classType);
- // prepend.append(InstructionFactory.createStore(classType,
- // slotForThis));
- // prepend.append(InstructionFactory.MONITORENTER);
-
- // MONITOREXIT
- // here be dragons
-
- // We basically need to wrap the code from the method in a
- // finally block that
- // will ensure monitorexit is called. Content on the finally
- // block seems to
- // be always:
- //
- // E1: ALOAD_1
- // MONITOREXIT
- // ATHROW
- //
- // so lets build that:
- InstructionList finallyBlock = new InstructionList();
- finallyBlock.append(InstructionFactory.createLoad(Type.getType(java.lang.Class.class), slotForThis));
- finallyBlock.append(InstructionConstants.MONITOREXIT);
- finallyBlock.append(InstructionConstants.ATHROW);
-
- // finally -> E1
- // | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line
- // 21)
- // | LDC "hello"
- // | INVOKEVIRTUAL java.io.PrintStream.println
- // (Ljava/lang/String;)V
- // | ALOAD_1 (line 20)
- // | MONITOREXIT
- // finally -> E1
- // GOTO L0
- // finally -> E1
- // | E1: ALOAD_1
- // | MONITOREXIT
- // finally -> E1
- // ATHROW
- // L0: RETURN (line 23)
- // frameEnv.put(donorFramePos, thisSlot);
-
- // search for 'returns' and make them to the
- // aload_<n>,monitorexit
- InstructionHandle walker = body.getStart();
- List<InstructionHandle> rets = new ArrayList<InstructionHandle>();
- while (walker != null) { // !walker.equals(body.getEnd())) {
- if (walker.getInstruction().isReturnInstruction()) {
- rets.add(walker);
- }
- walker = walker.getNext();
- }
- if (rets.size() > 0) {
- // need to ensure targeters for 'return' now instead target
- // the load instruction
- // (so we never jump over the monitorexit logic)
-
- for (InstructionHandle ret : rets) {
- // System.err.println("Adding monitor exit block at "+
- // element);
- InstructionList monitorExitBlock = new InstructionList();
- monitorExitBlock.append(InstructionFactory.createLoad(classType, slotForThis));
- monitorExitBlock.append(InstructionConstants.MONITOREXIT);
- // monitorExitBlock.append(Utility.copyInstruction(element
- // .getInstruction()));
- // element.setInstruction(InstructionFactory.createLoad(
- // classType,slotForThis));
- InstructionHandle monitorExitBlockStart = body.insert(ret, monitorExitBlock);
-
- // now move the targeters from the RET to the start of
- // the monitorexit block
- for (InstructionTargeter targeter : ret.getTargetersCopy()) {
- // what kinds are there?
- if (targeter instanceof LocalVariableTag) {
- // 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 InstructionBranch) {
- // move it
- targeter.updateTarget(ret, monitorExitBlockStart);
- } else {
- throw new BCException("Unexpected targeter encountered during transform: " + targeter);
- }
- }
- }
- }
- // body =
- // rewriteWithMonitorExitCalls(body,fact,true,slotForThis,
- // classType);
- // synchronizedMethod.setBody(body);
-
- // now the magic, putting the finally block around the code
- InstructionHandle finallyStart = finallyBlock.getStart();
-
- InstructionHandle tryPosition = body.getStart();
- InstructionHandle catchPosition = body.getEnd();
- body.insert(body.getStart(), prepend); // now we can put the
- // monitorenter stuff on
-
- synchronizedMethod.getBody().append(finallyBlock);
- synchronizedMethod.addExceptionHandler(tryPosition, catchPosition, finallyStart, null/* ==finally */, false);
- synchronizedMethod.addExceptionHandler(tryInstruction, catchInstruction, catchBlockStart,
- (ObjectType) Type.getType(ClassNotFoundException.class), true);
- synchronizedMethod.addExceptionHandler(finallyStart, finallyStart.getNext(), finallyStart, null, false);
- }
- } else {
-
- // TRANSFORMING NON STATIC METHOD
- Type classType = BcelWorld.makeBcelType(synchronizedMethod.getEnclosingClass().getType());
- // MONITORENTER
- // pseudocode: load up 'this' (var0), dup it, store it in a new
- // local var (for use with monitorexit) and call
- // monitorenter:
- // ALOAD_0, DUP, ASTORE_<n>, MONITORENTER
- prepend.append(InstructionFactory.createLoad(classType, 0));
- prepend.append(InstructionFactory.createDup(1));
- int slotForThis = synchronizedMethod.allocateLocal(classType);
- prepend.append(InstructionFactory.createStore(classType, slotForThis));
- prepend.append(InstructionFactory.MONITORENTER);
- // body.insert(body.getStart(),prepend);
-
- // MONITOREXIT
-
- // We basically need to wrap the code from the method in a finally
- // block that
- // will ensure monitorexit is called. Content on the finally block
- // seems to
- // be always:
- //
- // E1: ALOAD_1
- // MONITOREXIT
- // ATHROW
- //
- // so lets build that:
- InstructionList finallyBlock = new InstructionList();
- finallyBlock.append(InstructionFactory.createLoad(classType, slotForThis));
- finallyBlock.append(InstructionConstants.MONITOREXIT);
- finallyBlock.append(InstructionConstants.ATHROW);
-
- // finally -> E1
- // | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 21)
- // | LDC "hello"
- // | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
- // | ALOAD_1 (line 20)
- // | MONITOREXIT
- // finally -> E1
- // GOTO L0
- // finally -> E1
- // | E1: ALOAD_1
- // | MONITOREXIT
- // finally -> E1
- // ATHROW
- // L0: RETURN (line 23)
- // frameEnv.put(donorFramePos, thisSlot);
-
- // search for 'returns' and make them to the aload_<n>,monitorexit
- InstructionHandle walker = body.getStart();
- List<InstructionHandle> rets = new ArrayList<InstructionHandle>();
- while (walker != null) { // !walker.equals(body.getEnd())) {
- if (walker.getInstruction().isReturnInstruction()) {
- rets.add(walker);
- }
- walker = walker.getNext();
- }
- if (!rets.isEmpty()) {
- // need to ensure targeters for 'return' now instead target the
- // load instruction
- // (so we never jump over the monitorexit logic)
-
- for (Iterator<InstructionHandle> iter = rets.iterator(); iter.hasNext();) {
- InstructionHandle element = iter.next();
- // System.err.println("Adding monitor exit block at "+element
- // );
- InstructionList monitorExitBlock = new InstructionList();
- monitorExitBlock.append(InstructionFactory.createLoad(classType, slotForThis));
- monitorExitBlock.append(InstructionConstants.MONITOREXIT);
- // monitorExitBlock.append(Utility.copyInstruction(element.
- // getInstruction()));
- // element.setInstruction(InstructionFactory.createLoad(
- // classType,slotForThis));
- InstructionHandle monitorExitBlockStart = body.insert(element, monitorExitBlock);
-
- // now move the targeters from the RET to the start of the
- // monitorexit block
- for (InstructionTargeter targeter : element.getTargetersCopy()) {
- // what kinds are there?
- if (targeter instanceof LocalVariableTag) {
- // 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 InstructionBranch) {
- // move it
- targeter.updateTarget(element, monitorExitBlockStart);
- } else {
- throw new BCException("Unexpected targeter encountered during transform: " + targeter);
- }
- }
- }
- }
-
- // now the magic, putting the finally block around the code
- InstructionHandle finallyStart = finallyBlock.getStart();
-
- InstructionHandle tryPosition = body.getStart();
- InstructionHandle catchPosition = body.getEnd();
- body.insert(body.getStart(), prepend); // now we can put the
- // monitorenter stuff on
- synchronizedMethod.getBody().append(finallyBlock);
- synchronizedMethod.addExceptionHandler(tryPosition, catchPosition, finallyStart, null/* ==finally */, false);
- synchronizedMethod.addExceptionHandler(finallyStart, finallyStart.getNext(), finallyStart, null, false);
- // also the exception handling for the finally block jumps to itself
-
- // max locals will already have been modified in the allocateLocal()
- // call
-
- // synchronized bit is removed on LazyMethodGen.pack()
- }
-
- // gonna have to go through and change all aload_0s to load the var from
- // a variable,
- // going to add a new variable for the this var
-
- if (trace.isTraceEnabled()) {
- trace.exit("transformSynchronizedMethod");
- }
- }
-
- /**
- * generate the instructions to be inlined.
- *
- * @param donor the method from which we will copy (and adjust frame and jumps) instructions.
- * @param recipient the method the instructions will go into. Used to get the frame size so we can allocate new frame locations
- * for locals in donor.
- * @param frameEnv an environment to map from donor frame to recipient frame, initially populated with argument locations.
- * @param fact an instruction factory for recipient
- */
- static InstructionList genInlineInstructions(LazyMethodGen donor, LazyMethodGen recipient, IntMap frameEnv,
- InstructionFactory fact, boolean keepReturns) {
- InstructionList footer = new InstructionList();
- InstructionHandle end = footer.append(InstructionConstants.NOP);
-
- InstructionList ret = new InstructionList();
- InstructionList sourceList = donor.getBody();
-
- Map<InstructionHandle, InstructionHandle> srcToDest = new HashMap<InstructionHandle, InstructionHandle>();
- ConstantPool donorCpg = donor.getEnclosingClass().getConstantPool();
- ConstantPool recipientCpg = recipient.getEnclosingClass().getConstantPool();
-
- boolean isAcrossClass = donorCpg != recipientCpg;
- BootstrapMethods bootstrapMethods = null;
- // first pass: copy the instructions directly, populate the srcToDest
- // map,
- // fix frame instructions
- for (InstructionHandle src = sourceList.getStart(); src != null; src = src.getNext()) {
- 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.
- if (isAcrossClass) {
- InstructionCP cpi = (InstructionCP) fresh;
- cpi.setIndex(recipientCpg.addConstant(donorCpg.getConstant(cpi.getIndex()), donorCpg));
- }
- // May need to copy bootstrapmethods across too.
-// if (fresh instanceof InvokeDynamic) {
-// InvokeDynamic id = (InvokeDynamic)fresh;
-// ConstantInvokeDynamic cid = (ConstantInvokeDynamic)donorCpg.getConstant(src.getInstruction().getIndex());
-// int bmaIndex = cid.getBootstrapMethodAttrIndex();
-// if (bootstrapMethods == null) {
-// Collection<Attribute> attributes = donor.getEnclosingClass().getAttributes();
-// if (attributes != null) {
-// for (Attribute attribute: attributes) {
-// if (attribute instanceof BootstrapMethods) {
-// bootstrapMethods = (BootstrapMethods)attribute;
-// }
-// }
-// }
-// BootstrapMethods.BootstrapMethod bootstrapMethod =
-// bootstrapMethods.getBootstrapMethods()[bmaIndex];
-// ConstantMethodHandle methodhandle = (ConstantMethodHandle)donorCpg.getConstant(bootstrapMethod.getBootstrapMethodRef());
-// int bootstrapMethodArguments[] = bootstrapMethod.getBootstrapArguments();
-//
-// // Finally have all we need to build the new one...
-//
-// int newMethodHandleIndex = recipientCpg.addConstant(methodhandle, donorCpg);
-// int[] newMethodArguments = new int[bootstrapMethodArguments.length];
-// for (int a=0; a<bootstrapMethodArguments.length; a++) {
-// newMethodArguments[a] = recipientCpg.addConstant(donorCpg.getConstant(bootstrapMethodArguments[a]),donorCpg);
-// }
-// BootstrapMethods.BootstrapMethod newBootstrapMethod =
-// new BootstrapMethods.BootstrapMethod(newMethodHandleIndex,newMethodArguments);
-//
-// Collection<Attribute> newAttributes = recipient.getEnclosingClass().getAttributes();
-// BootstrapMethods newBootstrapMethods = null;
-// for (Attribute attr: newAttributes) {
-// if (attr instanceof BootstrapMethods) {
-// newBootstrapMethods = (BootstrapMethods)newBootstrapMethods;
-// }
-// }
-// if (newBootstrapMethods == null) {
-// newBootstrapMethods =
-// new BootstrapMethods(recipientCpg.addUtf8("BootstrapMethods"),
-// 2+newBootstrapMethod.getLength(),
-// new BootstrapMethods.BootstrapMethod[] {newBootstrapMethod},
-// recipientCpg);
-// recipient.getEnclosingClass().addAttribute(newBootstrapMethods);
-// }
-// TODO need to copy over lambda$0 support methods too...
-// }
-//
-// }
- }
- if (src.getInstruction() == Range.RANGEINSTRUCTION) {
- dest = ret.append(Range.RANGEINSTRUCTION);
- } else if (fresh.isReturnInstruction()) {
- if (keepReturns) {
- dest = ret.append(fresh);
- } else {
- dest = ret.append(InstructionFactory.createBranchInstruction(Constants.GOTO, end));
- }
- } else if (fresh instanceof InstructionBranch) {
- dest = ret.append((InstructionBranch) fresh);
- } else if (fresh.isLocalVariableInstruction() || fresh instanceof RET) {
-
- // IndexedInstruction indexed = (IndexedInstruction) fresh;
- int oldIndex = fresh.getIndex();
- int freshIndex;
- if (!frameEnv.hasKey(oldIndex)) {
- freshIndex = recipient.allocateLocal(2);
- frameEnv.put(oldIndex, freshIndex);
- } else {
- freshIndex = frameEnv.get(oldIndex);
- }
- if (fresh instanceof RET) {
- fresh.setIndex(freshIndex);
- } else {
- fresh = ((InstructionLV) fresh).setIndexAndCopyIfNecessary(freshIndex);
- }
- dest = ret.append(fresh);
- } else {
- dest = ret.append(fresh);
- }
- srcToDest.put(src, dest);
- }
-
- // second pass: retarget branch instructions, copy ranges and tags
- Map<Tag, Tag> tagMap = new HashMap<Tag, Tag>();
- Map<BcelShadow, BcelShadow> shadowMap = new HashMap<BcelShadow, BcelShadow>();
- for (InstructionHandle dest = ret.getStart(), src = sourceList.getStart(); dest != null; dest = dest.getNext(), src = src
- .getNext()) {
- Instruction inst = dest.getInstruction();
-
- // retarget branches
- if (inst instanceof InstructionBranch) {
- InstructionBranch branch = (InstructionBranch) inst;
- InstructionHandle oldTarget = branch.getTarget();
- InstructionHandle newTarget = srcToDest.get(oldTarget);
- if (newTarget == null) {
- // assert this is a GOTO
- // this was a return instruction we previously replaced
- } else {
- branch.setTarget(newTarget);
- if (branch instanceof InstructionSelect) {
- InstructionSelect select = (InstructionSelect) branch;
- InstructionHandle[] oldTargets = select.getTargets();
- for (int k = oldTargets.length - 1; k >= 0; k--) {
- select.setTarget(k, srcToDest.get(oldTargets[k]));
- }
- }
- }
- }
-
- // copy over tags and range attributes
-
- Iterator<InstructionTargeter> tIter = src.getTargeters().iterator();
- while (tIter.hasNext()) {
- InstructionTargeter old = tIter.next();
- if (old instanceof Tag) {
- Tag oldTag = (Tag) old;
- Tag fresh = tagMap.get(oldTag);
- if (fresh == null) {
- fresh = oldTag.copy();
- if (old instanceof LocalVariableTag) {
- // LocalVariable
- LocalVariableTag lvTag = (LocalVariableTag) old;
- LocalVariableTag lvTagFresh = (LocalVariableTag) fresh;
- if (lvTag.getSlot() == 0) {
- fresh = new LocalVariableTag(lvTag.getRealType().getSignature(), "ajc$aspectInstance",
- frameEnv.get(lvTag.getSlot()), 0);
- } else {
- // // Do not move it - when copying the code from the aspect to the affected target, 'this' is
- // // going to change from aspect to affected type. So just fix the type
- // System.out.println("For local variable tag at instruction " + src + " changing slot from "
- // + lvTag.getSlot() + " > " + frameEnv.get(lvTag.getSlot()));
- lvTagFresh.updateSlot(frameEnv.get(lvTag.getSlot()));
- }
- }
- tagMap.put(oldTag, fresh);
- }
- dest.addTargeter(fresh);
- } else if (old instanceof ExceptionRange) {
- ExceptionRange er = (ExceptionRange) old;
- if (er.getStart() == src) {
- ExceptionRange freshEr = new ExceptionRange(recipient.getBody(), er.getCatchType(), er.getPriority());
- freshEr.associateWithTargets(dest, srcToDest.get(er.getEnd()), srcToDest.get(er.getHandler()));
- }
- } else if (old instanceof ShadowRange) {
- ShadowRange oldRange = (ShadowRange) old;
- if (oldRange.getStart() == src) {
- BcelShadow oldShadow = oldRange.getShadow();
- BcelShadow freshEnclosing = oldShadow.getEnclosingShadow() == null ? null : (BcelShadow) shadowMap
- .get(oldShadow.getEnclosingShadow());
- BcelShadow freshShadow = oldShadow.copyInto(recipient, freshEnclosing);
- ShadowRange freshRange = new ShadowRange(recipient.getBody());
- freshRange.associateWithShadow(freshShadow);
- freshRange.associateWithTargets(dest, srcToDest.get(oldRange.getEnd()));
- shadowMap.put(oldShadow, freshShadow); // oldRange, freshRange
- // recipient.matchedShadows.add(freshShadow);
- // XXX should go through the NEW copied shadow and
- // update
- // the thisVar, targetVar, and argsVar
- // ??? Might want to also go through at this time and
- // add
- // "extra" vars to the shadow.
- }
- }
- }
- }
- if (!keepReturns) {
- ret.append(footer);
- }
- return ret;
- }
-
- // static InstructionList rewriteWithMonitorExitCalls(InstructionList
- // sourceList,InstructionFactory fact,boolean keepReturns,int
- // monitorVarSlot,Type monitorVarType)
- // {
- // InstructionList footer = new InstructionList();
- // InstructionHandle end = footer.append(InstructionConstants.NOP);
- //
- // InstructionList newList = new InstructionList();
- //
- // Map srcToDest = new HashMap();
- //
- // // first pass: copy the instructions directly, populate the srcToDest
- // map,
- // // fix frame instructions
- // for (InstructionHandle src = sourceList.getStart(); src != null; src =
- // src.getNext()) {
- // Instruction fresh = Utility.copyInstruction(src.getInstruction());
- // InstructionHandle dest;
- // if (src.getInstruction() == Range.RANGEINSTRUCTION) {
- // dest = newList.append(Range.RANGEINSTRUCTION);
- // } else if (fresh.isReturnInstruction()) {
- // if (keepReturns) {
- // newList.append(InstructionFactory.createLoad(monitorVarType,monitorVarSlot
- // ));
- // newList.append(InstructionConstants.MONITOREXIT);
- // dest = newList.append(fresh);
- // } else {
- // dest =
- // newList.append(InstructionFactory.createBranchInstruction(Constants.GOTO,
- // end));
- // }
- // } else if (fresh instanceof InstructionBranch) {
- // dest = newList.append((InstructionBranch) fresh);
- // } else if (
- // fresh.isLocalVariableInstruction() || fresh instanceof RET) {
- // //IndexedInstruction indexed = (IndexedInstruction) fresh;
- // int oldIndex = fresh.getIndex();
- // int freshIndex;
- // // if (!frameEnv.hasKey(oldIndex)) {
- // // freshIndex = recipient.allocateLocal(2);
- // // frameEnv.put(oldIndex, freshIndex);
- // // } else {
- // freshIndex = oldIndex;//frameEnv.get(oldIndex);
- // // }
- // if (fresh instanceof RET) {
- // fresh.setIndex(freshIndex);
- // } else {
- // fresh = ((InstructionLV)fresh).setIndexAndCopyIfNecessary(freshIndex);
- // }
- // dest = newList.append(fresh);
- // } else {
- // dest = newList.append(fresh);
- // }
- // srcToDest.put(src, dest);
- // }
- //
- // // second pass: retarget branch instructions, copy ranges and tags
- // Map tagMap = new HashMap();
- // for (InstructionHandle dest = newList.getStart(), src =
- // sourceList.getStart();
- // dest != null;
- // dest = dest.getNext(), src = src.getNext()) {
- // Instruction inst = dest.getInstruction();
- //
- // // retarget branches
- // if (inst instanceof InstructionBranch) {
- // InstructionBranch branch = (InstructionBranch) inst;
- // InstructionHandle oldTarget = branch.getTarget();
- // InstructionHandle newTarget =
- // (InstructionHandle) srcToDest.get(oldTarget);
- // if (newTarget == null) {
- // // assert this is a GOTO
- // // this was a return instruction we previously replaced
- // } else {
- // branch.setTarget(newTarget);
- // if (branch instanceof InstructionSelect) {
- // InstructionSelect select = (InstructionSelect) branch;
- // InstructionHandle[] oldTargets = select.getTargets();
- // for (int k = oldTargets.length - 1; k >= 0; k--) {
- // select.setTarget(
- // k,
- // (InstructionHandle) srcToDest.get(oldTargets[k]));
- // }
- // }
- // }
- // }
- //
- // //copy over tags and range attributes
- // Iterator tIter = src.getTargeters().iterator();
- //
- // while (tIter.hasNext()) {
- // InstructionTargeter old = (InstructionTargeter)tIter.next();
- // if (old instanceof Tag) {
- // Tag oldTag = (Tag) old;
- // Tag fresh = (Tag) tagMap.get(oldTag);
- // if (fresh == null) {
- // fresh = oldTag.copy();
- // tagMap.put(oldTag, fresh);
- // }
- // dest.addTargeter(fresh);
- // } else if (old instanceof ExceptionRange) {
- // ExceptionRange er = (ExceptionRange) old;
- // if (er.getStart() == src) {
- // ExceptionRange freshEr =
- // new ExceptionRange(newList/*recipient.getBody()*/,er.getCatchType(),er.
- // getPriority());
- // freshEr.associateWithTargets(
- // dest,
- // (InstructionHandle)srcToDest.get(er.getEnd()),
- // (InstructionHandle)srcToDest.get(er.getHandler()));
- // }
- // }
- // /*else if (old instanceof ShadowRange) {
- // ShadowRange oldRange = (ShadowRange) old;
- // if (oldRange.getStart() == src) {
- // BcelShadow oldShadow = oldRange.getShadow();
- // BcelShadow freshEnclosing =
- // oldShadow.getEnclosingShadow() == null
- // ? null
- // : (BcelShadow) shadowMap.get(oldShadow.getEnclosingShadow());
- // BcelShadow freshShadow =
- // oldShadow.copyInto(recipient, freshEnclosing);
- // ShadowRange freshRange = new ShadowRange(recipient.getBody());
- // freshRange.associateWithShadow(freshShadow);
- // freshRange.associateWithTargets(
- // dest,
- // (InstructionHandle) srcToDest.get(oldRange.getEnd()));
- // shadowMap.put(oldRange, freshRange);
- // //recipient.matchedShadows.add(freshShadow);
- // // XXX should go through the NEW copied shadow and update
- // // the thisVar, targetVar, and argsVar
- // // ??? Might want to also go through at this time and add
- // // "extra" vars to the shadow.
- // }
- // }*/
- // }
- // }
- // if (!keepReturns) newList.append(footer);
- // return newList;
- // }
-
- /**
- * generate the argument stores in preparation for inlining.
- *
- * @param donor the method we will inline from. Used to get the signature.
- * @param recipient the method we will inline into. Used to get the frame size so we can allocate fresh locations.
- * @param frameEnv an empty environment we populate with a map from donor frame to recipient frame.
- * @param fact an instruction factory for recipient
- */
- private static InstructionList genArgumentStores(LazyMethodGen donor, LazyMethodGen recipient, IntMap frameEnv,
- InstructionFactory fact) {
- InstructionList ret = new InstructionList();
-
- int donorFramePos = 0;
-
- // writing ret back to front because we're popping.
- if (!donor.isStatic()) {
- int targetSlot = recipient.allocateLocal(Type.OBJECT);
- ret.insert(InstructionFactory.createStore(Type.OBJECT, targetSlot));
- frameEnv.put(donorFramePos, targetSlot);
- donorFramePos += 1;
- }
- Type[] argTypes = donor.getArgumentTypes();
- for (int i = 0, len = argTypes.length; i < len; i++) {
- Type argType = argTypes[i];
- int argSlot = recipient.allocateLocal(argType);
- ret.insert(InstructionFactory.createStore(argType, argSlot));
- frameEnv.put(donorFramePos, argSlot);
- donorFramePos += argType.getSize();
- }
- return ret;
- }
-
- /**
- * get a called method: Assumes the called method is in this class, and the reference to it is exact (a la INVOKESPECIAL).
- *
- * @param ih The InvokeInstruction instructionHandle pointing to the called method.
- */
- private LazyMethodGen getCalledMethod(InstructionHandle ih) {
- InvokeInstruction inst = (InvokeInstruction) ih.getInstruction();
-
- String methodName = inst.getName(cpg);
- String signature = inst.getSignature(cpg);
-
- return clazz.getLazyMethodGen(methodName, signature);
- }
-
- private void weaveInAddedMethods() {
- Collections.sort(addedLazyMethodGens, new Comparator<LazyMethodGen>() {
- public int compare(LazyMethodGen aa, LazyMethodGen bb) {
- int i = aa.getName().compareTo(bb.getName());
- if (i != 0) {
- return i;
- }
- return aa.getSignature().compareTo(bb.getSignature());
- }
- });
-
- for (LazyMethodGen addedMember : addedLazyMethodGens) {
- clazz.addMethodGen(addedMember);
- }
- }
-
- // void addPerSingletonField(Member field) {
- // ObjectType aspectType = (ObjectType)
- // BcelWorld.makeBcelType(field.getReturnType());
- // String aspectName = field.getReturnType().getName();
- //
- // LazyMethodGen clinit = clazz.getStaticInitializer();
- // InstructionList setup = new InstructionList();
- // InstructionFactory fact = clazz.getFactory();
- //
- // setup.append(fact.createNew(aspectType));
- // setup.append(InstructionFactory.createDup(1));
- // setup.append(fact.createInvoke(aspectName, "<init>", Type.VOID, new
- // Type[0], Constants.INVOKESPECIAL));
- // setup.append(fact.createFieldAccess(aspectName, field.getName(),
- // aspectType, Constants.PUTSTATIC));
- // clinit.getBody().insert(setup);
- // }
-
- /**
- * Returns null if this is not a Java constructor, and then we won't weave into it at all
- */
- private InstructionHandle findSuperOrThisCall(LazyMethodGen mg) {
- int depth = 1;
- InstructionHandle start = mg.getBody().getStart();
- while (true) {
- if (start == null) {
- return null;
- }
-
- Instruction inst = start.getInstruction();
- if (inst.opcode == Constants.INVOKESPECIAL && ((InvokeInstruction) inst).getName(cpg).equals("<init>")) {
- depth--;
- if (depth == 0) {
- return start;
- }
- } else if (inst.opcode == Constants.NEW) {
- depth++;
- }
- start = start.getNext();
- }
- }
-
- // ----
-
- private boolean match(LazyMethodGen mg) {
- BcelShadow enclosingShadow;
- List<BcelShadow> shadowAccumulator = new ArrayList<BcelShadow>();
- boolean isOverweaving = world.isOverWeaving();
- boolean startsAngly = mg.getName().charAt(0) == '<';
- // we want to match ajsynthetic constructors...
- if (startsAngly && mg.getName().equals("<init>")) {
- return matchInit(mg, shadowAccumulator);
- } else if (!shouldWeaveBody(mg)) {
- return false;
- } else {
- if (startsAngly && mg.getName().equals("<clinit>")) {
- // clinitShadow =
- enclosingShadow = BcelShadow.makeStaticInitialization(world, mg);
- // System.err.println(enclosingShadow);
- } else if (mg.isAdviceMethod()) {
- enclosingShadow = BcelShadow.makeAdviceExecution(world, mg);
- } else {
- AjAttribute.EffectiveSignatureAttribute effective = mg.getEffectiveSignature();
- if (effective == null) {
- // Don't want ajc$preClinit to be considered for matching
- if (isOverweaving && mg.getName().startsWith(NameMangler.PREFIX)) {
- return false;
- }
- enclosingShadow = BcelShadow.makeMethodExecution(world, mg, !canMatchBodyShadows);
- } else if (effective.isWeaveBody()) {
- ResolvedMember rm = effective.getEffectiveSignature();
-
- // Annotations for things with effective signatures are
- // never stored in the effective
- // signature itself - we have to hunt for them. Storing them
- // in the effective signature
- // would mean keeping two sets up to date (no way!!)
-
- fixParameterNamesForResolvedMember(rm, mg.getMemberView());
- fixAnnotationsForResolvedMember(rm, mg.getMemberView());
-
- enclosingShadow = BcelShadow.makeShadowForMethod(world, mg, effective.getShadowKind(), rm);
- } else {
- return false;
- }
- }
-
- if (canMatchBodyShadows) {
- for (InstructionHandle h = mg.getBody().getStart(); h != null; h = h.getNext()) {
- match(mg, h, enclosingShadow, shadowAccumulator);
- }
- }
- // FIXME asc change from string match if we can, rather brittle.
- // this check actually prevents field-exec jps
- if (canMatch(enclosingShadow.getKind())
- && !(mg.getName().charAt(0) == 'a' && mg.getName().startsWith("ajc$interFieldInit"))) {
- if (match(enclosingShadow, shadowAccumulator)) {
- enclosingShadow.init();
- }
- }
- mg.matchedShadows = shadowAccumulator;
- return !shadowAccumulator.isEmpty();
- }
- }
-
- private boolean matchInit(LazyMethodGen mg, List<BcelShadow> shadowAccumulator) {
- BcelShadow enclosingShadow;
- // XXX the enclosing join point is wrong for things before ignoreMe.
- InstructionHandle superOrThisCall = findSuperOrThisCall(mg);
-
- // we don't walk bodies of things where it's a wrong constructor thingie
- if (superOrThisCall == null) {
- return false;
- }
-
- enclosingShadow = BcelShadow.makeConstructorExecution(world, mg, superOrThisCall);
- if (mg.getEffectiveSignature() != null) {
- enclosingShadow.setMatchingSignature(mg.getEffectiveSignature().getEffectiveSignature());
- }
-
- // walk the body
- boolean beforeSuperOrThisCall = true;
- if (shouldWeaveBody(mg)) {
- if (canMatchBodyShadows) {
- for (InstructionHandle h = mg.getBody().getStart(); h != null; h = h.getNext()) {
- if (h == superOrThisCall) {
- beforeSuperOrThisCall = false;
- continue;
- }
- match(mg, h, beforeSuperOrThisCall ? null : enclosingShadow, shadowAccumulator);
- }
- }
- if (canMatch(Shadow.ConstructorExecution)) {
- match(enclosingShadow, shadowAccumulator);
- }
- }
-
- // XXX we don't do pre-inits of interfaces
-
- // now add interface inits
- if (!isThisCall(superOrThisCall)) {
- InstructionHandle curr = enclosingShadow.getRange().getStart();
- for (Iterator<IfaceInitList> i = addedSuperInitializersAsList.iterator(); i.hasNext();) {
- IfaceInitList l = i.next();
-
- Member ifaceInitSig = AjcMemberMaker.interfaceConstructor(l.onType);
-
- BcelShadow initShadow = BcelShadow.makeIfaceInitialization(world, mg, ifaceInitSig);
-
- // insert code in place
- InstructionList inits = genInitInstructions(l.list, false);
- if (match(initShadow, shadowAccumulator) || !inits.isEmpty()) {
- initShadow.initIfaceInitializer(curr);
- initShadow.getRange().insert(inits, Range.OutsideBefore);
- }
- }
-
- // now we add our initialization code
- InstructionList inits = genInitInstructions(addedThisInitializers, false);
- enclosingShadow.getRange().insert(inits, Range.OutsideBefore);
- }
-
- // actually, you only need to inline the self constructors that are
- // in a particular group (partition the constructors into groups where
- // members
- // call or are called only by those in the group). Then only inline
- // constructors
- // in groups where at least one initialization jp matched. Future work.
- boolean addedInitialization = match(BcelShadow.makeUnfinishedInitialization(world, mg), initializationShadows);
- addedInitialization |= match(BcelShadow.makeUnfinishedPreinitialization(world, mg), initializationShadows);
- mg.matchedShadows = shadowAccumulator;
- return addedInitialization || !shadowAccumulator.isEmpty();
- }
-
- private boolean shouldWeaveBody(LazyMethodGen mg) {
- if (mg.isBridgeMethod()) {
- return false;
- }
- if (mg.isAjSynthetic()) {
- return mg.getName().equals("<clinit>");
- }
- AjAttribute.EffectiveSignatureAttribute a = mg.getEffectiveSignature();
- if (a != null) {
- return a.isWeaveBody();
- }
- return true;
- }
-
- /**
- * first sorts the mungers, then gens the initializers in the right order
- */
- private InstructionList genInitInstructions(List<ConcreteTypeMunger> list, boolean isStatic) {
- list = PartialOrder.sort(list);
- if (list == null) {
- throw new BCException("circularity in inter-types");
- }
-
- InstructionList ret = new InstructionList();
-
- for (ConcreteTypeMunger cmunger : list) {
- NewFieldTypeMunger munger = (NewFieldTypeMunger) cmunger.getMunger();
- ResolvedMember initMethod = munger.getInitMethod(cmunger.getAspectType());
- if (!isStatic) {
- ret.append(InstructionConstants.ALOAD_0);
- }
- ret.append(Utility.createInvoke(fact, world, initMethod));
- }
- return ret;
- }
-
- private void match(LazyMethodGen mg, InstructionHandle ih, BcelShadow enclosingShadow, List<BcelShadow> shadowAccumulator) {
- Instruction i = ih.getInstruction();
-
- // Exception handlers (pr230817)
- if (canMatch(Shadow.ExceptionHandler) && !Range.isRangeHandle(ih)) {
- Set<InstructionTargeter> targeters = ih.getTargetersCopy();
- // If in Java7 there may be overlapping exception ranges for multi catch - we should recognize that
- for (InstructionTargeter t : targeters) {
- if (t instanceof ExceptionRange) {
- // assert t.getHandler() == ih
- ExceptionRange er = (ExceptionRange) t;
- if (er.getCatchType() == null) {
- continue;
- }
- if (isInitFailureHandler(ih)) {
- return;
- }
- if (!ih.getInstruction().isStoreInstruction() && ih.getInstruction().getOpcode() != Constants.NOP) {
- // If using cobertura, the catch block stats with
- // INVOKESTATIC rather than ASTORE, in order that the ranges
- // for the methodcall and exceptionhandler shadows
- // that occur at this same
- // line, we need to modify the instruction list to
- // split them - adding a
- // NOP before the invokestatic that gets all the targeters
- // that were aimed at the INVOKESTATIC
- mg.getBody().insert(ih, InstructionConstants.NOP);
- InstructionHandle newNOP = ih.getPrev();
- // what about a try..catch that starts at the start
- // of the exception handler? need to only include
- // certain targeters really.
- er.updateTarget(ih, newNOP, mg.getBody());
- for (InstructionTargeter t2 : targeters) {
- newNOP.addTargeter(t2);
- }
- ih.removeAllTargeters();
- match(BcelShadow.makeExceptionHandler(world, er, mg, newNOP, enclosingShadow), shadowAccumulator);
- } else {
- match(BcelShadow.makeExceptionHandler(world, er, mg, ih, enclosingShadow), shadowAccumulator);
- }
- }
- }
- }
-
- if ((i instanceof FieldInstruction) && (canMatch(Shadow.FieldGet) || canMatch(Shadow.FieldSet))) {
- FieldInstruction fi = (FieldInstruction) i;
-
- if (fi.opcode == Constants.PUTFIELD || fi.opcode == Constants.PUTSTATIC) {
- // check for sets of constant fields. We first check the
- // previous
- // instruction. If the previous instruction is a LD_WHATEVER
- // (push
- // constant on the stack) then we must resolve the field to
- // determine
- // if it's final. If it is final, then we don't generate a
- // shadow.
- InstructionHandle prevHandle = ih.getPrev();
- Instruction prevI = prevHandle.getInstruction();
- if (Utility.isConstantPushInstruction(prevI)) {
- Member field = BcelWorld.makeFieldJoinPointSignature(clazz, (FieldInstruction) i);
- ResolvedMember resolvedField = field.resolve(world);
- if (resolvedField == null) {
- // we can't find the field, so it's not a join point.
- } else if (Modifier.isFinal(resolvedField.getModifiers())) {
- // it's final, so it's the set of a final constant, so
- // it's
- // not a join point according to 1.0.6 and 1.1.
- } else {
- if (canMatch(Shadow.FieldSet)) {
- matchSetInstruction(mg, ih, enclosingShadow, shadowAccumulator);
- }
- }
- } else {
- if (canMatch(Shadow.FieldSet)) {
- matchSetInstruction(mg, ih, enclosingShadow, shadowAccumulator);
- }
- }
- } else {
- if (canMatch(Shadow.FieldGet)) {
- matchGetInstruction(mg, ih, enclosingShadow, shadowAccumulator);
- }
- }
- } else if (i instanceof InvokeInstruction) {
- InvokeInstruction ii = (InvokeInstruction) i;
- if (ii.getMethodName(clazz.getConstantPool()).equals("<init>")) {
- if (canMatch(Shadow.ConstructorCall)) {
- match(BcelShadow.makeConstructorCall(world, mg, ih, enclosingShadow), shadowAccumulator);
- }
- } else if (ii.opcode == Constants.INVOKESPECIAL) {
- String onTypeName = ii.getClassName(cpg);
- if (onTypeName.equals(mg.getEnclosingClass().getName())) {
- // we are private
- matchInvokeInstruction(mg, ih, ii, enclosingShadow, shadowAccumulator);
- } else {
- // we are a super call, and this is not a join point in
- // AspectJ-1.{0,1}
- }
- } else {
- if (ii.getOpcode()!=Constants.INVOKEDYNAMIC) {
- matchInvokeInstruction(mg, ih, ii, enclosingShadow, shadowAccumulator);
- }
- }
- } else if (world.isJoinpointArrayConstructionEnabled() && i.isArrayCreationInstruction()) {
- if (canMatch(Shadow.ConstructorCall)) {
- if (i.opcode == Constants.ANEWARRAY) {
- // ANEWARRAY arrayInstruction = (ANEWARRAY)i;
- // ObjectType arrayType = i.getLoadClassType(clazz.getConstantPool());
- BcelShadow ctorCallShadow = BcelShadow.makeArrayConstructorCall(world, mg, ih, enclosingShadow);
- match(ctorCallShadow, shadowAccumulator);
- } else if (i.opcode == Constants.NEWARRAY) {
- // NEWARRAY arrayInstruction = (NEWARRAY)i;
- // Type arrayType = i.getType();
- BcelShadow ctorCallShadow = BcelShadow.makeArrayConstructorCall(world, mg, ih, enclosingShadow);
- match(ctorCallShadow, shadowAccumulator);
- } else if (i instanceof MULTIANEWARRAY) {
- // MULTIANEWARRAY arrayInstruction = (MULTIANEWARRAY) i;
- // ObjectType arrayType = arrayInstruction.getLoadClassType(clazz.getConstantPool());
- BcelShadow ctorCallShadow = BcelShadow.makeArrayConstructorCall(world, mg, ih, enclosingShadow);
- match(ctorCallShadow, shadowAccumulator);
- }
- }
- // see pr77166 if you are thinking about implementing this
- // } else if (i instanceof AALOAD ) {
- // AALOAD arrayLoad = (AALOAD)i;
- // Type arrayType = arrayLoad.getType(clazz.getConstantPoolGen());
- // BcelShadow arrayLoadShadow =
- // BcelShadow.makeArrayLoadCall(world,mg,ih,enclosingShadow);
- // match(arrayLoadShadow,shadowAccumulator);
- // } else if (i instanceof AASTORE) {
- // // ... magic required
- } else if (world.isJoinpointSynchronizationEnabled()
- && ((i.getOpcode() == Constants.MONITORENTER) || (i.getOpcode() == Constants.MONITOREXIT))) {
- // if (canMatch(Shadow.Monitoring)) {
- if (i.getOpcode() == Constants.MONITORENTER) {
- BcelShadow monitorEntryShadow = BcelShadow.makeMonitorEnter(world, mg, ih, enclosingShadow);
- match(monitorEntryShadow, shadowAccumulator);
- } else {
- BcelShadow monitorExitShadow = BcelShadow.makeMonitorExit(world, mg, ih, enclosingShadow);
- match(monitorExitShadow, shadowAccumulator);
- }
- // }
- }
-
- }
-
- private boolean isInitFailureHandler(InstructionHandle ih) {
- // Skip the astore_0 and aload_0 at the start of the handler and
- // then check if the instruction following these is
- // 'putstatic ajc$initFailureCause'. If it is then we are
- // in the handler we created in AspectClinit.generatePostSyntheticCode()
- InstructionHandle twoInstructionsAway = ih.getNext().getNext();
- if (twoInstructionsAway.getInstruction().opcode == Constants.PUTSTATIC) {
- String name = ((FieldInstruction) twoInstructionsAway.getInstruction()).getFieldName(cpg);
- if (name.equals(NameMangler.INITFAILURECAUSE_FIELD_NAME)) {
- return true;
- }
- }
- return false;
- }
-
- private void matchSetInstruction(LazyMethodGen mg, InstructionHandle ih, BcelShadow enclosingShadow,
- List<BcelShadow> shadowAccumulator) {
- FieldInstruction fi = (FieldInstruction) ih.getInstruction();
- Member field = BcelWorld.makeFieldJoinPointSignature(clazz, fi);
-
- // synthetic fields are never join points
- if (field.getName().startsWith(NameMangler.PREFIX)) {
- return;
- }
-
- ResolvedMember resolvedField = field.resolve(world);
- if (resolvedField == null) {
- // we can't find the field, so it's not a join point.
- return;
- } else if (Modifier.isFinal(resolvedField.getModifiers())
- && Utility.isConstantPushInstruction(ih.getPrev().getInstruction())) {
- // it's the set of a final constant, so it's
- // not a join point according to 1.0.6 and 1.1.
- return;
- } else if (resolvedField.isSynthetic()) {
- // sets of synthetics aren't join points in 1.1
- return;
- } else {
- // 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);
- }
- }
-
- private void matchGetInstruction(LazyMethodGen mg, InstructionHandle ih, BcelShadow enclosingShadow,
- List<BcelShadow> shadowAccumulator) {
- FieldInstruction fi = (FieldInstruction) ih.getInstruction();
- Member field = BcelWorld.makeFieldJoinPointSignature(clazz, fi);
-
- // synthetic fields are never join points
- if (field.getName().startsWith(NameMangler.PREFIX)) {
- return;
- }
-
- ResolvedMember resolvedField = field.resolve(world);
- if (resolvedField == null) {
- // we can't find the field, so it's not a join point.
- return;
- } else if (resolvedField.isSynthetic()) {
- // sets of synthetics aren't join points in 1.1
- return;
- } else {
- BcelShadow bs = BcelShadow.makeFieldGet(world, resolvedField, mg, ih, enclosingShadow);
- String cname = fi.getClassName(cpg);
- if (!resolvedField.getDeclaringType().getName().equals(cname)) {
- bs.setActualTargetType(cname);
- }
- match(bs, shadowAccumulator);
- }
- }
-
- /**
- * For some named resolved type, this method looks for a member with a particular name - it should only be used when you truly
- * believe there is only one member with that name in the type as it returns the first one it finds.
- */
- private ResolvedMember findResolvedMemberNamed(ResolvedType type, String methodName) {
- ResolvedMember[] allMethods = type.getDeclaredMethods();
- for (int i = 0; i < allMethods.length; i++) {
- ResolvedMember member = allMethods[i];
- if (member.getName().equals(methodName)) {
- return member;
- }
- }
- return null;
- }
-
- /**
- * Find the specified member in the specified type.
- *
- * @param type the type to search for the member
- * @param methodName the name of the method to find
- * @param params the method parameters that the discovered method should have
- */
- private ResolvedMember findResolvedMemberNamed(ResolvedType type, String methodName, UnresolvedType[] params) {
- ResolvedMember[] allMethods = type.getDeclaredMethods();
- List<ResolvedMember> candidates = new ArrayList<ResolvedMember>();
- for (int i = 0; i < allMethods.length; i++) {
- ResolvedMember candidate = allMethods[i];
- if (candidate.getName().equals(methodName)) {
- if (candidate.getArity() == params.length) {
- candidates.add(candidate);
- }
- }
- }
-
- if (candidates.size() == 0) {
- return null;
- } else if (candidates.size() == 1) {
- return candidates.get(0);
- } else {
- // multiple candidates
- for (ResolvedMember candidate : candidates) {
- // These checks will break down with generics... but that would need two ITDs with the same name, same arity and
- // generics
- boolean allOK = true;
- UnresolvedType[] candidateParams = candidate.getParameterTypes();
- for (int p = 0; p < candidateParams.length; p++) {
- if (!candidateParams[p].getErasureSignature().equals(params[p].getErasureSignature())) {
- allOK = false;
- break;
- }
- }
- if (allOK) {
- return candidate;
- }
- }
- }
- return null;
- }
-
- /**
- * For a given resolvedmember, this will discover the real annotations for it. <b>Should only be used when the resolvedmember is
- * the contents of an effective signature attribute, as thats the only time when the annotations aren't stored directly in the
- * resolvedMember</b>
- *
- * @param rm the sig we want it to pretend to be 'int A.m()' or somesuch ITD like thing
- * @param declaredSig the real sig 'blah.ajc$xxx'
- */
- private void fixParameterNamesForResolvedMember(ResolvedMember rm, ResolvedMember declaredSig) {
-
- UnresolvedType memberHostType = declaredSig.getDeclaringType();
- String methodName = declaredSig.getName();
- String[] pnames = null;
- if (rm.getKind() == Member.METHOD && !rm.isAbstract()) {
- if (methodName.startsWith("ajc$inlineAccessMethod") || methodName.startsWith("ajc$superDispatch")) {
- ResolvedMember resolvedDooberry = world.resolve(declaredSig);
- pnames = resolvedDooberry.getParameterNames();
- } else {
- ResolvedMember realthing = AjcMemberMaker.interMethodDispatcher(rm.resolve(world), memberHostType).resolve(world);
- ResolvedMember theRealMember = findResolvedMemberNamed(memberHostType.resolve(world), realthing.getName());
- if (theRealMember != null) {
- pnames = theRealMember.getParameterNames();
- // static ITDs don't need any parameter shifting
- if (pnames.length > 0 && pnames[0].equals("ajc$this_")) {
- String[] pnames2 = new String[pnames.length - 1];
- System.arraycopy(pnames, 1, pnames2, 0, pnames2.length);
- pnames = pnames2;
- }
- }
- }
- // i think ctors are missing from here... copy code from below...
- }
- rm.setParameterNames(pnames);
- }
-
- /**
- * For a given resolvedmember, this will discover the real annotations for it. <b>Should only be used when the resolvedmember is
- * the contents of an effective signature attribute, as thats the only time when the annotations aren't stored directly in the
- * resolvedMember</b>
- *
- * @param rm the sig we want it to pretend to be 'int A.m()' or somesuch ITD like thing
- * @param declaredSig the real sig 'blah.ajc$xxx'
- */
- private void fixAnnotationsForResolvedMember(ResolvedMember rm, ResolvedMember declaredSig) {
- try {
- UnresolvedType memberHostType = declaredSig.getDeclaringType();
- boolean containsKey = mapToAnnotationHolder.containsKey(rm);
- ResolvedMember realAnnotationHolder = mapToAnnotationHolder.get(rm);
- String methodName = declaredSig.getName();
- // FIXME asc shouldnt really rely on string names !
- if (!containsKey) {
- if (rm.getKind() == Member.FIELD) {
- if (methodName.startsWith("ajc$inlineAccessField")) {
- realAnnotationHolder = world.resolve(rm);
- } else {
- ResolvedMember realthing = AjcMemberMaker.interFieldInitializer(rm, memberHostType);
- realAnnotationHolder = world.resolve(realthing);
- }
- } else if (rm.getKind() == Member.METHOD && !rm.isAbstract()) {
- if (methodName.startsWith("ajc$inlineAccessMethod") || methodName.startsWith("ajc$superDispatch")) {
- realAnnotationHolder = world.resolve(declaredSig);
- } else {
- ResolvedMember realthing = AjcMemberMaker.interMethodDispatcher(rm.resolve(world), memberHostType).resolve(world);
- realAnnotationHolder = findResolvedMemberNamed(memberHostType.resolve(world), realthing.getName(),realthing.getParameterTypes());
- if (realAnnotationHolder == null) {
- throw new UnsupportedOperationException(
- "Known limitation in M4 - can't find ITD members when type variable is used as an argument and has upper bound specified");
- }
- }
- } else if (rm.getKind() == Member.CONSTRUCTOR) {
- ResolvedMember realThing = AjcMemberMaker.postIntroducedConstructor(memberHostType.resolve(world),rm.getDeclaringType(), rm.getParameterTypes());
- realAnnotationHolder = world.resolve(realThing);
- // AMC temp guard for M4
- if (realAnnotationHolder == null) {
- throw new UnsupportedOperationException("Known limitation in M4 - can't find ITD members when type variable is used as an argument and has upper bound specified");
- }
- }
- mapToAnnotationHolder.put(rm, realAnnotationHolder);
- }
- ResolvedType[] annotationTypes;
- AnnotationAJ[] annotations;
- if (realAnnotationHolder!=null) {
- annotationTypes = realAnnotationHolder.getAnnotationTypes();
- annotations = realAnnotationHolder.getAnnotations();
- if (annotationTypes==null) {
- annotationTypes = ResolvedType.EMPTY_ARRAY;
- }
- if (annotations==null) {
- annotations = AnnotationAJ.EMPTY_ARRAY;
- }
- } else {
- annotations = AnnotationAJ.EMPTY_ARRAY;
- annotationTypes = ResolvedType.EMPTY_ARRAY;
- }
- rm.setAnnotations(annotations);
- rm.setAnnotationTypes(annotationTypes);
- } catch (UnsupportedOperationException ex) {
- throw ex;
- } catch (Throwable t) {
- // FIXME asc remove this catch after more testing has confirmed the
- // above stuff is OK
- throw new BCException("Unexpectedly went bang when searching for annotations on " + rm, t);
- }
- }
-
- private void matchInvokeInstruction(LazyMethodGen mg, InstructionHandle ih, InvokeInstruction invoke,
- BcelShadow enclosingShadow, List<BcelShadow> shadowAccumulator) {
- String methodName = invoke.getName(cpg);
- if (methodName.startsWith(NameMangler.PREFIX)) {
- Member jpSig = world.makeJoinPointSignatureForMethodInvocation(clazz, invoke);
- ResolvedMember declaredSig = jpSig.resolve(world);
- // System.err.println(method + ", declaredSig: " +declaredSig);
- if (declaredSig == null) {
- return;
- }
-
- if (declaredSig.getKind() == Member.FIELD) {
- Shadow.Kind kind;
- if (jpSig.getReturnType().equals(UnresolvedType.VOID)) {
- kind = Shadow.FieldSet;
- } else {
- kind = Shadow.FieldGet;
- }
-
- if (canMatch(Shadow.FieldGet) || canMatch(Shadow.FieldSet)) {
- match(BcelShadow.makeShadowForMethodCall(world, mg, ih, enclosingShadow, kind, declaredSig), shadowAccumulator);
- }
- } else if (!declaredSig.getName().startsWith(NameMangler.PREFIX)) {
- // 307147 - resolution above may have found the real method directly rather
- // than needing to go through the effective signature attribute
- if (canMatch(Shadow.MethodCall)) {
- match(BcelShadow.makeShadowForMethodCall(world, mg, ih, enclosingShadow, Shadow.MethodCall, declaredSig),
- shadowAccumulator);
- }
- } else {
- AjAttribute.EffectiveSignatureAttribute effectiveSig = declaredSig.getEffectiveSignature();
- if (effectiveSig == null) {
- return;
- }
- // System.err.println("call to inter-type member: " +
- // effectiveSig);
- if (effectiveSig.isWeaveBody()) {
- return;
- }
-
- ResolvedMember rm = effectiveSig.getEffectiveSignature();
- fixParameterNamesForResolvedMember(rm, declaredSig);
- fixAnnotationsForResolvedMember(rm, declaredSig); // abracadabra
-
- if (canMatch(effectiveSig.getShadowKind())) {
- match(BcelShadow.makeShadowForMethodCall(world, mg, ih, enclosingShadow, effectiveSig.getShadowKind(), rm),
- shadowAccumulator);
- }
- }
- } else {
- if (canMatch(Shadow.MethodCall)) {
- boolean proceed = true;
- // overweaving needs to ignore some calls added by the previous weave
- if (world.isOverWeaving()) {
- String s = invoke.getClassName(mg.getConstantPool());
- // skip all the inc/dec/isValid/etc
- if (s.length() > 4
- && s.charAt(4) == 'a'
- && (s.equals("org.aspectj.runtime.internal.CFlowCounter")
- || s.equals("org.aspectj.runtime.internal.CFlowStack") || s
- .equals("org.aspectj.runtime.reflect.Factory"))) {
- proceed = false;
- } else {
- if (methodName.equals("aspectOf")) {
- proceed = false;
- }
- }
- }
- if (proceed) {
- match(BcelShadow.makeMethodCall(world, mg, ih, enclosingShadow), shadowAccumulator);
- }
- }
- }
- }
-
- // static ... so all worlds will share the config for the first one
- // created...
- private static boolean checkedXsetForLowLevelContextCapturing = false;
- private static boolean captureLowLevelContext = false;
-
- private boolean match(BcelShadow shadow, List<BcelShadow> shadowAccumulator) {
- // Duplicate blocks - one with context one without, seems faster than multiple 'ifs'
- if (captureLowLevelContext) {
- ContextToken shadowMatchToken = CompilationAndWeavingContext.enteringPhase(
- CompilationAndWeavingContext.MATCHING_SHADOW, shadow);
- boolean isMatched = false;
-
- Shadow.Kind shadowKind = shadow.getKind();
- List<ShadowMunger> candidateMungers = indexedShadowMungers[shadowKind.getKey()];
-
- // System.out.println("Candidates " + candidateMungers);
- if (candidateMungers != null) {
- for (ShadowMunger munger : candidateMungers) {
-
- ContextToken mungerMatchToken = CompilationAndWeavingContext.enteringPhase(
- CompilationAndWeavingContext.MATCHING_POINTCUT, munger.getPointcut());
- if (munger.match(shadow, world)) {
- shadow.addMunger(munger);
- isMatched = true;
- if (shadow.getKind() == Shadow.StaticInitialization) {
- clazz.warnOnAddedStaticInitializer(shadow, munger.getSourceLocation());
- }
- }
- CompilationAndWeavingContext.leavingPhase(mungerMatchToken);
- }
-
- if (isMatched) {
- shadowAccumulator.add(shadow);
- }
- }
- CompilationAndWeavingContext.leavingPhase(shadowMatchToken);
- return isMatched;
- } else {
- boolean isMatched = false;
-
- Shadow.Kind shadowKind = shadow.getKind();
- List<ShadowMunger> candidateMungers = indexedShadowMungers[shadowKind.getKey()];
-
- // System.out.println("Candidates at " + shadowKind + " are " + candidateMungers);
- if (candidateMungers != null) {
- for (ShadowMunger munger : candidateMungers) {
- if (munger.match(shadow, world)) {
- shadow.addMunger(munger);
- isMatched = true;
- if (shadow.getKind() == Shadow.StaticInitialization) {
- clazz.warnOnAddedStaticInitializer(shadow, munger.getSourceLocation());
- }
- }
- }
- if (isMatched) {
- shadowAccumulator.add(shadow);
- }
- }
- return isMatched;
- }
- }
-
- // ----
-
- private void implement(LazyMethodGen mg) {
- List<BcelShadow> shadows = mg.matchedShadows;
- if (shadows == null) {
- return;
- }
- // We depend on a partial order such that inner shadows are earlier on
- // the list than outer shadows. That's fine. This order is preserved if:
-
- // A preceeds B iff B.getStart() is LATER THAN A.getStart().
-
- for (BcelShadow shadow : shadows) {
- ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.IMPLEMENTING_ON_SHADOW,
- shadow);
- shadow.implement();
- CompilationAndWeavingContext.leavingPhase(tok);
- }
- // int ii =
- mg.getMaxLocals();
- mg.matchedShadows = null;
- }
-
- // ----
-
- public LazyClassGen getLazyClassGen() {
- return clazz;
- }
-
- public BcelWorld getWorld() {
- return world;
- }
-
- public void setReweavableMode(boolean mode) {
- inReweavableMode = mode;
- }
-
- public boolean getReweavableMode() {
- return inReweavableMode;
- }
-
- @Override
- public String toString() {
- return "BcelClassWeaver instance for : " + clazz;
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelConstantPoolReader.java b/weaver/src/org/aspectj/weaver/bcel/BcelConstantPoolReader.java
deleted file mode 100644
index 2deaf57c1..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelConstantPoolReader.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2010 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 (SpringSource)
- * ******************************************************************/
-package org.aspectj.weaver.bcel;
-
-import org.aspectj.apache.bcel.classfile.ConstantPool;
-import org.aspectj.weaver.ConstantPoolReader;
-
-/**
- * An implementation of the constant pool reader that speaks Bcel.
- *
- * @author Andy Clement
- */
-public class BcelConstantPoolReader implements ConstantPoolReader {
-
- private ConstantPool constantPool;
-
- public BcelConstantPoolReader(ConstantPool constantPool) {
- this.constantPool = constantPool;
- }
-
- public String readUtf8(int cpIndex) {
- return constantPool.getConstantUtf8(cpIndex).getValue();
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelConstantPoolWriter.java b/weaver/src/org/aspectj/weaver/bcel/BcelConstantPoolWriter.java
deleted file mode 100644
index 634764901..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelConstantPoolWriter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2010 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 (SpringSource)
- * ******************************************************************/
-package org.aspectj.weaver.bcel;
-
-import org.aspectj.apache.bcel.classfile.ConstantPool;
-import org.aspectj.weaver.ConstantPoolWriter;
-
-/**
- * An implementation of the constant pool writer that speaks Bcel.
- *
- * @author Andy Clement
- */
-class BcelConstantPoolWriter implements ConstantPoolWriter {
-
- ConstantPool pool;
-
- public BcelConstantPoolWriter(ConstantPool pool) {
- this.pool = pool;
- }
-
- public int writeUtf8(String name) {
- return pool.addUtf8(name);
- }
-
-} \ No newline at end of file
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelField.java b/weaver/src/org/aspectj/weaver/bcel/BcelField.java
deleted file mode 100644
index c88e8519f..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelField.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/* *******************************************************************
- * 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.util.List;
-
-import org.aspectj.apache.bcel.classfile.Attribute;
-import org.aspectj.apache.bcel.classfile.ConstantPool;
-import org.aspectj.apache.bcel.classfile.Field;
-import org.aspectj.apache.bcel.classfile.Synthetic;
-import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
-import org.aspectj.apache.bcel.generic.FieldGen;
-import org.aspectj.util.GenericSignature;
-import org.aspectj.util.GenericSignatureParser;
-import org.aspectj.weaver.AjAttribute;
-import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
-import org.aspectj.weaver.AnnotationAJ;
-import org.aspectj.weaver.ISourceContext;
-import org.aspectj.weaver.ResolvedMemberImpl;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.World;
-import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException;
-
-/**
- * An AspectJ Field object that is backed by a Bcel Field object.
- *
- * @author PARC
- * @author Andy Clement
- */
-final class BcelField extends ResolvedMemberImpl {
-
- public static int AccSynthetic = 0x1000;
-
- private Field field;
- private boolean isAjSynthetic;
- private boolean isSynthetic = false;
- private AnnotationAJ[] annotations;
- private final World world;
- private final BcelObjectType bcelObjectType;
- private UnresolvedType genericFieldType = null;
- private boolean unpackedGenericSignature = false;
- private boolean annotationsOnFieldObjectAreOutOfDate = false;
-
- BcelField(BcelObjectType declaringType, Field field) {
- super(FIELD, declaringType.getResolvedTypeX(), field.getModifiers(), field.getName(), field.getSignature());
- this.field = field;
- this.world = declaringType.getResolvedTypeX().getWorld();
- this.bcelObjectType = declaringType;
- unpackAttributes(world);
- checkedExceptions = UnresolvedType.NONE;
- }
-
- /**
- * Constructs an instance that wrappers a Field object, but where we do not (yet) have a BcelObjectType - usually because the
- * containing type (and this field) are being constructed at runtime (so there is no .class file to retrieve).
- */
- BcelField(String declaringTypeName, Field field, World world) {
- super(FIELD, UnresolvedType.forName(declaringTypeName), field.getModifiers(), field.getName(), field.getSignature());
- this.field = field;
- this.world = world;
- this.bcelObjectType = null;
- unpackAttributes(world);
- checkedExceptions = UnresolvedType.NONE;
- }
-
- private void unpackAttributes(World world) {
- Attribute[] attrs = field.getAttributes();
- if (attrs != null && attrs.length > 0) {
- ISourceContext sourceContext = getSourceContext(world);
- List<AjAttribute> as = Utility.readAjAttributes(getDeclaringType().getClassName(), attrs, sourceContext, world,
- (bcelObjectType != null ? bcelObjectType.getWeaverVersionAttribute() : WeaverVersionInfo.CURRENT),
- new BcelConstantPoolReader(field.getConstantPool()));
- as.addAll(AtAjAttributes.readAj5FieldAttributes(field, this, world.resolve(getDeclaringType()), sourceContext,
- world.getMessageHandler()));
-
- // FIXME this code has no effect!!!??? it is set to false immediately after the block
- // for (AjAttribute a : as) {
- // if (a instanceof AjAttribute.AjSynthetic) {
- // isAjSynthetic = true;
- // } else {
- // throw new BCException("weird field attribute " + a);
- // }
- // }
- }
- isAjSynthetic = false;
-
- for (int i = attrs.length - 1; i >= 0; i--) {
- if (attrs[i] instanceof Synthetic) {
- isSynthetic = true;
- }
- }
- // in 1.5, synthetic is a modifier, not an attribute
- if ((field.getModifiers() & AccSynthetic) != 0) {
- isSynthetic = true;
- }
-
- }
-
- @Override
- public boolean isAjSynthetic() {
- return isAjSynthetic;
- }
-
- @Override
- public boolean isSynthetic() {
- return isSynthetic;
- }
-
- @Override
- public boolean hasAnnotation(UnresolvedType ofType) {
- ensureAnnotationTypesRetrieved();
- for (ResolvedType aType : annotationTypes) {
- if (aType.equals(ofType)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public ResolvedType[] getAnnotationTypes() {
- ensureAnnotationTypesRetrieved();
- return annotationTypes;
- }
-
- @Override
- public AnnotationAJ[] getAnnotations() {
- ensureAnnotationTypesRetrieved();
- return annotations;
- }
-
- @Override
- public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
- ensureAnnotationTypesRetrieved();
- for (AnnotationAJ annotation : annotations) {
- if (annotation.getTypeName().equals(ofType.getName())) {
- return annotation;
- }
- }
- return null;
- }
-
- private void ensureAnnotationTypesRetrieved() {
- if (annotationTypes == null) {
- AnnotationGen annos[] = field.getAnnotations();
- if (annos.length == 0) {
- annotationTypes = ResolvedType.EMPTY_ARRAY;
- annotations = AnnotationAJ.EMPTY_ARRAY;
- } else {
- int annosCount = annos.length;
- annotationTypes = new ResolvedType[annosCount];
- annotations = new AnnotationAJ[annosCount];
- for (int i = 0; i < annosCount; i++) {
- AnnotationGen anno = annos[i];
- annotations[i] = new BcelAnnotation(anno, world);
- annotationTypes[i] = annotations[i].getType();
- }
- }
- }
- }
-
- @Override
- public void addAnnotation(AnnotationAJ annotation) {
- ensureAnnotationTypesRetrieved();
- int len = annotations.length;
- AnnotationAJ[] ret = new AnnotationAJ[len + 1];
- System.arraycopy(annotations, 0, ret, 0, len);
- ret[len] = annotation;
- annotations = ret;
-
- ResolvedType[] newAnnotationTypes = new ResolvedType[len + 1];
- System.arraycopy(annotationTypes, 0, newAnnotationTypes, 0, len);
- newAnnotationTypes[len] = annotation.getType();
- annotationTypes = newAnnotationTypes;
-
- annotationsOnFieldObjectAreOutOfDate = true;
- }
-
- public void removeAnnotation(AnnotationAJ annotation) {
- ensureAnnotationTypesRetrieved();
-
- int len = annotations.length;
- AnnotationAJ[] ret = new AnnotationAJ[len - 1];
- int p = 0;
- for (AnnotationAJ anno : annotations) {
- if (!anno.getType().equals(annotation.getType())) {
- ret[p++] = anno;
- }
- }
- annotations = ret;
-
- ResolvedType[] newAnnotationTypes = new ResolvedType[len - 1];
- p = 0;
- for (ResolvedType anno : annotationTypes) {
- if (!anno.equals(annotation.getType())) {
- newAnnotationTypes[p++] = anno;
- }
- }
- annotationTypes = newAnnotationTypes;
-
- annotationsOnFieldObjectAreOutOfDate = true;
- }
-
- /**
- * Unpack the generic signature attribute if there is one and we haven't already done so, then find the true field type of this
- * field (eg. List<String>).
- */
- @Override
- public UnresolvedType getGenericReturnType() {
- unpackGenericSignature();
- return genericFieldType;
- }
-
- public Field getFieldAsIs() {
- return field;
- }
-
- public Field getField(ConstantPool cpool) {
- if (!annotationsOnFieldObjectAreOutOfDate) {
- return field;
- }
- FieldGen newFieldGen = new FieldGen(field, cpool);
- newFieldGen.removeAnnotations();
- // List<AnnotationGen> alreadyHas = fg.getAnnotations();
- // if (annotations != null) {
- // fg.removeAnnotations();
- for (AnnotationAJ annotation : annotations) {
- newFieldGen.addAnnotation(new AnnotationGen(((BcelAnnotation) annotation).getBcelAnnotation(), cpool, true));
- }
- // for (int i = 0; i < annotations.length; i++) {
- // AnnotationAJ array_element = annotations[i];
- // boolean alreadyHasIt = false;
- // for (AnnotationGen gen : alreadyHas) {
- // if (gen.getTypeName().equals(array_element.getTypeName())) {
- // alreadyHasIt = true;
- // break;
- // }
- // }
- // if (!alreadyHasIt) {
- // fg.addAnnotation(new AnnotationGen(((BcelAnnotation) array_element).getBcelAnnotation(), cpg, true));
- // // }
- // // }
- // }
- field = newFieldGen.getField();
- annotationsOnFieldObjectAreOutOfDate = false; // we are now correct again
- return field;
- }
-
- private void unpackGenericSignature() {
- if (unpackedGenericSignature) {
- return;
- }
- if (!world.isInJava5Mode()) {
- this.genericFieldType = getReturnType();
- return;
- }
- unpackedGenericSignature = true;
- String gSig = field.getGenericSignature();
- if (gSig != null) {
- // get from generic
- GenericSignature.FieldTypeSignature fts = new GenericSignatureParser().parseAsFieldSignature(gSig);
- GenericSignature.ClassSignature genericTypeSig = bcelObjectType.getGenericClassTypeSignature();
-
- GenericSignature.FormalTypeParameter[] parentFormals = bcelObjectType.getAllFormals();
- GenericSignature.FormalTypeParameter[] typeVars = ((genericTypeSig == null) ? new GenericSignature.FormalTypeParameter[0]
- : genericTypeSig.formalTypeParameters);
- GenericSignature.FormalTypeParameter[] formals = new GenericSignature.FormalTypeParameter[parentFormals.length
- + typeVars.length];
- // put method formal in front of type formals for overriding in
- // lookup
- System.arraycopy(typeVars, 0, formals, 0, typeVars.length);
- System.arraycopy(parentFormals, 0, formals, typeVars.length, parentFormals.length);
-
- try {
- genericFieldType = BcelGenericSignatureToTypeXConverter.fieldTypeSignature2TypeX(fts, formals, world);
- } catch (GenericSignatureFormatException e) {
- // development bug, fail fast with good info
- throw new IllegalStateException("While determing the generic field type of " + this.toString()
- + " with generic signature " + gSig + " the following error was detected: " + e.getMessage());
- }
- } else {
- genericFieldType = getReturnType();
- }
- }
-
- @Override
- public void evictWeavingState() {
- if (field != null) {
- unpackGenericSignature();
- unpackAttributes(world);
- ensureAnnotationTypesRetrieved();
- // this.sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT;
- field = null;
- }
- }
-} \ No newline at end of file
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelFieldRef.java b/weaver/src/org/aspectj/weaver/bcel/BcelFieldRef.java
deleted file mode 100644
index a5a2a79ec..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelFieldRef.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/* *******************************************************************
- * 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 org.aspectj.apache.bcel.Constants;
-import org.aspectj.apache.bcel.generic.Instruction;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.weaver.ResolvedType;
-
-/**
- * XXX Erik and I need to discuss this hierarchy. Having FieldRef extend Var is convenient, but hopefully there's a better design.
- *
- * This is always a static reference.
- */
-public class BcelFieldRef extends BcelVar {
-
- private String className, fieldName;
-
- public BcelFieldRef(ResolvedType type, String className, String fieldName) {
- super(type, 0);
- this.className = className;
- this.fieldName = fieldName;
- }
-
- public String toString() {
- return "BcelFieldRef(" + getType() + " " + className + "." + fieldName + ")";
- }
-
- // public int getSlot() { return slot; }
-
- public Instruction createLoad(InstructionFactory fact) {
- return fact.createFieldAccess(className, fieldName, BcelWorld.makeBcelType(getType()), Constants.GETSTATIC);
- }
-
- public Instruction createStore(InstructionFactory fact) {
- return fact.createFieldAccess(className, fieldName, BcelWorld.makeBcelType(getType()), Constants.PUTSTATIC);
- }
-
- public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) {
- throw new RuntimeException("unimplemented");
- }
-
- // this is an array var
- // void appendConvertableArrayLoad(
- // InstructionList il,
- // InstructionFactory fact,
- // int index,
- // ResolvedType convertTo)
- // {
- // ResolvedType convertFromType = getType().getResolvedComponentType();
- // appendLoad(il, fact);
- // il.append(Utility.createConstant(fact, index));
- // il.append(fact.createArrayLoad(BcelWorld.makeBcelType(convertFromType)));
- // Utility.appendConversion(il, fact, convertFromType, convertTo);
- // }
- //
- // void appendConvertableArrayStore(
- // InstructionList il,
- // InstructionFactory fact,
- // int index,
- // BcelFieldRef storee)
- // {
- // ResolvedType convertToType = getType().getResolvedComponentType();
- // appendLoad(il, fact);
- // il.append(Utility.createConstant(fact, index));
- // storee.appendLoad(il, fact);
- // Utility.appendConversion(il, fact, storee.getType(), convertToType);
- // il.append(fact.createArrayStore(BcelWorld.makeBcelType(convertToType)));
- // }
- //
- // InstructionList createConvertableArrayStore(
- // InstructionFactory fact,
- // int index,
- // BcelFieldRef storee)
- // {
- // InstructionList il = new InstructionList();
- // appendConvertableArrayStore(il, fact, index, storee);
- // return il;
- // }
- // InstructionList createConvertableArrayLoad(
- // InstructionFactory fact,
- // int index,
- // ResolvedType convertTo)
- // {
- // InstructionList il = new InstructionList();
- // appendConvertableArrayLoad(il, fact, index, convertTo);
- // return il;
- // }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXConverter.java b/weaver/src/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXConverter.java
deleted file mode 100644
index 9b4c90cbc..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXConverter.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/* *******************************************************************
- * 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.bcel;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.aspectj.util.GenericSignature;
-import org.aspectj.util.GenericSignature.SimpleClassTypeSignature;
-import org.aspectj.weaver.BoundedReferenceType;
-import org.aspectj.weaver.ReferenceType;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.TypeFactory;
-import org.aspectj.weaver.TypeVariable;
-import org.aspectj.weaver.TypeVariableReferenceType;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.World;
-import org.aspectj.weaver.tools.Trace;
-import org.aspectj.weaver.tools.TraceFactory;
-
-/**
- * A utility class that assists in unpacking constituent parts of generic signature attributes and returning their equivalents in
- * UnresolvedType world.
- */
-public class BcelGenericSignatureToTypeXConverter {
-
- private static Trace trace = TraceFactory.getTraceFactory().getTrace(BcelGenericSignatureToTypeXConverter.class);
-
- public static ResolvedType classTypeSignature2TypeX(GenericSignature.ClassTypeSignature aClassTypeSignature,
- GenericSignature.FormalTypeParameter[] typeParams, World world) throws GenericSignatureFormatException {
- Map<GenericSignature.FormalTypeParameter, ReferenceType> typeMap = new HashMap<GenericSignature.FormalTypeParameter, ReferenceType>();
- ResolvedType ret = classTypeSignature2TypeX(aClassTypeSignature, typeParams, world, typeMap);
- fixUpCircularDependencies(ret, typeMap);
- return ret;
- }
-
- private static ResolvedType classTypeSignature2TypeX(GenericSignature.ClassTypeSignature aClassTypeSignature,
- GenericSignature.FormalTypeParameter[] typeParams, World world,
- Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
- throws GenericSignatureFormatException {
- // class type sig consists of an outer type, and zero or more nested types
- // the fully qualified name is outer-type.nested-type1.nested-type2....
- // each type in the hierarchy may have type arguments
-
- // first build the 'raw type' signature
- StringBuffer sig = new StringBuffer();
- sig.append(aClassTypeSignature.outerType.identifier.replace(';', ' ').trim());
- for (int i = 0; i < aClassTypeSignature.nestedTypes.length; i++) {
- sig.append("$");
- sig.append(aClassTypeSignature.nestedTypes[i].identifier.replace(';', ' ').trim());
- }
- sig.append(";");
-
- // now look for any type parameters.
- // I *think* we only need to worry about the 'right-most' type...
- SimpleClassTypeSignature innerType = aClassTypeSignature.outerType;
- if (aClassTypeSignature.nestedTypes.length > 0) {
- innerType = aClassTypeSignature.nestedTypes[aClassTypeSignature.nestedTypes.length - 1];
- }
- if (innerType.typeArguments.length > 0) {
- // we have to create a parameterized type
- // type arguments may be array types, class types, or typevariable types
- ResolvedType theBaseType = UnresolvedType.forSignature(sig.toString()).resolve(world);
-
- // Sometimes we may find that when the code is being load-time woven that the types have changed.
- // Perhaps an old form of a library jar is being used - this can mean we discover right here
- // that a type is not parameterizable (is that a word?). I think in these cases it is ok to
- // just return with what we know (the base type). (see pr152848)
- if (!(theBaseType.isGenericType() || theBaseType.isRawType())) {
- if (trace.isTraceEnabled()) {
- trace.event("classTypeSignature2TypeX: this type is not a generic type:", null, new Object[] { theBaseType });
- }
- return theBaseType;
- }
-
- ResolvedType[] typeArgumentTypes = new ResolvedType[innerType.typeArguments.length];
- for (int i = 0; i < typeArgumentTypes.length; i++) {
- typeArgumentTypes[i] = typeArgument2TypeX(innerType.typeArguments[i], typeParams, world,
- inProgressTypeVariableResolutions);
- }
- return TypeFactory.createParameterizedType(theBaseType, typeArgumentTypes, world);
-
- // world.resolve(UnresolvedType.forParameterizedTypes(
- // UnresolvedType.forSignature(sig.toString()).resolve(world),
- // typeArgumentTypes));
- } else {
- // we have a non-parameterized type
- return world.resolve(UnresolvedType.forSignature(sig.toString()));
- }
- }
-
- public static ResolvedType fieldTypeSignature2TypeX(GenericSignature.FieldTypeSignature aFieldTypeSignature,
- GenericSignature.FormalTypeParameter[] typeParams, World world) throws GenericSignatureFormatException {
- Map<GenericSignature.FormalTypeParameter, ReferenceType> typeMap = new HashMap<GenericSignature.FormalTypeParameter, ReferenceType>();
- ResolvedType ret = fieldTypeSignature2TypeX(aFieldTypeSignature, typeParams, world, typeMap);
- fixUpCircularDependencies(ret, typeMap);
- return ret;
- }
-
- private static ResolvedType fieldTypeSignature2TypeX(GenericSignature.FieldTypeSignature aFieldTypeSignature,
- GenericSignature.FormalTypeParameter[] typeParams, World world,
- Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
- throws GenericSignatureFormatException {
- if (aFieldTypeSignature.isClassTypeSignature()) {
- return classTypeSignature2TypeX((GenericSignature.ClassTypeSignature) aFieldTypeSignature, typeParams, world,
- inProgressTypeVariableResolutions);
- } else if (aFieldTypeSignature.isArrayTypeSignature()) {
- int dims = 0;
- GenericSignature.TypeSignature ats = aFieldTypeSignature;
- while (ats instanceof GenericSignature.ArrayTypeSignature) {
- dims++;
- ats = ((GenericSignature.ArrayTypeSignature) ats).typeSig;
- }
- return world.resolve(UnresolvedType.makeArray(
- typeSignature2TypeX(ats, typeParams, world, inProgressTypeVariableResolutions), dims));
- } else if (aFieldTypeSignature.isTypeVariableSignature()) {
- ResolvedType rtx = typeVariableSignature2TypeX((GenericSignature.TypeVariableSignature) aFieldTypeSignature,
- typeParams, world, inProgressTypeVariableResolutions);
- return rtx;
- } else {
- throw new GenericSignatureFormatException("Cant understand field type signature: " + aFieldTypeSignature);
- }
- }
-
- public static TypeVariable formalTypeParameter2TypeVariable(GenericSignature.FormalTypeParameter aFormalTypeParameter,
- GenericSignature.FormalTypeParameter[] typeParams, World world) throws GenericSignatureFormatException {
- Map<GenericSignature.FormalTypeParameter, ReferenceType> typeMap = new HashMap<GenericSignature.FormalTypeParameter, ReferenceType>();
- return formalTypeParameter2TypeVariable(aFormalTypeParameter, typeParams, world, typeMap);
- }
-
- private static TypeVariable formalTypeParameter2TypeVariable(GenericSignature.FormalTypeParameter aFormalTypeParameter,
- GenericSignature.FormalTypeParameter[] typeParams, World world,
- Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
- throws GenericSignatureFormatException {
- UnresolvedType upperBound = fieldTypeSignature2TypeX(aFormalTypeParameter.classBound, typeParams, world,
- inProgressTypeVariableResolutions);
- UnresolvedType[] ifBounds = new UnresolvedType[aFormalTypeParameter.interfaceBounds.length];
- for (int i = 0; i < ifBounds.length; i++) {
- ifBounds[i] = fieldTypeSignature2TypeX(aFormalTypeParameter.interfaceBounds[i], typeParams, world,
- inProgressTypeVariableResolutions);
- }
- return new TypeVariable(aFormalTypeParameter.identifier, upperBound, ifBounds);
- }
-
- private static ResolvedType typeArgument2TypeX(GenericSignature.TypeArgument aTypeArgument,
- GenericSignature.FormalTypeParameter[] typeParams, World world,
- Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
- throws GenericSignatureFormatException {
- if (aTypeArgument.isWildcard) {
- return UnresolvedType.SOMETHING.resolve(world);
- }
- if (aTypeArgument.isMinus) {
- UnresolvedType bound = fieldTypeSignature2TypeX(aTypeArgument.signature, typeParams, world,
- inProgressTypeVariableResolutions);
- ResolvedType resolvedBound = world.resolve(bound);
- if (resolvedBound.isMissing()) {
- world.getLint().cantFindType.signal("Unable to find type (for bound): " + resolvedBound.getName(), null);
- resolvedBound = world.resolve(UnresolvedType.OBJECT);
- }
- ReferenceType rBound = (ReferenceType) resolvedBound;
- return new BoundedReferenceType(rBound, false, world);
- } else if (aTypeArgument.isPlus) {
- UnresolvedType bound = fieldTypeSignature2TypeX(aTypeArgument.signature, typeParams, world,
- inProgressTypeVariableResolutions);
- ResolvedType resolvedBound = world.resolve(bound);
- if (resolvedBound.isMissing()) {
- world.getLint().cantFindType.signal("Unable to find type (for bound): " + resolvedBound.getName(), null);
- resolvedBound = world.resolve(UnresolvedType.OBJECT);
- }
- ReferenceType rBound = (ReferenceType) resolvedBound;
- return new BoundedReferenceType(rBound, true, world);
- } else {
- return fieldTypeSignature2TypeX(aTypeArgument.signature, typeParams, world, inProgressTypeVariableResolutions);
- }
- }
-
- public static ResolvedType typeSignature2TypeX(GenericSignature.TypeSignature aTypeSig,
- GenericSignature.FormalTypeParameter[] typeParams, World world) throws GenericSignatureFormatException {
- Map<GenericSignature.FormalTypeParameter, ReferenceType> typeMap = new HashMap<GenericSignature.FormalTypeParameter, ReferenceType>();
- ResolvedType ret = typeSignature2TypeX(aTypeSig, typeParams, world, typeMap);
- fixUpCircularDependencies(ret, typeMap);
- return ret;
- }
-
- private static ResolvedType typeSignature2TypeX(GenericSignature.TypeSignature aTypeSig,
- GenericSignature.FormalTypeParameter[] typeParams, World world,
- Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
- throws GenericSignatureFormatException {
- if (aTypeSig.isBaseType()) {
- return world.resolve(UnresolvedType.forSignature(((GenericSignature.BaseTypeSignature) aTypeSig).toString()));
- } else {
- return fieldTypeSignature2TypeX((GenericSignature.FieldTypeSignature) aTypeSig, typeParams, world,
- inProgressTypeVariableResolutions);
- }
- }
-
- private static ResolvedType typeVariableSignature2TypeX(GenericSignature.TypeVariableSignature aTypeVarSig,
- GenericSignature.FormalTypeParameter[] typeParams, World world,
- Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
- throws GenericSignatureFormatException {
- GenericSignature.FormalTypeParameter typeVarBounds = null;
- for (int i = 0; i < typeParams.length; i++) {
- if (typeParams[i].identifier.equals(aTypeVarSig.typeVariableName)) {
- typeVarBounds = typeParams[i];
- break;
- }
- }
- if (typeVarBounds == null) {
- // blowing up here breaks the situation with ITDs where the type variable is mentioned in the
- // declaring type and used somewhere in the signature. Temporary change to allow it to return just a
- // 'dumb' typevariablereference.
- return new TypeVariableReferenceType(new TypeVariable(aTypeVarSig.typeVariableName), world);
- // throw new GenericSignatureFormatException("Undeclared type variable in signature: " + aTypeVarSig.typeVariableName);
- }
- if (inProgressTypeVariableResolutions.containsKey(typeVarBounds)) {
- return inProgressTypeVariableResolutions.get(typeVarBounds);
- }
- inProgressTypeVariableResolutions.put(typeVarBounds, new FTPHolder(typeVarBounds, world));
- ReferenceType ret = new TypeVariableReferenceType(formalTypeParameter2TypeVariable(typeVarBounds, typeParams, world,
- inProgressTypeVariableResolutions), world);
- inProgressTypeVariableResolutions.put(typeVarBounds, ret);
- return ret;
- }
-
- private static void fixUpCircularDependencies(ResolvedType aTypeX,
- Map<GenericSignature.FormalTypeParameter, ReferenceType> typeVariableResolutions) {
- if (!(aTypeX instanceof ReferenceType)) {
- return;
- }
-
- ReferenceType rt = (ReferenceType) aTypeX;
- TypeVariable[] typeVars = rt.getTypeVariables();
- if (typeVars != null) {
- for (int i = 0; i < typeVars.length; i++) {
- if (typeVars[i].getUpperBound() instanceof FTPHolder) {
- GenericSignature.FormalTypeParameter key = ((FTPHolder) typeVars[i].getUpperBound()).ftpToBeSubstituted;
- typeVars[i].setUpperBound(typeVariableResolutions.get(key));
- }
- }
- }
- }
-
- private static class FTPHolder extends ReferenceType {
- public GenericSignature.FormalTypeParameter ftpToBeSubstituted;
-
- public FTPHolder(GenericSignature.FormalTypeParameter ftp, World world) {
- super("Ljava/lang/Object;", world);
- this.ftpToBeSubstituted = ftp;
- }
-
- public String toString() {
- return "placeholder for TypeVariable of " + ftpToBeSubstituted.toString();
- }
-
- public ResolvedType resolve(World world) {
- return this;
- }
-
- public boolean isCacheable() {
- return false;
- }
- }
-
- public static class GenericSignatureFormatException extends Exception {
- public GenericSignatureFormatException(String explanation) {
- super(explanation);
- }
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java b/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java
deleted file mode 100644
index d1e60e1c7..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java
+++ /dev/null
@@ -1,714 +0,0 @@
-/* *******************************************************************
- * 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.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.StringTokenizer;
-
-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.JavaClass;
-import org.aspectj.apache.bcel.classfile.LineNumber;
-import org.aspectj.apache.bcel.classfile.LineNumberTable;
-import org.aspectj.apache.bcel.classfile.LocalVariable;
-import org.aspectj.apache.bcel.classfile.LocalVariableTable;
-import org.aspectj.apache.bcel.classfile.Method;
-import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
-import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
-import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.bridge.SourceLocation;
-import org.aspectj.util.GenericSignature;
-import org.aspectj.util.GenericSignature.TypeVariableSignature;
-import org.aspectj.util.GenericSignatureParser;
-import org.aspectj.weaver.AjAttribute;
-import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
-import org.aspectj.weaver.AnnotationAJ;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.ISourceContext;
-import org.aspectj.weaver.MemberKind;
-import org.aspectj.weaver.ResolvedMemberImpl;
-import org.aspectj.weaver.ResolvedPointcutDefinition;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.ShadowMunger;
-import org.aspectj.weaver.TypeVariable;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.World;
-import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException;
-
-//public final
-class BcelMethod extends ResolvedMemberImpl {
-
- private final static String ASPECTJ_ANNOTATION_PACKAGE = "org.aspectj.lang.annotation";
- private final static char PACKAGE_INITIAL_CHAR = ASPECTJ_ANNOTATION_PACKAGE.charAt(0);
-
- private Method method;
-
- // these fields are not set for many BcelMethods...
- private ShadowMunger associatedShadowMunger;
- private ResolvedPointcutDefinition preResolvedPointcut; // used when ajc has pre-resolved the pointcut of some @Advice
- private AjAttribute.EffectiveSignatureAttribute effectiveSignature;
-
- private AjAttribute.MethodDeclarationLineNumberAttribute declarationLineNumber;
- private final BcelObjectType bcelObjectType;
-
- private int bitflags;
- private static final int KNOW_IF_SYNTHETIC = 0x0001;
- private static final int PARAMETER_NAMES_INITIALIZED = 0x0002;
- private static final int CAN_BE_PARAMETERIZED = 0x0004;
- private static final int UNPACKED_GENERIC_SIGNATURE = 0x0008;
- private static final int IS_AJ_SYNTHETIC = 0x0040;
- private static final int IS_SYNTHETIC = 0x0080;
- private static final int IS_SYNTHETIC_INVERSE = 0x7f7f; // all bits but
- // IS_SYNTHETIC (and
- // topmost bit)
- private static final int HAS_ANNOTATIONS = 0x0400;
- private static final int HAVE_DETERMINED_ANNOTATIONS = 0x0800;
-
- // genericized version of return and parameter types
- private UnresolvedType genericReturnType = null;
- private UnresolvedType[] genericParameterTypes = null;
-
- BcelMethod(BcelObjectType declaringType, Method method) {
- super(method.getName().equals("<init>") ? CONSTRUCTOR : (method.getName().equals("<clinit>") ? STATIC_INITIALIZATION
- : METHOD), declaringType.getResolvedTypeX(), method.getModifiers(), method.getName(), method.getSignature());
- this.method = method;
- sourceContext = declaringType.getResolvedTypeX().getSourceContext();
- bcelObjectType = declaringType;
- unpackJavaAttributes();
- unpackAjAttributes(bcelObjectType.getWorld());
- }
-
- /**
- * This constructor expects to be passed the attributes, rather than deserializing them.
- */
- BcelMethod(BcelObjectType declaringType, Method method, List<AjAttribute> attributes) {
- super(method.getName().equals("<init>") ? CONSTRUCTOR : (method.getName().equals("<clinit>") ? STATIC_INITIALIZATION
- : METHOD), declaringType.getResolvedTypeX(), method.getModifiers(), method.getName(), method.getSignature());
- this.method = method;
- sourceContext = declaringType.getResolvedTypeX().getSourceContext();
- bcelObjectType = declaringType;
- unpackJavaAttributes();
- processAttributes(bcelObjectType.getWorld(), attributes);
- }
-
- // ----
-
- private void unpackJavaAttributes() {
- ExceptionTable exnTable = method.getExceptionTable();
- checkedExceptions = (exnTable == null) ? UnresolvedType.NONE : UnresolvedType.forNames(exnTable.getExceptionNames());
- }
-
- @Override
- public String[] getParameterNames() {
- determineParameterNames();
- return super.getParameterNames();
- }
-
- public int getLineNumberOfFirstInstruction() {
- LineNumberTable lnt = method.getLineNumberTable();
- if (lnt == null) {
- return -1;
- }
- LineNumber[] lns = lnt.getLineNumberTable();
- if (lns == null || lns.length == 0) {
- return -1;
- }
- return lns[0].getLineNumber();
- }
-
- public void determineParameterNames() {
- if ((bitflags & PARAMETER_NAMES_INITIALIZED) != 0) {
- return;
- }
- bitflags |= PARAMETER_NAMES_INITIALIZED;
- LocalVariableTable varTable = method.getLocalVariableTable();
- int len = getArity();
- if (varTable == null) {
- // do we have an annotation with the argNames value specified...
- AnnotationAJ[] annos = getAnnotations();
- if (annos != null && annos.length != 0) {
- AnnotationAJ[] axs = getAnnotations();
- for (int i = 0; i < axs.length; i++) {
- AnnotationAJ annotationX = axs[i];
- String typename = annotationX.getTypeName();
- if (typename.charAt(0) == PACKAGE_INITIAL_CHAR) {
- 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 = ((BcelAnnotation) annotationX).getBcelAnnotation();
- if (a != null) {
- List<NameValuePair> values = a.getValues();
- for (NameValuePair nvPair : values) {
- if (nvPair.getNameString().equals("argNames")) {
- String argNames = nvPair.getValue().stringifyValue();
- StringTokenizer argNameTokenizer = new StringTokenizer(argNames, " ,");
- List<String> argsList = new ArrayList<String>();
- while (argNameTokenizer.hasMoreTokens()) {
- argsList.add(argNameTokenizer.nextToken());
- }
- int requiredCount = getParameterTypes().length;
- while (argsList.size() < requiredCount) {
- argsList.add("arg" + argsList.size());
- }
- setParameterNames(argsList.toArray(new String[] {}));
- return;
- }
- }
- }
- }
- }
- }
- }
- setParameterNames(Utility.makeArgNames(len));
- } else {
- UnresolvedType[] paramTypes = getParameterTypes();
- String[] paramNames = new String[len];
- int index = Modifier.isStatic(modifiers) ? 0 : 1;
- for (int i = 0; i < len; i++) {
- LocalVariable lv = varTable.getLocalVariable(index);
- if (lv == null) {
- paramNames[i] = "arg" + i;
- } else {
- paramNames[i] = lv.getName();
- }
- index += paramTypes[i].getSize();
- }
- setParameterNames(paramNames);
- }
- }
-
- private void unpackAjAttributes(World world) {
- associatedShadowMunger = null;
- ResolvedType resolvedDeclaringType = getDeclaringType().resolve(world);
- WeaverVersionInfo wvinfo = bcelObjectType.getWeaverVersionAttribute();
- List<AjAttribute> as = Utility.readAjAttributes(resolvedDeclaringType.getClassName(), method.getAttributes(),
- resolvedDeclaringType.getSourceContext(), world, wvinfo, new BcelConstantPoolReader(method.getConstantPool()));
- processAttributes(world, as);
- as = AtAjAttributes.readAj5MethodAttributes(method, this, resolvedDeclaringType, preResolvedPointcut,
- resolvedDeclaringType.getSourceContext(), world.getMessageHandler());
- processAttributes(world, as);
- }
-
- private void processAttributes(World world, List<AjAttribute> as) {
- for (AjAttribute attr : as) {
- if (attr instanceof AjAttribute.MethodDeclarationLineNumberAttribute) {
- declarationLineNumber = (AjAttribute.MethodDeclarationLineNumberAttribute) attr;
- } else if (attr instanceof AjAttribute.AdviceAttribute) {
- associatedShadowMunger = ((AjAttribute.AdviceAttribute) attr).reify(this, world, (ResolvedType) getDeclaringType());
- } else if (attr instanceof AjAttribute.AjSynthetic) {
- bitflags |= IS_AJ_SYNTHETIC;
- } else if (attr instanceof AjAttribute.EffectiveSignatureAttribute) {
- effectiveSignature = (AjAttribute.EffectiveSignatureAttribute) attr;
- } else if (attr instanceof AjAttribute.PointcutDeclarationAttribute) {
- // this is an @AspectJ annotated advice method, with pointcut pre-resolved by ajc
- preResolvedPointcut = ((AjAttribute.PointcutDeclarationAttribute) attr).reify();
- } else {
- throw new BCException("weird method attribute " + attr);
- }
- }
- }
-
- //
- // // for testing - if we have this attribute, return it - will return null
- // if
- // // it doesnt know anything
- // public AjAttribute[] getAttributes(String name) {
- // List results = new ArrayList();
- // List l = Utility.readAjAttributes(getDeclaringType().getClassName(),
- // method.getAttributes(),
- // getSourceContext(bcelObjectType.getWorld()), bcelObjectType.getWorld(),
- // bcelObjectType.getWeaverVersionAttribute());
- // for (Iterator iter = l.iterator(); iter.hasNext();) {
- // AjAttribute element = (AjAttribute) iter.next();
- // if (element.getNameString().equals(name))
- // results.add(element);
- // }
- // if (results.size() > 0) {
- // return (AjAttribute[]) results.toArray(new AjAttribute[] {});
- // }
- // return null;
- // }
-
- @Override
- 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();
- List<String> names = new ArrayList<String>();
- // String[] strs = new String[as.length];
- for (int j = 0; j < as.length; j++) {
- if (!onlyIncludeAjOnes || as[j].getName().startsWith(AjAttribute.AttributePrefix)) {
- names.add(as[j].getName());
- }
- }
- return names.toArray(new String[] {});
- }
-
- @Override
- public boolean isAjSynthetic() {
- return (bitflags & IS_AJ_SYNTHETIC) != 0;
- }
-
- @Override
- public ShadowMunger getAssociatedShadowMunger() {
- return associatedShadowMunger;
- }
-
- @Override
- public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature() {
- return effectiveSignature;
- }
-
- public boolean hasDeclarationLineNumberInfo() {
- return declarationLineNumber != null;
- }
-
- public int getDeclarationLineNumber() {
- if (declarationLineNumber != null) {
- return declarationLineNumber.getLineNumber();
- } else {
- return -1;
- }
- }
-
- public int getDeclarationOffset() {
- if (declarationLineNumber != null) {
- return declarationLineNumber.getOffset();
- } else {
- return -1;
- }
- }
-
- @Override
- public ISourceLocation getSourceLocation() {
- ISourceLocation ret = super.getSourceLocation();
- if ((ret == null || ret.getLine() == 0) && hasDeclarationLineNumberInfo()) {
- // lets see if we can do better
- ISourceContext isc = getSourceContext();
- if (isc != null) {
- ret = isc.makeSourceLocation(getDeclarationLineNumber(), getDeclarationOffset());
- } else {
- ret = new SourceLocation(null, getDeclarationLineNumber());
- }
- }
- return ret;
- }
-
- @Override
- public MemberKind getKind() {
- if (associatedShadowMunger != null) {
- return ADVICE;
- } else {
- return super.getKind();
- }
- }
-
- @Override
- public boolean hasAnnotation(UnresolvedType ofType) {
- ensureAnnotationsRetrieved();
- for (ResolvedType aType : annotationTypes) {
- if (aType.equals(ofType)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public AnnotationAJ[] getAnnotations() {
- ensureAnnotationsRetrieved();
- if ((bitflags & HAS_ANNOTATIONS) != 0) {
- return annotations;
- } else {
- return AnnotationAJ.EMPTY_ARRAY;
- }
- }
-
- @Override
- public ResolvedType[] getAnnotationTypes() {
- ensureAnnotationsRetrieved();
- return annotationTypes;
- }
-
- @Override
- public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
- ensureAnnotationsRetrieved();
- if ((bitflags & HAS_ANNOTATIONS) == 0) {
- return null;
- }
- for (int i = 0; i < annotations.length; i++) {
- if (annotations[i].getTypeName().equals(ofType.getName())) {
- return annotations[i];
- }
- }
- return null;
- }
-
- @Override
- public void addAnnotation(AnnotationAJ annotation) {
- ensureAnnotationsRetrieved();
- if ((bitflags & HAS_ANNOTATIONS) == 0) {
- annotations = new AnnotationAJ[1];
- annotations[0] = annotation;
- annotationTypes = new ResolvedType[1];
- annotationTypes[0] = annotation.getType();
- } else {
- // Add it to the set of annotations
- int len = annotations.length;
- AnnotationAJ[] ret = new AnnotationAJ[len + 1];
- System.arraycopy(annotations, 0, ret, 0, len);
- ret[len] = annotation;
- annotations = ret;
- ResolvedType[] newAnnotationTypes = new ResolvedType[len + 1];
- System.arraycopy(annotationTypes, 0, newAnnotationTypes, 0, len);
- newAnnotationTypes[len] = annotation.getType();
- annotationTypes = newAnnotationTypes;
- }
- bitflags |= HAS_ANNOTATIONS;
- }
-
- public void removeAnnotation(ResolvedType annotationType) {
- ensureAnnotationsRetrieved();
- if ((bitflags & HAS_ANNOTATIONS) == 0) {
- // nothing to do, why did we get called?
- } else {
- int len = annotations.length;
- if (len == 1) {
- bitflags &= ~HAS_ANNOTATIONS;
- annotations = null;
- annotationTypes = null;
- return;
- }
- AnnotationAJ[] ret = new AnnotationAJ[len - 1];
- int p = 0;
- for (AnnotationAJ annotation : annotations) {
- if (!annotation.getType().equals(annotationType)) {
- ret[p++] = annotation;
- }
- }
- annotations = ret;
-
- ResolvedType[] newAnnotationTypes = new ResolvedType[len - 1];
- p = 0;
- for (AnnotationAJ annotation : annotations) {
- if (!annotation.getType().equals(annotationType)) {
- newAnnotationTypes[p++] = annotationType;
- }
- }
- annotationTypes = newAnnotationTypes;
- }
- bitflags |= HAS_ANNOTATIONS;
- }
-
- public static final AnnotationAJ[] NO_PARAMETER_ANNOTATIONS = new AnnotationAJ[] {};
-
- public void addParameterAnnotation(int param, AnnotationAJ anno) {
- ensureParameterAnnotationsRetrieved();
- if (parameterAnnotations == NO_PARAMETER_ANNOTATIONXS) {
- // First time we've added any, so lets set up the array
- parameterAnnotations = new AnnotationAJ[getArity()][];
- for (int i = 0; i < getArity(); i++) {
- parameterAnnotations[i] = NO_PARAMETER_ANNOTATIONS;
- }
- }
- int existingCount = parameterAnnotations[param].length;
- if (existingCount == 0) {
- AnnotationAJ[] annoArray = new AnnotationAJ[1];
- annoArray[0] = anno;
- parameterAnnotations[param] = annoArray;
- } else {
- AnnotationAJ[] newAnnoArray = new AnnotationAJ[existingCount + 1];
- System.arraycopy(parameterAnnotations[param], 0, newAnnoArray, 0, existingCount);
- newAnnoArray[existingCount] = anno;
- parameterAnnotations[param] = newAnnoArray;
- }
- }
-
- 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;
- AnnotationGen annos[] = method.getAnnotations();
- if (annos.length == 0) {
- annotationTypes = ResolvedType.NONE;
- annotations = AnnotationAJ.EMPTY_ARRAY;
- } else {
- int annoCount = annos.length;
- annotationTypes = new ResolvedType[annoCount];
- annotations = new AnnotationAJ[annoCount];
- for (int i = 0; i < annoCount; i++) {
- AnnotationGen annotation = annos[i];
- annotations[i] = new BcelAnnotation(annotation, bcelObjectType.getWorld());
- annotationTypes[i] = annotations[i].getType();
- }
- bitflags |= HAS_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 AnnotationAJ[annos.length][];
- parameterAnnotationTypes = new ResolvedType[annos.length][];
- for (int i = 0; i < annos.length; i++) {
- AnnotationGen[] annosOnThisParam = annos[i];
- if (annos[i].length == 0) {
- parameterAnnotations[i] = AnnotationAJ.EMPTY_ARRAY;
- parameterAnnotationTypes[i] = ResolvedType.NONE;
- } else {
- parameterAnnotations[i] = new AnnotationAJ[annosOnThisParam.length];
- parameterAnnotationTypes[i] = new ResolvedType[annosOnThisParam.length];
- for (int j = 0; j < annosOnThisParam.length; j++) {
- parameterAnnotations[i][j] = new BcelAnnotation(annosOnThisParam[j], bcelObjectType.getWorld());
- parameterAnnotationTypes[i][j] = bcelObjectType.getWorld().resolve(
- UnresolvedType.forSignature(annosOnThisParam[j].getTypeSignature()));
- }
- }
- }
- }
- }
- }
-
- @Override
- public AnnotationAJ[][] getParameterAnnotations() {
- ensureParameterAnnotationsRetrieved();
- return parameterAnnotations;
- }
-
- @Override
- public ResolvedType[][] getParameterAnnotationTypes() {
- ensureParameterAnnotationsRetrieved();
- return parameterAnnotationTypes;
- }
-
- /**
- * A method can be parameterized if it has one or more generic parameters. A generic parameter (type variable parameter) is
- * identified by the prefix "T"
- */
- @Override
- public boolean canBeParameterized() {
- unpackGenericSignature();
- return (bitflags & CAN_BE_PARAMETERIZED) != 0;
- }
-
- @Override
- public UnresolvedType[] getGenericParameterTypes() {
- unpackGenericSignature();
- return genericParameterTypes;
- }
-
- /**
- * Return the parameterized/generic return type or the normal return type if the method is not generic.
- */
- @Override
- public UnresolvedType getGenericReturnType() {
- unpackGenericSignature();
- return genericReturnType;
- }
-
- /** For testing only */
- public Method getMethod() {
- return method;
- }
-
- private void unpackGenericSignature() {
- if ((bitflags & UNPACKED_GENERIC_SIGNATURE) != 0) {
- return;
- }
- bitflags |= UNPACKED_GENERIC_SIGNATURE;
- if (!bcelObjectType.getWorld().isInJava5Mode()) {
- genericReturnType = getReturnType();
- genericParameterTypes = getParameterTypes();
- return;
- }
- String gSig = method.getGenericSignature();
- if (gSig != null) {
- GenericSignature.MethodTypeSignature mSig = new GenericSignatureParser().parseAsMethodSignature(gSig);// method
- // .
- // getGenericSignature
- // ());
- if (mSig.formalTypeParameters.length > 0) {
- // generic method declaration
- bitflags |= CAN_BE_PARAMETERIZED;
- }
-
- typeVariables = new TypeVariable[mSig.formalTypeParameters.length];
- for (int i = 0; i < typeVariables.length; i++) {
- GenericSignature.FormalTypeParameter methodFtp = mSig.formalTypeParameters[i];
- try {
- typeVariables[i] = BcelGenericSignatureToTypeXConverter.formalTypeParameter2TypeVariable(methodFtp,
- mSig.formalTypeParameters, bcelObjectType.getWorld());
- } catch (GenericSignatureFormatException e) {
- // this is a development bug, so fail fast with good info
- throw new IllegalStateException("While getting the type variables for method " + this.toString()
- + " with generic signature " + mSig + " the following error condition was detected: " + e.getMessage());
- }
- }
-
- GenericSignature.FormalTypeParameter[] parentFormals = bcelObjectType.getAllFormals();
- GenericSignature.FormalTypeParameter[] formals = new GenericSignature.FormalTypeParameter[parentFormals.length
- + mSig.formalTypeParameters.length];
- // put method formal in front of type formals for overriding in
- // lookup
- System.arraycopy(mSig.formalTypeParameters, 0, formals, 0, mSig.formalTypeParameters.length);
- System.arraycopy(parentFormals, 0, formals, mSig.formalTypeParameters.length, parentFormals.length);
- GenericSignature.TypeSignature returnTypeSignature = mSig.returnType;
- try {
- genericReturnType = BcelGenericSignatureToTypeXConverter.typeSignature2TypeX(returnTypeSignature, formals,
- bcelObjectType.getWorld());
- } catch (GenericSignatureFormatException e) {
- // development bug, fail fast with good info
- throw new IllegalStateException("While determing the generic return type of " + this.toString()
- + " with generic signature " + gSig + " the following error was detected: " + e.getMessage());
- }
- GenericSignature.TypeSignature[] paramTypeSigs = mSig.parameters;
- if (paramTypeSigs.length == 0) {
- genericParameterTypes = UnresolvedType.NONE;
- } else {
- genericParameterTypes = new UnresolvedType[paramTypeSigs.length];
- }
- for (int i = 0; i < paramTypeSigs.length; i++) {
- try {
- genericParameterTypes[i] = BcelGenericSignatureToTypeXConverter.typeSignature2TypeX(paramTypeSigs[i], formals,
- bcelObjectType.getWorld());
- } catch (GenericSignatureFormatException e) {
- // development bug, fail fast with good info
- throw new IllegalStateException("While determining the generic parameter types of " + this.toString()
- + " with generic signature " + gSig + " the following error was detected: " + e.getMessage());
- }
- if (paramTypeSigs[i] instanceof TypeVariableSignature) {
- bitflags |= CAN_BE_PARAMETERIZED;
- }
- }
- } else {
- genericReturnType = getReturnType();
- genericParameterTypes = getParameterTypes();
- }
- }
-
- @Override
- public void evictWeavingState() {
- if (method != null) {
- unpackGenericSignature();
- unpackJavaAttributes();
- ensureAnnotationsRetrieved();
- ensureParameterAnnotationsRetrieved();
- determineParameterNames();
- // this.sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT;
- method = null;
- }
- }
-
- @Override
- public boolean isSynthetic() {
- if ((bitflags & KNOW_IF_SYNTHETIC) == 0) {
- workOutIfSynthetic();
- }
- return (bitflags & IS_SYNTHETIC) != 0;// isSynthetic;
- }
-
- // Pre Java5 synthetic is an attribute 'Synthetic', post Java5 it is a
- // modifier (4096 or 0x1000)
- private void workOutIfSynthetic() {
- if ((bitflags & KNOW_IF_SYNTHETIC) != 0) {
- return;
- }
- bitflags |= KNOW_IF_SYNTHETIC;
- JavaClass jc = bcelObjectType.getJavaClass();
- bitflags &= IS_SYNTHETIC_INVERSE; // unset the bit
- if (jc == null) {
- return; // what the hell has gone wrong?
- }
- if (jc.getMajor() < 49/* Java5 */) {
- // synthetic is an attribute
- String[] synthetics = getAttributeNames(false);
- if (synthetics != null) {
- for (int i = 0; i < synthetics.length; i++) {
- if (synthetics[i].equals("Synthetic")) {
- bitflags |= IS_SYNTHETIC;
- break;
- }
- }
- }
- } else {
- // synthetic is a modifier (4096)
- if ((modifiers & 4096) != 0) {
- bitflags |= IS_SYNTHETIC;
- }
- }
- }
-
- /**
- * Returns whether or not the given object is equivalent to the current one. Returns true if
- * getMethod().getCode().getCodeString() are equal. Allows for different line number tables.
- */
- // bug 154054: is similar to equals(Object) however
- // doesn't require implementing equals in Method and Code
- // which proved expensive. Currently used within
- // CrosscuttingMembers.replaceWith() to decide if we need
- // to do a full build
- @Override
- public boolean isEquivalentTo(Object other) {
- if (!(other instanceof BcelMethod)) {
- return false;
- }
- BcelMethod o = (BcelMethod) other;
- return getMethod().getCode().getCodeString().equals(o.getMethod().getCode().getCodeString());
- }
-
- /**
- * Return true if the method represents the default constructor. Hard to determine this from bytecode, but the existence of the
- * MethodDeclarationLineNumber attribute should tell us.
- *
- * @return true if this BcelMethod represents the default constructor
- */
- @Override
- public boolean isDefaultConstructor() {
- boolean mightBe = !hasDeclarationLineNumberInfo() && name.equals("<init>") && parameterTypes.length == 0;
- if (mightBe) {
- // TODO would be nice to do a check to see if the file was compiled with javac or ajc?
- // maybe by checking the constant pool for aspectj strings?
- return true;
- } else {
- return false;
- }
- }
-
-} \ No newline at end of file
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
deleted file mode 100644
index 710eb6dc7..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
+++ /dev/null
@@ -1,1023 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2002 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:
- * PARC initial implementation
- * RonBodkin/AndyClement optimizations for memory consumption/speed
- * ******************************************************************/
-
-package org.aspectj.weaver.bcel;
-
-import java.io.PrintStream;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import org.aspectj.apache.bcel.classfile.Attribute;
-import org.aspectj.apache.bcel.classfile.AttributeUtils;
-import org.aspectj.apache.bcel.classfile.ConstantClass;
-import org.aspectj.apache.bcel.classfile.ConstantPool;
-import org.aspectj.apache.bcel.classfile.EnclosingMethod;
-import org.aspectj.apache.bcel.classfile.Field;
-import org.aspectj.apache.bcel.classfile.InnerClass;
-import org.aspectj.apache.bcel.classfile.InnerClasses;
-import org.aspectj.apache.bcel.classfile.JavaClass;
-import org.aspectj.apache.bcel.classfile.Method;
-import org.aspectj.apache.bcel.classfile.Signature;
-import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
-import org.aspectj.apache.bcel.classfile.annotation.EnumElementValue;
-import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
-import org.aspectj.asm.AsmManager;
-import org.aspectj.bridge.IMessageHandler;
-import org.aspectj.bridge.MessageUtil;
-import org.aspectj.util.GenericSignature;
-import org.aspectj.util.GenericSignature.FormalTypeParameter;
-import org.aspectj.weaver.AbstractReferenceTypeDelegate;
-import org.aspectj.weaver.AjAttribute;
-import org.aspectj.weaver.AjcMemberMaker;
-import org.aspectj.weaver.AnnotationAJ;
-import org.aspectj.weaver.AnnotationTargetKind;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.BindingScope;
-import org.aspectj.weaver.ConcreteTypeMunger;
-import org.aspectj.weaver.ISourceContext;
-import org.aspectj.weaver.ReferenceType;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedPointcutDefinition;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.SourceContextImpl;
-import org.aspectj.weaver.TypeVariable;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.WeaverStateInfo;
-import org.aspectj.weaver.World;
-import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException;
-import org.aspectj.weaver.patterns.Declare;
-import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
-import org.aspectj.weaver.patterns.DeclarePrecedence;
-import org.aspectj.weaver.patterns.FormalBinding;
-import org.aspectj.weaver.patterns.IScope;
-import org.aspectj.weaver.patterns.PerClause;
-
-public class BcelObjectType extends AbstractReferenceTypeDelegate {
- public JavaClass javaClass;
- private boolean artificial; // Was the BcelObject built from an artificial set of bytes? Or from the real ondisk stuff?
- private LazyClassGen lazyClassGen = null; // set lazily if it's an aspect
-
- private int modifiers;
- private String className;
-
- private String superclassSignature;
- private String superclassName;
- private String[] interfaceSignatures;
-
- private ResolvedMember[] fields = null;
- private ResolvedMember[] methods = null;
- private ResolvedType[] annotationTypes = null;
- private AnnotationAJ[] annotations = null;
- private TypeVariable[] typeVars = null;
- private String retentionPolicy;
- private AnnotationTargetKind[] annotationTargetKinds;
-
- // Aspect related stuff (pointcuts *could* be in a java class)
- private AjAttribute.WeaverVersionInfo wvInfo = AjAttribute.WeaverVersionInfo.UNKNOWN;
- private ResolvedPointcutDefinition[] pointcuts = null;
- private ResolvedMember[] privilegedAccess = null;
- private WeaverStateInfo weaverState = null;
- private PerClause perClause = null;
- private List<ConcreteTypeMunger> typeMungers = Collections.emptyList();
- private List<Declare> declares = Collections.emptyList();
-
- private GenericSignature.FormalTypeParameter[] formalsForResolution = null;
- private String declaredSignature = null;
-
- private boolean hasBeenWoven = false;
- private boolean isGenericType = false;
- private boolean isInterface;
- private boolean isEnum;
- private boolean isAnnotation;
- private boolean isAnonymous;
- private boolean isNested;
- private boolean isObject = false; // set upon construction
- private boolean isAnnotationStyleAspect = false;// set upon construction
- private boolean isCodeStyleAspect = false; // not redundant with field
- // above!
-
- private WeakReference<ResolvedType> superTypeReference = new WeakReference<ResolvedType>(null);
- private WeakReference<ResolvedType[]> superInterfaceReferences = new WeakReference<ResolvedType[]>(null);
-
- private int bitflag = 0x0000;
-
- // discovery bits
- private static final int DISCOVERED_ANNOTATION_RETENTION_POLICY = 0x0001;
- private static final int UNPACKED_GENERIC_SIGNATURE = 0x0002;
- private static final int UNPACKED_AJATTRIBUTES = 0x0004; // see note(1)
- // below
- private static final int DISCOVERED_ANNOTATION_TARGET_KINDS = 0x0008;
- private static final int DISCOVERED_DECLARED_SIGNATURE = 0x0010;
- private static final int DISCOVERED_WHETHER_ANNOTATION_STYLE = 0x0020;
-
- private static final int ANNOTATION_UNPACK_IN_PROGRESS = 0x0100;
-
- private static final String[] NO_INTERFACE_SIGS = new String[] {};
-
- /*
- * Notes: note(1): in some cases (perclause inheritance) we encounter unpacked state when calling getPerClause
- *
- * note(2): A BcelObjectType is 'damaged' if it has been modified from what was original constructed from the bytecode. This
- * currently happens if the parents are modified or an annotation is added - ideally BcelObjectType should be immutable but
- * that's a bigger piece of work. XXX
- */
-
- BcelObjectType(ReferenceType resolvedTypeX, JavaClass javaClass, boolean artificial, boolean exposedToWeaver) {
- super(resolvedTypeX, exposedToWeaver);
- this.javaClass = javaClass;
- this.artificial = artificial;
- initializeFromJavaclass();
-
- // ATAJ: set the delegate right now for @AJ pointcut, else it is done
- // too late to lookup
- // @AJ pc refs annotation in class hierarchy
- resolvedTypeX.setDelegate(this);
-
- ISourceContext sourceContext = resolvedTypeX.getSourceContext();
- if (sourceContext == SourceContextImpl.UNKNOWN_SOURCE_CONTEXT) {
- sourceContext = new SourceContextImpl(this);
- setSourceContext(sourceContext);
- }
-
- // this should only ever be java.lang.Object which is
- // the only class in Java-1.4 with no superclasses
- isObject = (javaClass.getSuperclassNameIndex() == 0);
- ensureAspectJAttributesUnpacked();
- // if (sourceContext instanceof SourceContextImpl) {
- // ((SourceContextImpl)sourceContext).setSourceFileName(javaClass.
- // getSourceFileName());
- // }
- setSourcefilename(javaClass.getSourceFileName());
- }
-
- // repeat initialization
- public void setJavaClass(JavaClass newclass, boolean artificial) {
- this.javaClass = newclass;
- this.artificial = artificial;
- resetState();
- initializeFromJavaclass();
- }
-
- @Override
- public boolean isCacheable() {
- return true;
- }
-
- private void initializeFromJavaclass() {
- isInterface = javaClass.isInterface();
- isEnum = javaClass.isEnum();
- isAnnotation = javaClass.isAnnotation();
- isAnonymous = javaClass.isAnonymous();
- isNested = javaClass.isNested();
- modifiers = javaClass.getModifiers();
- superclassName = javaClass.getSuperclassName();
- className = javaClass.getClassName();
- cachedGenericClassTypeSignature = null;
- }
-
- // --- getters
-
- // Java related
- public boolean isInterface() {
- return isInterface;
- }
-
- public boolean isEnum() {
- return isEnum;
- }
-
- public boolean isAnnotation() {
- return isAnnotation;
- }
-
- public boolean isAnonymous() {
- return isAnonymous;
- }
-
- public boolean isNested() {
- return isNested;
- }
-
- public int getModifiers() {
- return modifiers;
- }
-
- /**
- * Must take into account generic signature
- */
- public ResolvedType getSuperclass() {
- if (isObject) {
- return null;
- }
- ResolvedType supertype = superTypeReference.get();
- if (supertype == null) {
- ensureGenericSignatureUnpacked();
- if (superclassSignature == null) {
- if (superclassName == null) {
- superclassName = javaClass.getSuperclassName();
- }
- superclassSignature = getResolvedTypeX().getWorld().resolve(UnresolvedType.forName(superclassName)).getSignature();
- }
- World world = getResolvedTypeX().getWorld();
- supertype = world.resolve(UnresolvedType.forSignature(superclassSignature));
- superTypeReference = new WeakReference<ResolvedType>(supertype);
- }
- return supertype;
- }
-
- public World getWorld() {
- return getResolvedTypeX().getWorld();
- }
-
- /**
- * Retrieves the declared interfaces - this allows for the generic signature on a type. If specified then the generic signature
- * is used to work out the types - this gets around the results of erasure when the class was originally compiled.
- */
- public ResolvedType[] getDeclaredInterfaces() {
-
- ResolvedType[] cachedInterfaceTypes = superInterfaceReferences.get();
- if (cachedInterfaceTypes == null) {
- ensureGenericSignatureUnpacked();
- ResolvedType[] interfaceTypes = null;
- if (interfaceSignatures == null) {
- String[] names = javaClass.getInterfaceNames();
- if (names.length == 0) {
- interfaceSignatures = NO_INTERFACE_SIGS;
- interfaceTypes = ResolvedType.NONE;
- } else {
- interfaceSignatures = new String[names.length];
- interfaceTypes = new ResolvedType[names.length];
- for (int i = 0, len = names.length; i < len; i++) {
- interfaceTypes[i] = getResolvedTypeX().getWorld().resolve(UnresolvedType.forName(names[i]));
- interfaceSignatures[i] = interfaceTypes[i].getSignature();
- }
- }
- } else {
- interfaceTypes = new ResolvedType[interfaceSignatures.length];
- for (int i = 0, len = interfaceSignatures.length; i < len; i++) {
- interfaceTypes[i] = getResolvedTypeX().getWorld().resolve(UnresolvedType.forSignature(interfaceSignatures[i]));
- }
- }
- superInterfaceReferences = new WeakReference<ResolvedType[]>(interfaceTypes);
- return interfaceTypes;
- } else {
- return cachedInterfaceTypes;
- }
- }
-
- public ResolvedMember[] getDeclaredMethods() {
- ensureGenericSignatureUnpacked();
- if (methods == null) {
- Method[] ms = javaClass.getMethods();
- ResolvedMember[] newMethods = new ResolvedMember[ms.length];
- for (int i = ms.length - 1; i >= 0; i--) {
- newMethods[i] = new BcelMethod(this, ms[i]);
- }
- methods = newMethods;
- }
- return methods;
- }
-
- public ResolvedMember[] getDeclaredFields() {
- ensureGenericSignatureUnpacked();
- if (fields == null) {
- Field[] fs = javaClass.getFields();
- ResolvedMember[] newfields = new ResolvedMember[fs.length];
- for (int i = 0, len = fs.length; i < len; i++) {
- newfields[i] = new BcelField(this, fs[i]);
- }
- fields = newfields;
- }
- return fields;
- }
-
- public TypeVariable[] getTypeVariables() {
- if (!isGeneric()) {
- return TypeVariable.NONE;
- }
-
- if (typeVars == null) {
- GenericSignature.ClassSignature classSig = getGenericClassTypeSignature();
- typeVars = new TypeVariable[classSig.formalTypeParameters.length];
- for (int i = 0; i < typeVars.length; i++) {
- GenericSignature.FormalTypeParameter ftp = classSig.formalTypeParameters[i];
- try {
- typeVars[i] = BcelGenericSignatureToTypeXConverter.formalTypeParameter2TypeVariable(ftp,
- classSig.formalTypeParameters, getResolvedTypeX().getWorld());
- } catch (GenericSignatureFormatException e) {
- // this is a development bug, so fail fast with good info
- throw new IllegalStateException("While getting the type variables for type " + this.toString()
- + " with generic signature " + classSig + " the following error condition was detected: "
- + e.getMessage());
- }
- }
- }
- return typeVars;
- }
-
- public Collection<ConcreteTypeMunger> getTypeMungers() {
- return typeMungers;
- }
-
- public Collection<Declare> getDeclares() {
- return declares;
- }
-
- public Collection<ResolvedMember> getPrivilegedAccesses() {
- if (privilegedAccess == null) {
- return Collections.emptyList();
- }
- return Arrays.asList(privilegedAccess);
- }
-
- public ResolvedMember[] getDeclaredPointcuts() {
- return pointcuts;
- }
-
- public boolean isAspect() {
- return perClause != null;
- }
-
- /**
- * Check if the type is an @AJ aspect (no matter if used from an LTW point of view). Such aspects are annotated with @Aspect
- *
- * @return true for @AJ aspect
- */
- public boolean isAnnotationStyleAspect() {
- if ((bitflag & DISCOVERED_WHETHER_ANNOTATION_STYLE) == 0) {
- bitflag |= DISCOVERED_WHETHER_ANNOTATION_STYLE;
- isAnnotationStyleAspect = !isCodeStyleAspect && hasAnnotation(AjcMemberMaker.ASPECT_ANNOTATION);
- }
- return isAnnotationStyleAspect;
- }
-
- /**
- * Process any org.aspectj.weaver attributes stored against the class.
- */
- private void ensureAspectJAttributesUnpacked() {
- if ((bitflag & UNPACKED_AJATTRIBUTES) != 0) {
- return;
- }
- bitflag |= UNPACKED_AJATTRIBUTES;
- IMessageHandler msgHandler = getResolvedTypeX().getWorld().getMessageHandler();
- // Pass in empty list that can store things for readAj5 to process
- List<AjAttribute> l = null;
- try {
- l = Utility.readAjAttributes(className, javaClass.getAttributes(), getResolvedTypeX().getSourceContext(),
- getResolvedTypeX().getWorld(), AjAttribute.WeaverVersionInfo.UNKNOWN,
- new BcelConstantPoolReader(javaClass.getConstantPool()));
- } catch (RuntimeException re) {
- throw new RuntimeException("Problem processing attributes in " + javaClass.getFileName(), re);
- }
- List<ResolvedPointcutDefinition> pointcuts = new ArrayList<ResolvedPointcutDefinition>();
- typeMungers = new ArrayList<ConcreteTypeMunger>();
- declares = new ArrayList<Declare>();
- processAttributes(l, pointcuts, false);
- ReferenceType type = getResolvedTypeX();
- AsmManager asmManager = ((BcelWorld) type.getWorld()).getModelAsAsmManager();
- l = AtAjAttributes.readAj5ClassAttributes(asmManager, javaClass, type, type.getSourceContext(), msgHandler,
- isCodeStyleAspect);
- AjAttribute.Aspect deferredAspectAttribute = processAttributes(l, pointcuts, true);
-
- if (pointcuts.size() == 0) {
- this.pointcuts = ResolvedPointcutDefinition.NO_POINTCUTS;
- } else {
- this.pointcuts = pointcuts.toArray(new ResolvedPointcutDefinition[pointcuts.size()]);
- }
-
- resolveAnnotationDeclares(l);
-
- if (deferredAspectAttribute != null) {
- // we can finally process the aspect and its associated perclause...
- perClause = deferredAspectAttribute.reifyFromAtAspectJ(this.getResolvedTypeX());
- }
- if (isAspect() && !Modifier.isAbstract(getModifiers()) && isGeneric()) {
- msgHandler.handleMessage(MessageUtil.error("The generic aspect '" + getResolvedTypeX().getName()
- + "' must be declared abstract", getResolvedTypeX().getSourceLocation()));
- }
-
- }
-
- private AjAttribute.Aspect processAttributes(List<AjAttribute> attributeList, List<ResolvedPointcutDefinition> pointcuts,
- boolean fromAnnotations) {
- AjAttribute.Aspect deferredAspectAttribute = null;
- for (AjAttribute a : attributeList) {
- if (a instanceof AjAttribute.Aspect) {
- if (fromAnnotations) {
- deferredAspectAttribute = (AjAttribute.Aspect) a;
- } else {
- perClause = ((AjAttribute.Aspect) a).reify(this.getResolvedTypeX());
- isCodeStyleAspect = true;
- }
- } else if (a instanceof AjAttribute.PointcutDeclarationAttribute) {
- pointcuts.add(((AjAttribute.PointcutDeclarationAttribute) a).reify());
- } else if (a instanceof AjAttribute.WeaverState) {
- weaverState = ((AjAttribute.WeaverState) a).reify();
- } else if (a instanceof AjAttribute.TypeMunger) {
- typeMungers.add(((AjAttribute.TypeMunger) a).reify(getResolvedTypeX().getWorld(), getResolvedTypeX()));
- } else if (a instanceof AjAttribute.DeclareAttribute) {
- declares.add(((AjAttribute.DeclareAttribute) a).getDeclare());
- } else if (a instanceof AjAttribute.PrivilegedAttribute) {
- AjAttribute.PrivilegedAttribute privAttribute = (AjAttribute.PrivilegedAttribute) a;
- privilegedAccess = privAttribute.getAccessedMembers();
- } else if (a instanceof AjAttribute.SourceContextAttribute) {
- if (getResolvedTypeX().getSourceContext() instanceof SourceContextImpl) {
- AjAttribute.SourceContextAttribute sca = (AjAttribute.SourceContextAttribute) a;
- ((SourceContextImpl) getResolvedTypeX().getSourceContext()).configureFromAttribute(sca.getSourceFileName(),
- sca.getLineBreaks());
-
- setSourcefilename(sca.getSourceFileName());
- }
- } else if (a instanceof AjAttribute.WeaverVersionInfo) {
- // Set the weaver version used to build this type
- wvInfo = (AjAttribute.WeaverVersionInfo) a;
- } else {
- throw new BCException("bad attribute " + a);
- }
- }
- return deferredAspectAttribute;
- }
-
- /**
- * Extra processing step needed because declares that come from annotations are not pre-resolved. We can't do the resolution
- * until *after* the pointcuts have been resolved.
- */
- private void resolveAnnotationDeclares(List<AjAttribute> attributeList) {
- FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
- IScope bindingScope = new BindingScope(getResolvedTypeX(), getResolvedTypeX().getSourceContext(), bindings);
- for (Iterator<AjAttribute> iter = attributeList.iterator(); iter.hasNext();) {
- AjAttribute a = iter.next();
- if (a instanceof AjAttribute.DeclareAttribute) {
- Declare decl = (((AjAttribute.DeclareAttribute) a).getDeclare());
- if (decl instanceof DeclareErrorOrWarning) {
- decl.resolve(bindingScope);
- } else if (decl instanceof DeclarePrecedence) {
- ((DeclarePrecedence) decl).setScopeForResolution(bindingScope);
- }
- }
- }
- }
-
- public PerClause getPerClause() {
- ensureAspectJAttributesUnpacked();
- return perClause;
- }
-
- public JavaClass getJavaClass() {
- return javaClass;
- }
-
- /**
- * @return true if built from bytes obtained from somewhere. False if built from bytes retrieved from disk.
- */
- public boolean isArtificial() {
- return artificial;
- }
-
- public void resetState() {
- if (javaClass == null) {
- // we might store the classname and allow reloading?
- // At this point we are relying on the world to not evict if it
- // might want to reweave multiple times
- throw new BCException("can't weave evicted type");
- }
-
- bitflag = 0x0000;
-
- this.annotationTypes = null;
- this.annotations = null;
- this.interfaceSignatures = null;
- this.superclassSignature = null;
- this.superclassName = null;
- this.fields = null;
- this.methods = null;
- this.pointcuts = null;
- this.perClause = null;
- this.weaverState = null;
- this.lazyClassGen = null;
- hasBeenWoven = false;
-
- isObject = (javaClass.getSuperclassNameIndex() == 0);
- isAnnotationStyleAspect = false;
- ensureAspectJAttributesUnpacked();
- }
-
- public void finishedWith() {
- // memory usage experiments....
- // this.interfaces = null;
- // this.superClass = null;
- // this.fields = null;
- // this.methods = null;
- // this.pointcuts = null;
- // this.perClause = null;
- // this.weaverState = null;
- // this.lazyClassGen = null;
- // this next line frees up memory, but need to understand incremental
- // implications
- // before leaving it in.
- // getResolvedTypeX().setSourceContext(null);
- }
-
- public WeaverStateInfo getWeaverState() {
- return weaverState;
- }
-
- void setWeaverState(WeaverStateInfo weaverState) {
- this.weaverState = weaverState;
- }
-
- public void printWackyStuff(PrintStream out) {
- if (typeMungers.size() > 0) {
- out.println(" TypeMungers: " + typeMungers);
- }
- if (declares.size() > 0) {
- out.println(" declares: " + declares);
- }
- }
-
- /**
- * Return the lazyClassGen associated with this type. For aspect types, this value will be cached, since it is used to inline
- * advice. For non-aspect types, this lazyClassGen is always newly constructed.
- */
- public LazyClassGen getLazyClassGen() {
- LazyClassGen ret = lazyClassGen;
- if (ret == null) {
- // 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 );
- if (isAspect()) {
- lazyClassGen = ret;
- }
- }
- return ret;
- }
-
- public boolean isSynthetic() {
- return getResolvedTypeX().isSynthetic();
- }
-
- public AjAttribute.WeaverVersionInfo getWeaverVersionAttribute() {
- return wvInfo;
- }
-
- // -- annotation related
-
- public ResolvedType[] getAnnotationTypes() {
- ensureAnnotationsUnpacked();
- return annotationTypes;
- }
-
- public AnnotationAJ[] getAnnotations() {
- ensureAnnotationsUnpacked();
- return annotations;
- }
-
- public boolean hasAnnotations() {
- ensureAnnotationsUnpacked();
- return annotations.length != 0;
- }
-
- public boolean hasAnnotation(UnresolvedType ofType) {
- // Due to re-entrancy we may be in the middle of unpacking the annotations already... in which case use this slow
- // alternative until the stack unwinds itself
- if (isUnpackingAnnotations()) {
- AnnotationGen annos[] = javaClass.getAnnotations();
- if (annos == null || annos.length == 0) {
- return false;
- } else {
- String lookingForSignature = ofType.getSignature();
- for (int a = 0; a < annos.length; a++) {
- AnnotationGen annotation = annos[a];
- if (lookingForSignature.equals(annotation.getTypeSignature())) {
- return true;
- }
- }
- }
- return false;
- }
- ensureAnnotationsUnpacked();
- for (int i = 0, max = annotationTypes.length; i < max; i++) {
- UnresolvedType ax = annotationTypes[i];
- if (ax == null) {
- throw new RuntimeException("Annotation entry " + i + " on type " + this.getResolvedTypeX().getName() + " is null!");
- }
- if (ax.equals(ofType)) {
- return true;
- }
- }
- return false;
- }
-
- public boolean isAnnotationWithRuntimeRetention() {
- return (getRetentionPolicy() == null ? false : getRetentionPolicy().equals("RUNTIME"));
- }
-
- public String getRetentionPolicy() {
- if ((bitflag & DISCOVERED_ANNOTATION_RETENTION_POLICY) == 0) {
- bitflag |= DISCOVERED_ANNOTATION_RETENTION_POLICY;
- retentionPolicy = null; // null means we have no idea
- if (isAnnotation()) {
- ensureAnnotationsUnpacked();
- for (int i = annotations.length - 1; i >= 0; i--) {
- AnnotationAJ ax = annotations[i];
- if (ax.getTypeName().equals(UnresolvedType.AT_RETENTION.getName())) {
- List<NameValuePair> values = ((BcelAnnotation) ax).getBcelAnnotation().getValues();
- for (Iterator<NameValuePair> it = values.iterator(); it.hasNext();) {
- NameValuePair element = it.next();
- EnumElementValue v = (EnumElementValue) element.getValue();
- retentionPolicy = v.getEnumValueString();
- return retentionPolicy;
- }
- }
- }
- }
- }
- return retentionPolicy;
- }
-
- public boolean canAnnotationTargetType() {
- AnnotationTargetKind[] targetKinds = getAnnotationTargetKinds();
- if (targetKinds == null) {
- return true;
- }
- for (int i = 0; i < targetKinds.length; i++) {
- if (targetKinds[i].equals(AnnotationTargetKind.TYPE)) {
- return true;
- }
- }
- return false;
- }
-
- public AnnotationTargetKind[] getAnnotationTargetKinds() {
- if ((bitflag & DISCOVERED_ANNOTATION_TARGET_KINDS) != 0) {
- return annotationTargetKinds;
- }
- bitflag |= DISCOVERED_ANNOTATION_TARGET_KINDS;
- annotationTargetKinds = null; // null means we have no idea or the
- // @Target annotation hasn't been used
- List<AnnotationTargetKind> targetKinds = new ArrayList<AnnotationTargetKind>();
- if (isAnnotation()) {
- AnnotationAJ[] annotationsOnThisType = getAnnotations();
- for (int i = 0; i < annotationsOnThisType.length; i++) {
- AnnotationAJ a = annotationsOnThisType[i];
- if (a.getTypeName().equals(UnresolvedType.AT_TARGET.getName())) {
- Set<String> targets = a.getTargets();
- if (targets != null) {
- for (String targetKind : targets) {
- 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);
- } else if (targetKind.equals("LOCAL_VARIABLE")) {
- targetKinds.add(AnnotationTargetKind.LOCAL_VARIABLE);
- } else if (targetKind.equals("METHOD")) {
- targetKinds.add(AnnotationTargetKind.METHOD);
- } else if (targetKind.equals("PACKAGE")) {
- targetKinds.add(AnnotationTargetKind.PACKAGE);
- } else if (targetKind.equals("PARAMETER")) {
- targetKinds.add(AnnotationTargetKind.PARAMETER);
- } else if (targetKind.equals("TYPE")) {
- targetKinds.add(AnnotationTargetKind.TYPE);
- }
- }
- }
- }
- }
- if (!targetKinds.isEmpty()) {
- annotationTargetKinds = new AnnotationTargetKind[targetKinds.size()];
- return targetKinds.toArray(annotationTargetKinds);
- }
- }
- return annotationTargetKinds;
- }
-
- // --- unpacking methods
-
- private boolean isUnpackingAnnotations() {
- return (bitflag & ANNOTATION_UNPACK_IN_PROGRESS) != 0;
- }
-
- private void ensureAnnotationsUnpacked() {
- if (isUnpackingAnnotations()) {
- throw new BCException("Re-entered weaver instance whilst unpacking annotations on " + this.className);
- }
- if (annotationTypes == null) {
- try {
- bitflag |= ANNOTATION_UNPACK_IN_PROGRESS;
- AnnotationGen annos[] = javaClass.getAnnotations();
- if (annos == null || annos.length == 0) {
- annotationTypes = ResolvedType.NONE;
- annotations = AnnotationAJ.EMPTY_ARRAY;
- } else {
- World w = getResolvedTypeX().getWorld();
- annotationTypes = new ResolvedType[annos.length];
- annotations = new AnnotationAJ[annos.length];
- for (int i = 0; i < annos.length; i++) {
- AnnotationGen annotation = annos[i];
- String typeSignature = annotation.getTypeSignature();
- ResolvedType rType = w.resolve(UnresolvedType.forSignature(typeSignature));
- if (rType == null) {
- throw new RuntimeException("Whilst unpacking annotations on '" + getResolvedTypeX().getName()
- + "', failed to resolve type '" + typeSignature + "'");
- }
- annotationTypes[i] = rType;
- annotations[i] = new BcelAnnotation(annotation, rType);
- }
- }
- } finally {
- bitflag &= ~ANNOTATION_UNPACK_IN_PROGRESS;
- }
- }
- }
-
- // ---
-
- public String getDeclaredGenericSignature() {
- ensureGenericInfoProcessed();
- return declaredSignature;
- }
-
- private void ensureGenericSignatureUnpacked() {
- if ((bitflag & UNPACKED_GENERIC_SIGNATURE) != 0) {
- return;
- }
- bitflag |= UNPACKED_GENERIC_SIGNATURE;
- if (!getResolvedTypeX().getWorld().isInJava5Mode()) {
- return;
- }
- GenericSignature.ClassSignature cSig = getGenericClassTypeSignature();
- if (cSig != null) {
- formalsForResolution = cSig.formalTypeParameters;
- if (isNested()) {
- // we have to find any type variables from the outer type before
- // proceeding with resolution.
- GenericSignature.FormalTypeParameter[] extraFormals = getFormalTypeParametersFromOuterClass();
- if (extraFormals.length > 0) {
- List<FormalTypeParameter> allFormals = new ArrayList<FormalTypeParameter>();
- for (int i = 0; i < formalsForResolution.length; i++) {
- allFormals.add(formalsForResolution[i]);
- }
- for (int i = 0; i < extraFormals.length; i++) {
- allFormals.add(extraFormals[i]);
- }
- formalsForResolution = new GenericSignature.FormalTypeParameter[allFormals.size()];
- allFormals.toArray(formalsForResolution);
- }
- }
- GenericSignature.ClassTypeSignature superSig = cSig.superclassSignature;
- try {
- // this.superClass =
- // BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX(
- // superSig, formalsForResolution,
- // getResolvedTypeX().getWorld());
-
- ResolvedType rt = BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX(superSig, formalsForResolution,
- getResolvedTypeX().getWorld());
- this.superclassSignature = rt.getSignature();
- this.superclassName = rt.getName();
-
- } catch (GenericSignatureFormatException e) {
- // development bug, fail fast with good info
- throw new IllegalStateException("While determining the generic superclass of " + this.className
- + " with generic signature " + getDeclaredGenericSignature() + " the following error was detected: "
- + e.getMessage());
- }
- // this.interfaces = new
- // ResolvedType[cSig.superInterfaceSignatures.length];
- if (cSig.superInterfaceSignatures.length == 0) {
- this.interfaceSignatures = NO_INTERFACE_SIGS;
- } else {
- this.interfaceSignatures = new String[cSig.superInterfaceSignatures.length];
- for (int i = 0; i < cSig.superInterfaceSignatures.length; i++) {
- try {
- // this.interfaces[i] =
- // BcelGenericSignatureToTypeXConverter.
- // classTypeSignature2TypeX(
- // cSig.superInterfaceSignatures[i],
- // formalsForResolution,
- // getResolvedTypeX().getWorld());
- this.interfaceSignatures[i] = BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX(
- cSig.superInterfaceSignatures[i], formalsForResolution, getResolvedTypeX().getWorld())
- .getSignature();
- } catch (GenericSignatureFormatException e) {
- // development bug, fail fast with good info
- throw new IllegalStateException("While determing the generic superinterfaces of " + this.className
- + " with generic signature " + getDeclaredGenericSignature()
- + " the following error was detected: " + e.getMessage());
- }
- }
- }
- }
- if (isGeneric()) {
- // update resolved typex to point at generic type not raw type.
- ReferenceType genericType = (ReferenceType) this.resolvedTypeX.getGenericType();
- // genericType.setSourceContext(this.resolvedTypeX.getSourceContext());
- // Can be null if unpacking whilst building the bcel delegate (in call hierarchy from BcelWorld.addSourceObjectType()
- // line 453) - see 317139
- if (genericType != null) {
- genericType.setStartPos(this.resolvedTypeX.getStartPos());
- this.resolvedTypeX = genericType;
- }
- }
- }
-
- public GenericSignature.FormalTypeParameter[] getAllFormals() {
- ensureGenericSignatureUnpacked();
- if (formalsForResolution == null) {
- return new GenericSignature.FormalTypeParameter[0];
- } else {
- return formalsForResolution;
- }
- }
-
- public ResolvedType getOuterClass() {
- if (!isNested()) {
- throw new IllegalStateException("Can't get the outer class of non-nested type: " + className);
- }
-
- // try finding outer class name from InnerClasses attribute assigned to this class
- for (Attribute attr : javaClass.getAttributes()) {
- if (attr instanceof InnerClasses) {
- // search for InnerClass entry that has current class as inner and some other class as outer
- InnerClass[] innerClss = ((InnerClasses) attr).getInnerClasses();
- ConstantPool cpool = javaClass.getConstantPool();
- for (InnerClass innerCls : innerClss) {
-
- // skip entries that miss any necessary component, 0 index means "undefined", from JVM Spec 2nd ed. par. 4.7.5
- if (innerCls.getInnerClassIndex() == 0 || innerCls.getOuterClassIndex() == 0) {
- continue;
- }
-
- // resolve inner class name, check if it matches current class name
- ConstantClass innerClsInfo = (ConstantClass) cpool.getConstant(innerCls.getInnerClassIndex());
-
- // class names in constant pool use '/' instead of '.', from JVM Spec 2nd ed. par. 4.2
- String innerClsName = cpool.getConstantUtf8(innerClsInfo.getNameIndex()).getValue().replace('/', '.');
-
- if (innerClsName.compareTo(className) == 0) {
- // resolve outer class name
- ConstantClass outerClsInfo = (ConstantClass) cpool.getConstant(innerCls.getOuterClassIndex());
-
- // class names in constant pool use '/' instead of '.', from JVM Spec 2nd ed. par. 4.2
- String outerClsName = cpool.getConstantUtf8(outerClsInfo.getNameIndex()).getValue().replace('/', '.');
-
- UnresolvedType outer = UnresolvedType.forName(outerClsName);
- return outer.resolve(getResolvedTypeX().getWorld());
- }
- }
- }
- }
-
- for (Attribute attr : javaClass.getAttributes()) { // bug339300
- ConstantPool cpool = javaClass.getConstantPool();
- if (attr instanceof EnclosingMethod) {
- EnclosingMethod enclosingMethodAttribute = (EnclosingMethod) attr;
- if (enclosingMethodAttribute.getEnclosingClassIndex() != 0) {
- ConstantClass outerClassInfo = enclosingMethodAttribute.getEnclosingClass();
- String outerClassName = cpool.getConstantUtf8(outerClassInfo.getNameIndex()).getValue().replace('/', '.');
- UnresolvedType outer = UnresolvedType.forName(outerClassName);
- return outer.resolve(getResolvedTypeX().getWorld());
- }
- }
- }
-
- // try finding outer class name by assuming standard class name mangling convention of javac for this class
- int lastDollar = className.lastIndexOf('$');
- if (lastDollar == -1) {
- // Is this class damaged/obfuscated? Why did we think it was nested but couldn't find the parent using
- // the attributes above. For now just ignore it... I wonder when ignoring this will come back to bite!
- return null;
- }
- String superClassName = className.substring(0, lastDollar);
- UnresolvedType outer = UnresolvedType.forName(superClassName);
- return outer.resolve(getResolvedTypeX().getWorld());
- }
-
- private void ensureGenericInfoProcessed() {
- if ((bitflag & DISCOVERED_DECLARED_SIGNATURE) != 0) {
- return;
- }
- bitflag |= DISCOVERED_DECLARED_SIGNATURE;
- Signature sigAttr = AttributeUtils.getSignatureAttribute(javaClass.getAttributes());
- declaredSignature = (sigAttr == null ? null : sigAttr.getSignature());
- if (declaredSignature != null) {
- isGenericType = (declaredSignature.charAt(0) == '<');
- }
- }
-
- public boolean isGeneric() {
- ensureGenericInfoProcessed();
- return isGenericType;
- }
-
- @Override
- public String toString() {
- return (javaClass == null ? "BcelObjectType" : "BcelObjectTypeFor:" + className);
- }
-
- // --- state management
-
- public void evictWeavingState() {
- // Can't chuck all this away
- if (getResolvedTypeX().getWorld().couldIncrementalCompileFollow()) {
- return;
- }
-
- if (javaClass != null) {
- // Force retrieval of any lazy information
- ensureAnnotationsUnpacked();
- ensureGenericInfoProcessed();
-
- getDeclaredInterfaces();
- getDeclaredFields();
- getDeclaredMethods();
- // The lazyClassGen is preserved for aspects - it exists to enable
- // around advice
- // inlining since the method will need 'injecting' into the affected
- // class. If
- // XnoInline is on, we can chuck away the lazyClassGen since it
- // won't be required
- // later.
- if (getResolvedTypeX().getWorld().isXnoInline()) {
- lazyClassGen = null;
- }
-
- // discard expensive bytecode array containing reweavable info
- if (weaverState != null) {
- weaverState.setReweavable(false);
- weaverState.setUnwovenClassFileData(null);
- }
- for (int i = methods.length - 1; i >= 0; i--) {
- methods[i].evictWeavingState();
- }
- for (int i = fields.length - 1; i >= 0; i--) {
- fields[i].evictWeavingState();
- }
- javaClass = null;
- this.artificial = true;
- // setSourceContext(SourceContextImpl.UNKNOWN_SOURCE_CONTEXT); //
- // bit naughty
- // interfaces=null; // force reinit - may get us the right
- // instances!
- // superClass=null;
- }
- }
-
- public void weavingCompleted() {
- hasBeenWoven = true;
- if (getResolvedTypeX().getWorld().isRunMinimalMemory()) {
- evictWeavingState();
- }
- if (getSourceContext() != null && !getResolvedTypeX().isAspect()) {
- getSourceContext().tidy();
- }
- }
-
- public boolean hasBeenWoven() {
- return hasBeenWoven;
- }
-
- @Override
- public boolean copySourceContext() {
- return false;
- }
-
- public void setExposedToWeaver(boolean b) {
- exposedToWeaver = b;
- }
-
- @Override
- public int getCompilerVersion() {
- return wvInfo.getMajorVersion();
- }
-
- public void ensureConsistent() {
- superTypeReference.clear();
- superInterfaceReferences.clear();
- }
-
- public boolean isWeavable() {
- return true;
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java b/weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java
deleted file mode 100644
index b8ede0a9a..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java
+++ /dev/null
@@ -1,560 +0,0 @@
-/*******************************************************************************
- * 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:
- * initial implementation Alexandre Vasseur
- *******************************************************************************/
-package org.aspectj.weaver.bcel;
-
-import org.aspectj.apache.bcel.Constants;
-import org.aspectj.apache.bcel.generic.InstructionBranch;
-import org.aspectj.apache.bcel.generic.InstructionConstants;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionHandle;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.apache.bcel.generic.ObjectType;
-import org.aspectj.apache.bcel.generic.ReferenceType;
-import org.aspectj.apache.bcel.generic.Type;
-import org.aspectj.weaver.AjAttribute;
-import org.aspectj.weaver.AjcMemberMaker;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.NameMangler;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.patterns.PerClause;
-
-/**
- * Adds aspectOf(), hasAspect() etc to the annotation defined aspects
- *
- * @author Alexandre Vasseur
- * @author Andy Clement
- */
-public class BcelPerClauseAspectAdder extends BcelTypeMunger {
-
- private final PerClause.Kind kind;
-
- private boolean hasGeneratedInner = false;
-
- public BcelPerClauseAspectAdder(ResolvedType aspect, PerClause.Kind kind) {
- super(null, aspect);
- this.kind = kind;
- if (kind == PerClause.SINGLETON || kind == PerClause.PERTYPEWITHIN || kind == PerClause.PERCFLOW) {
- // no inner needed
- hasGeneratedInner = true;
- }
- }
-
- public boolean munge(BcelClassWeaver weaver) {
- LazyClassGen gen = weaver.getLazyClassGen();
-
- doAggressiveInner(gen);
-
- // Only munge the aspect type
- if (!gen.getType().equals(aspectType)) {
- return false;
- }
-
- return doMunge(gen, true);
- }
-
- public boolean forceMunge(LazyClassGen gen, boolean checkAlreadyThere) {
- doAggressiveInner(gen);
- return doMunge(gen, checkAlreadyThere);
- }
-
- private void doAggressiveInner(LazyClassGen gen) {
- // agressively generate the inner interface if any
- // Note: we do so because of the bug #75442 that leads to have this interface implemented by all classes and not
- // only those matched by the per clause, which fails under LTW since the very first class
- // gets weaved and impl this interface that is still not defined.
- if (!hasGeneratedInner) {
- if (kind == PerClause.PEROBJECT) {// redundant test - see constructor, but safer
- // inner class
- UnresolvedType interfaceTypeX = AjcMemberMaker.perObjectInterfaceType(aspectType);
- LazyClassGen interfaceGen = new LazyClassGen(interfaceTypeX.getName(), "java.lang.Object", null,
- Constants.ACC_INTERFACE + Constants.ACC_PUBLIC + Constants.ACC_ABSTRACT, new String[0], getWorld());
- interfaceGen.addMethodGen(makeMethodGen(interfaceGen, AjcMemberMaker.perObjectInterfaceGet(aspectType)));
- interfaceGen.addMethodGen(makeMethodGen(interfaceGen, AjcMemberMaker.perObjectInterfaceSet(aspectType)));
- // not really an inner class of it but that does not matter, we pass back to the LTW
- gen.addGeneratedInner(interfaceGen);
- }
- hasGeneratedInner = true;
- }
- }
-
- private boolean doMunge(LazyClassGen gen, boolean checkAlreadyThere) {
- if (checkAlreadyThere && hasPerClauseMembersAlready(gen)) {
- return false;
- }
-
- generatePerClauseMembers(gen);
-
- if (kind == PerClause.SINGLETON) {
- generatePerSingletonAspectOfMethod(gen);
- generatePerSingletonHasAspectMethod(gen);
- generatePerSingletonAjcClinitMethod(gen);
- } else if (kind == PerClause.PEROBJECT) {
- generatePerObjectAspectOfMethod(gen);
- generatePerObjectHasAspectMethod(gen);
- generatePerObjectBindMethod(gen);
- // these will be added by the PerObjectInterface munger that affects the type - pr144602
- // generatePerObjectGetSetMethods(gen);
- } else if (kind == PerClause.PERCFLOW) {
- generatePerCflowAspectOfMethod(gen);
- generatePerCflowHasAspectMethod(gen);
- generatePerCflowPushMethod(gen);
- generatePerCflowAjcClinitMethod(gen);
- } else if (kind == PerClause.PERTYPEWITHIN) {
- generatePerTWAspectOfMethod(gen);
- generatePerTWHasAspectMethod(gen);
- generatePerTWGetInstanceMethod(gen);
- generatePerTWCreateAspectInstanceMethod(gen);
- generatePerTWGetWithinTypeNameMethod(gen);
- } else {
- throw new Error("should not happen - not such kind " + kind.getName());
- }
- return true;
- }
-
- public ResolvedMember getMatchingSyntheticMember(Member member) {
- return null;
- }
-
- public ResolvedMember getSignature() {
- return null;
- }
-
- public boolean matches(ResolvedType onType) {
- // cannot always do the right thing because may need to eagerly generate ajcMightHaveAspect interface for LTW (says Alex)
- if (hasGeneratedInner) { // pr237419 - not always going to generate the marker interface
- return aspectType.equals(onType);
- } else {
- return true;
- }
- }
-
- private boolean hasPerClauseMembersAlready(LazyClassGen classGen) {
- ResolvedMember[] methods = classGen.getBcelObjectType().getDeclaredMethods();
- for (int i = 0; i < methods.length; i++) {
- ResolvedMember method = methods[i];
- if ("aspectOf".equals(method.getName())) {
- if ("()".equals(method.getParameterSignature()) && (kind == PerClause.SINGLETON || kind == PerClause.PERCFLOW)) {
- return true;
- } else if ("(Ljava/lang/Object;)".equals(method.getParameterSignature()) && kind == PerClause.PEROBJECT) {
- return true;
- } else if ("(Ljava/lang/Class;)".equals(method.getParameterSignature()) && kind == PerClause.PERTYPEWITHIN) {
- return true;
- }
- }
- }
- return false;
- }
-
- private void generatePerClauseMembers(LazyClassGen classGen) {
- // FIXME Alex handle when field already there - or handle it with / similar to isAnnotationDefinedAspect()
- // for that use aspectType and iterate on the fields.
-
- // FIXME Alex percflowX is not using this one but AJ code style does generate it so..
- ResolvedMember failureFieldInfo = AjcMemberMaker.initFailureCauseField(aspectType);
- if (kind == PerClause.SINGLETON) {
- classGen.addField(makeFieldGen(classGen, failureFieldInfo), null);
- }
-
- if (kind == PerClause.SINGLETON) {
- ResolvedMember perSingletonFieldInfo = AjcMemberMaker.perSingletonField(aspectType);
- classGen.addField(makeFieldGen(classGen, perSingletonFieldInfo), null);
- // pr144602 - don't need to do this, PerObjectInterface munger will do it
- // } else if (kind == PerClause.PEROBJECT) {
- // ResolvedMember perObjectFieldInfo = AjcMemberMaker.perObjectField(aspectType, aspectType);
- // classGen.addField(makeFieldGen(classGen, perObjectFieldInfo).(), null);
- // // if lazy generation of the inner interface MayHaveAspect works on LTW (see previous note)
- // // it should be done here.
- } else if (kind == PerClause.PERCFLOW) {
- ResolvedMember perCflowFieldInfo = AjcMemberMaker.perCflowField(aspectType);
- classGen.addField(makeFieldGen(classGen, perCflowFieldInfo), null);
- } else if (kind == PerClause.PERTYPEWITHIN) {
- ResolvedMember perTypeWithinForField = AjcMemberMaker.perTypeWithinWithinTypeField(aspectType, aspectType);
- classGen.addField(makeFieldGen(classGen, perTypeWithinForField), null);
- }
- }
-
- private void generatePerSingletonAspectOfMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perSingletonAspectOfMethod(aspectType));
- flagAsSynthetic(method, false);
- classGen.addMethodGen(method);
-
- InstructionList il = method.getBody();
- il.append(Utility.createGet(factory, AjcMemberMaker.perSingletonField(aspectType)));
- InstructionBranch ifNotNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
- il.append(ifNotNull);
- il.append(factory.createNew(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName()));
- il.append(InstructionConstants.DUP);
- il.append(InstructionFactory.PUSH(classGen.getConstantPool(), aspectType.getName()));
- il.append(Utility.createGet(factory, AjcMemberMaker.initFailureCauseField(aspectType)));
- il.append(factory.createInvoke(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName(), "<init>", Type.VOID, new Type[] {
- Type.STRING, new ObjectType("java.lang.Throwable") }, Constants.INVOKESPECIAL));
- il.append(InstructionConstants.ATHROW);
- InstructionHandle ifElse = il.append(Utility.createGet(factory, AjcMemberMaker.perSingletonField(aspectType)));
- il.append(InstructionFactory.createReturn(Type.OBJECT));
- ifNotNull.setTarget(ifElse);
- }
-
- private void generatePerSingletonHasAspectMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perSingletonHasAspectMethod(aspectType));
- flagAsSynthetic(method, false);
- classGen.addMethodGen(method);
-
- InstructionList il = method.getBody();
- il.append(Utility.createGet(factory, AjcMemberMaker.perSingletonField(aspectType)));
- InstructionBranch ifNull = InstructionFactory.createBranchInstruction(Constants.IFNULL, null);
- il.append(ifNull);
- il.append(InstructionFactory.PUSH(classGen.getConstantPool(), true));
- il.append(InstructionFactory.createReturn(Type.INT));
- InstructionHandle ifElse = il.append(InstructionFactory.PUSH(classGen.getConstantPool(), false));
- il.append(InstructionFactory.createReturn(Type.INT));
- ifNull.setTarget(ifElse);
- }
-
- private void generatePerSingletonAjcClinitMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.ajcPostClinitMethod(aspectType));
- flagAsSynthetic(method, true);
- classGen.addMethodGen(method);
-
- InstructionList il = method.getBody();
- il.append(factory.createNew(aspectType.getName()));
- il.append(InstructionConstants.DUP);
- il.append(factory.createInvoke(aspectType.getName(), "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
- il.append(Utility.createSet(factory, AjcMemberMaker.perSingletonField(aspectType)));
- il.append(InstructionFactory.createReturn(Type.VOID));
-
- // patch <clinit> to delegate to ajc$postClinit at the end
- LazyMethodGen clinit = classGen.getStaticInitializer();
- il = new InstructionList();
- InstructionHandle tryStart = il.append(factory.createInvoke(aspectType.getName(), NameMangler.AJC_POST_CLINIT_NAME,
- Type.VOID, Type.NO_ARGS, Constants.INVOKESTATIC));
- InstructionBranch tryEnd = InstructionFactory.createBranchInstruction(Constants.GOTO, null);
- il.append(tryEnd);
- InstructionHandle handler = il.append(InstructionConstants.ASTORE_0);
- il.append(InstructionConstants.ALOAD_0);
- il.append(Utility.createSet(factory, AjcMemberMaker.initFailureCauseField(aspectType)));
- il.append(InstructionFactory.createReturn(Type.VOID));
- tryEnd.setTarget(il.getEnd());
-
- // replace the original "return" with a "nop"
- // TODO AV - a bit odd, looks like Bcel alters bytecode and has a IMPDEP1 in its representation
- if (clinit.getBody().getEnd().getInstruction().opcode == Constants.IMPDEP1) {
- clinit.getBody().getEnd().getPrev().setInstruction(InstructionConstants.NOP);
- }
- clinit.getBody().getEnd().setInstruction(InstructionConstants.NOP);
- clinit.getBody().append(il);
-
- clinit.addExceptionHandler(tryStart, handler.getPrev(), handler, new ObjectType("java.lang.Throwable"), false);
- }
-
- private void generatePerObjectAspectOfMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- ReferenceType interfaceType = (ReferenceType) BcelWorld.makeBcelType(AjcMemberMaker.perObjectInterfaceType(aspectType));
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perObjectAspectOfMethod(aspectType));
- flagAsSynthetic(method, false);
- classGen.addMethodGen(method);
-
- InstructionList il = method.getBody();
- il.append(InstructionConstants.ALOAD_0);
- il.append(factory.createInstanceOf(interfaceType));
- InstructionBranch ifEq = InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
- il.append(ifEq);
- il.append(InstructionConstants.ALOAD_0);
- il.append(factory.createCheckCast(interfaceType));
- il.append(Utility.createInvoke(factory, Constants.INVOKEINTERFACE, AjcMemberMaker.perObjectInterfaceGet(aspectType)));
- il.append(InstructionConstants.DUP);
- InstructionBranch ifNull = InstructionFactory.createBranchInstruction(Constants.IFNULL, null);
- il.append(ifNull);
- il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(aspectType)));
- InstructionHandle ifNullElse = il.append(InstructionConstants.POP);
- ifNull.setTarget(ifNullElse);
- InstructionHandle ifEqElse = il.append(factory.createNew(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName()));
- ifEq.setTarget(ifEqElse);
- il.append(InstructionConstants.DUP);
- il.append(factory.createInvoke(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName(), "<init>", Type.VOID, Type.NO_ARGS,
- Constants.INVOKESPECIAL));
- il.append(InstructionConstants.ATHROW);
- }
-
- private void generatePerObjectHasAspectMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- ReferenceType interfaceType = (ReferenceType) BcelWorld.makeBcelType(AjcMemberMaker.perObjectInterfaceType(aspectType));
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perObjectHasAspectMethod(aspectType));
- flagAsSynthetic(method, false);
- classGen.addMethodGen(method);
-
- InstructionList il = method.getBody();
- il.append(InstructionConstants.ALOAD_0);
- il.append(factory.createInstanceOf(interfaceType));
- InstructionBranch ifEq = InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
- il.append(ifEq);
- il.append(InstructionConstants.ALOAD_0);
- il.append(factory.createCheckCast(interfaceType));
- il.append(Utility.createInvoke(factory, Constants.INVOKEINTERFACE, AjcMemberMaker.perObjectInterfaceGet(aspectType)));
- InstructionBranch ifNull = InstructionFactory.createBranchInstruction(Constants.IFNULL, null);
- il.append(ifNull);
- il.append(InstructionConstants.ICONST_1);
- il.append(InstructionFactory.createReturn(Type.INT));
- InstructionHandle ifEqElse = il.append(InstructionConstants.ICONST_0);
- ifEq.setTarget(ifEqElse);
- ifNull.setTarget(ifEqElse);
- il.append(InstructionFactory.createReturn(Type.INT));
- }
-
- private void generatePerObjectBindMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- ReferenceType interfaceType = (ReferenceType) BcelWorld.makeBcelType(AjcMemberMaker.perObjectInterfaceType(aspectType));
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perObjectBind(aspectType));
- flagAsSynthetic(method, true);
- classGen.addMethodGen(method);
-
- InstructionList il = method.getBody();
- il.append(InstructionConstants.ALOAD_0);
- il.append(factory.createInstanceOf(interfaceType));
- InstructionBranch ifEq = InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
- il.append(ifEq);
- il.append(InstructionConstants.ALOAD_0);
- il.append(factory.createCheckCast(interfaceType));
- il.append(Utility.createInvoke(factory, Constants.INVOKEINTERFACE, AjcMemberMaker.perObjectInterfaceGet(aspectType)));
- InstructionBranch ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
- il.append(ifNonNull);
- il.append(InstructionConstants.ALOAD_0);
- il.append(factory.createCheckCast(interfaceType));
- il.append(factory.createNew(aspectType.getName()));
- il.append(InstructionConstants.DUP);
- il.append(factory.createInvoke(aspectType.getName(), "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
- il.append(Utility.createInvoke(factory, Constants.INVOKEINTERFACE, AjcMemberMaker.perObjectInterfaceSet(aspectType)));
- InstructionHandle end = il.append(InstructionFactory.createReturn(Type.VOID));
- ifEq.setTarget(end);
- ifNonNull.setTarget(end);
- }
-
- // private void generatePerObjectGetSetMethods(LazyClassGen classGen) {
- // InstructionFactory factory = classGen.getFactory();
- //
- // LazyMethodGen methodGet = makeMethodGen(classGen, AjcMemberMaker.perObjectInterfaceGet(aspectType));
- // flagAsSynthetic(methodGet, true);
- // classGen.addMethodGen(methodGet);
- // InstructionList ilGet = methodGet.getBody();
- // ilGet = new InstructionList();
- // ilGet.append(InstructionConstants.ALOAD_0);
- // ilGet.append(Utility.createGet(factory, AjcMemberMaker.perObjectField(aspectType, aspectType)));
- // ilGet.append(InstructionFactory.createReturn(Type.OBJECT));
- //
- // LazyMethodGen methodSet = makeMethodGen(classGen, AjcMemberMaker.perObjectInterfaceSet(aspectType));
- // flagAsSynthetic(methodSet, true);
- // classGen.addMethodGen(methodSet);
- // InstructionList ilSet = methodSet.getBody();
- // ilSet = new InstructionList();
- // ilSet.append(InstructionConstants.ALOAD_0);
- // ilSet.append(InstructionConstants.ALOAD_1);
- // ilSet.append(Utility.createSet(factory, AjcMemberMaker.perObjectField(aspectType, aspectType)));
- // ilSet.append(InstructionFactory.createReturn(Type.VOID));
- // }
-
- private void generatePerCflowAspectOfMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perCflowAspectOfMethod(aspectType));
- flagAsSynthetic(method, false);
- classGen.addMethodGen(method);
-
- InstructionList il = method.getBody();
- il.append(Utility.createGet(factory, AjcMemberMaker.perCflowField(aspectType)));
- il.append(Utility.createInvoke(factory, Constants.INVOKEVIRTUAL, AjcMemberMaker.cflowStackPeekInstance()));
- il.append(factory.createCheckCast((ReferenceType) BcelWorld.makeBcelType(aspectType)));
- il.append(InstructionFactory.createReturn(Type.OBJECT));
- }
-
- private void generatePerCflowHasAspectMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perCflowHasAspectMethod(aspectType));
- flagAsSynthetic(method, false);
- classGen.addMethodGen(method);
-
- InstructionList il = method.getBody();
- il.append(Utility.createGet(factory, AjcMemberMaker.perCflowField(aspectType)));
- il.append(Utility.createInvoke(factory, Constants.INVOKEVIRTUAL, AjcMemberMaker.cflowStackIsValid()));
- il.append(InstructionFactory.createReturn(Type.INT));
- }
-
- private void generatePerCflowPushMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perCflowPush(aspectType));
- flagAsSynthetic(method, true);
- classGen.addMethodGen(method);
-
- InstructionList il = method.getBody();
- il.append(Utility.createGet(factory, AjcMemberMaker.perCflowField(aspectType)));
- il.append(factory.createNew(aspectType.getName()));
- il.append(InstructionConstants.DUP);
- il.append(factory.createInvoke(aspectType.getName(), "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
- il.append(Utility.createInvoke(factory, Constants.INVOKEVIRTUAL, AjcMemberMaker.cflowStackPushInstance()));
- il.append(InstructionFactory.createReturn(Type.VOID));
- }
-
- private void generatePerCflowAjcClinitMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
-
- LazyMethodGen method = classGen.getAjcPreClinit(); // Creates a clinit if there isn't one
-
- InstructionList il = new InstructionList();
- il.append(factory.createNew(AjcMemberMaker.CFLOW_STACK_TYPE.getName()));
- il.append(InstructionConstants.DUP);
- il.append(factory.createInvoke(AjcMemberMaker.CFLOW_STACK_TYPE.getName(), "<init>", Type.VOID, Type.NO_ARGS,
- Constants.INVOKESPECIAL));
- il.append(Utility.createSet(factory, AjcMemberMaker.perCflowField(aspectType)));
- method.getBody().insert(il);
- }
-
- private void generatePerTWAspectOfMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perTypeWithinAspectOfMethod(aspectType, classGen.getWorld()
- .isInJava5Mode()));
- flagAsSynthetic(method, false);
- classGen.addMethodGen(method);
-
- InstructionList il = method.getBody();
- InstructionHandle tryStart = il.append(InstructionConstants.ALOAD_0);
-
- il.append(Utility.createInvoke(factory, Constants.INVOKESTATIC, AjcMemberMaker.perTypeWithinGetInstance(aspectType)));
- il.append(InstructionConstants.ASTORE_1);
- il.append(InstructionConstants.ALOAD_1);
- InstructionBranch ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
- il.append(ifNonNull);
- il.append(factory.createNew(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName()));
- il.append(InstructionConstants.DUP);
- il.append(InstructionFactory.PUSH(classGen.getConstantPool(), aspectType.getName()));
- il.append(InstructionConstants.ACONST_NULL);
- il.append(factory.createInvoke(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName(), "<init>", Type.VOID, new Type[] {
- Type.STRING, new ObjectType("java.lang.Throwable") }, Constants.INVOKESPECIAL));
- il.append(InstructionConstants.ATHROW);
- InstructionHandle ifElse = il.append(InstructionConstants.ALOAD_1);
- ifNonNull.setTarget(ifElse);
- il.append(InstructionFactory.createReturn(Type.OBJECT));
-
- InstructionHandle handler = il.append(InstructionConstants.ASTORE_1);
- il.append(factory.createNew(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName()));
- il.append(InstructionConstants.DUP);
- il.append(factory.createInvoke(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName(), "<init>", Type.VOID, Type.NO_ARGS,
- Constants.INVOKESPECIAL));
- il.append(InstructionConstants.ATHROW);
-
- method.addExceptionHandler(tryStart, handler.getPrev(), handler, new ObjectType("java.lang.Exception"), false);
- }
-
- // Create 'public String getWithinTypeName() { return ajc$withinType;}'
- private void generatePerTWGetWithinTypeNameMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perTypeWithinGetWithinTypeNameMethod(aspectType, classGen
- .getWorld().isInJava5Mode()));
- flagAsSynthetic(method, false);
- classGen.addMethodGen(method);
- // 0: aload_0
- // 1: getfield #14; //Field ajc$withinType:Ljava/lang/String;
- // 4: areturn
- InstructionList il = method.getBody();
- il.append(InstructionConstants.ALOAD_0);
- il.append(Utility.createGet(factory, AjcMemberMaker.perTypeWithinWithinTypeField(aspectType, aspectType)));
- il.append(InstructionConstants.ARETURN);
- }
-
- private void generatePerTWHasAspectMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perTypeWithinHasAspectMethod(aspectType, classGen.getWorld()
- .isInJava5Mode()));
- flagAsSynthetic(method, false);
- classGen.addMethodGen(method);
-
- InstructionList il = method.getBody();
- InstructionHandle tryStart = il.append(InstructionConstants.ALOAD_0);
- il.append(Utility.createInvoke(factory, Constants.INVOKESTATIC, AjcMemberMaker.perTypeWithinGetInstance(aspectType)));
- InstructionBranch ifNull = InstructionFactory.createBranchInstruction(Constants.IFNULL, null);
- il.append(ifNull);
- il.append(InstructionConstants.ICONST_1);
- il.append(InstructionConstants.IRETURN);
- InstructionHandle ifElse = il.append(InstructionConstants.ICONST_0);
- ifNull.setTarget(ifElse);
- il.append(InstructionConstants.IRETURN);
-
- InstructionHandle handler = il.append(InstructionConstants.ASTORE_1);
- il.append(InstructionConstants.ICONST_0);
- il.append(InstructionConstants.IRETURN);
-
- method.addExceptionHandler(tryStart, handler.getPrev(), handler, new ObjectType("java.lang.Exception"), false);
- }
-
- private void generatePerTWGetInstanceMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perTypeWithinGetInstance(aspectType));
- flagAsSynthetic(method, true);
- classGen.addMethodGen(method);
-
- InstructionList il = method.getBody();
- InstructionHandle tryStart = il.append(InstructionConstants.ALOAD_0);
- il.append(InstructionFactory.PUSH(factory.getConstantPool(), NameMangler.perTypeWithinLocalAspectOf(aspectType)));
- il.append(InstructionConstants.ACONST_NULL);// Class[] for "getDeclaredMethod"
- il.append(factory.createInvoke("java/lang/Class", "getDeclaredMethod", Type.getType("Ljava/lang/reflect/Method;"),
- new Type[] { Type.getType("Ljava/lang/String;"), Type.getType("[Ljava/lang/Class;") }, Constants.INVOKEVIRTUAL));
- il.append(InstructionConstants.ACONST_NULL);// Object for "invoke", static method
- il.append(InstructionConstants.ACONST_NULL);// Object[] for "invoke", no arg
- il.append(factory.createInvoke("java/lang/reflect/Method", "invoke", Type.OBJECT, new Type[] {
- Type.getType("Ljava/lang/Object;"), Type.getType("[Ljava/lang/Object;") }, Constants.INVOKEVIRTUAL));
- il.append(factory.createCheckCast((ReferenceType) BcelWorld.makeBcelType(aspectType)));
- il.append(InstructionConstants.ARETURN);
-
- InstructionHandle handler = il.append(InstructionConstants.ASTORE_1);
- il.append(InstructionConstants.ACONST_NULL);
- il.append(InstructionConstants.ARETURN);
-
- method.addExceptionHandler(tryStart, handler.getPrev(), handler, new ObjectType("java.lang.Exception"), false);
- }
-
- private void generatePerTWCreateAspectInstanceMethod(LazyClassGen classGen) {
- InstructionFactory factory = classGen.getFactory();
- LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perTypeWithinCreateAspectInstance(aspectType));
- flagAsSynthetic(method, true);
- classGen.addMethodGen(method);
-
- InstructionList il = method.getBody();
- il.append(factory.createNew(aspectType.getName()));
- il.append(InstructionConstants.DUP);
- il.append(factory.createInvoke(aspectType.getName(), "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
- il.append(InstructionConstants.ASTORE_1);
- il.append(InstructionConstants.ALOAD_1);
- il.append(InstructionConstants.ALOAD_0);
- il.append(Utility.createSet(factory, AjcMemberMaker.perTypeWithinWithinTypeField(aspectType, aspectType)));
- il.append(InstructionConstants.ALOAD_1);
- il.append(InstructionConstants.ARETURN);
- }
-
- /**
- * Add standard Synthetic (if wished) and AjSynthetic (always) attributes
- *
- * @param methodGen
- * @param makeJavaSynthetic true if standard Synthetic attribute must be set as well (invisible to user)
- */
- private static void flagAsSynthetic(LazyMethodGen methodGen, boolean makeJavaSynthetic) {
- if (makeJavaSynthetic) {
- methodGen.makeSynthetic();
- }
- methodGen.addAttribute(Utility
- .bcelAttribute(new AjAttribute.AjSynthetic(), methodGen.getEnclosingClass().getConstantPool()));
- }
-
- // public boolean isLateTypeMunger() {
- // return true;
- // }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelRenderer.java b/weaver/src/org/aspectj/weaver/bcel/BcelRenderer.java
deleted file mode 100644
index e1f99439f..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelRenderer.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/* *******************************************************************
- * 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.lang.reflect.Modifier;
-
-import org.aspectj.apache.bcel.Constants;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionHandle;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.apache.bcel.generic.ObjectType;
-import org.aspectj.apache.bcel.generic.ReferenceType;
-import org.aspectj.apache.bcel.generic.Type;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.MemberImpl;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.ast.And;
-import org.aspectj.weaver.ast.Call;
-import org.aspectj.weaver.ast.CallExpr;
-import org.aspectj.weaver.ast.Expr;
-import org.aspectj.weaver.ast.FieldGet;
-import org.aspectj.weaver.ast.FieldGetCall;
-import org.aspectj.weaver.ast.HasAnnotation;
-import org.aspectj.weaver.ast.IExprVisitor;
-import org.aspectj.weaver.ast.ITestVisitor;
-import org.aspectj.weaver.ast.Instanceof;
-import org.aspectj.weaver.ast.Literal;
-import org.aspectj.weaver.ast.Not;
-import org.aspectj.weaver.ast.Or;
-import org.aspectj.weaver.ast.Test;
-import org.aspectj.weaver.ast.Var;
-import org.aspectj.weaver.internal.tools.MatchingContextBasedTest;
-
-// we generate right to left, btw.
-public final class BcelRenderer implements ITestVisitor, IExprVisitor {
-
- private InstructionList instructions;
- private InstructionFactory fact;
- private BcelWorld world;
-
- InstructionHandle sk, fk, next = null;
-
- private BcelRenderer(InstructionFactory fact, BcelWorld world) {
- super();
- this.fact = fact;
- this.world = world;
- this.instructions = new InstructionList();
- }
-
- // ---- renderers
-
- public static InstructionList renderExpr(InstructionFactory fact, BcelWorld world, Expr e) {
- BcelRenderer renderer = new BcelRenderer(fact, world);
- e.accept(renderer);
- return renderer.instructions;
- }
-
- public static InstructionList renderExpr(InstructionFactory fact, BcelWorld world, Expr e, Type desiredType) {
- BcelRenderer renderer = new BcelRenderer(fact, world);
- e.accept(renderer);
- InstructionList il = renderer.instructions;
- il.append(Utility.createConversion(fact, BcelWorld.makeBcelType(e.getType()), desiredType));
- return il;
- }
-
- public static InstructionList renderExprs(InstructionFactory fact, BcelWorld world, Expr[] es) {
- BcelRenderer renderer = new BcelRenderer(fact, world);
- for (int i = es.length - 1; i >= 0; i--) {
- es[i].accept(renderer);
- }
- return renderer.instructions;
- }
-
- /*
- * Get the instructions representing this test.
- *
- * @param e test to render
- *
- * @param sk instructionHandle to jump to if our rendered check succeeds (typically start of advice)
- *
- * @param fk instructionHandle to jump to if our rendered check fails (typically after end of advice)
- *
- * @param next instructionHandle that will follow this generated code. Passing in null will generate one unnecessary GOTO
- * instruction.
- *
- * @returns the instruction list representing this expression
- */
- public static InstructionList renderTest(InstructionFactory fact, BcelWorld world, Test e, InstructionHandle sk,
- InstructionHandle fk, InstructionHandle next) {
- BcelRenderer renderer = new BcelRenderer(fact, world);
- renderer.recur(e, sk, fk, next);
- return renderer.instructions;
- }
-
- // ---- recurrers
-
- private void recur(Test e, InstructionHandle sk, InstructionHandle fk, InstructionHandle next) {
- this.sk = sk;
- this.fk = fk;
- this.next = next;
- e.accept(this);
- }
-
- // ---- test visitors
-
- public void visit(And e) {
- InstructionHandle savedFk = fk;
- recur(e.getRight(), sk, fk, next);
- InstructionHandle ning = instructions.getStart();
- recur(e.getLeft(), ning, savedFk, ning);
- }
-
- public void visit(Or e) {
- InstructionHandle savedSk = sk;
- recur(e.getRight(), sk, fk, next);
- recur(e.getLeft(), savedSk, instructions.getStart(), instructions.getStart());
- }
-
- public void visit(Not e) {
- recur(e.getBody(), fk, sk, next);
- }
-
- public void visit(Instanceof i) {
- instructions.insert(createJumpBasedOnBooleanOnStack());
- instructions.insert(Utility.createInstanceof(fact, (ReferenceType) BcelWorld.makeBcelType(i.getType())));
- i.getVar().accept(this);
- }
-
- public void visit(HasAnnotation hasAnnotation) {
- // in Java:
- // foo.class.isAnnotationPresent(annotationClass);
- // in bytecode:
-
- // ifnull? skip to the end if it is as getClass() will fail (see pr 257833)
-
- // load var onto the stack (done for us later)
- // invokevirtual java/lang/Object.getClass:()Ljava/lang/Class
- // ldc_w annotationClass
- // invokevirtual java/lang/Class.isAnnotationPresent:(Ljava/lang/Class;)Z
- InstructionList il = new InstructionList();
-
- // If it is null jump past the advice call
- il.append(InstructionFactory.createBranchInstruction(Constants.IFNULL, fk));
-
- // Load up the var again
- il.append(((BcelVar) hasAnnotation.getVar()).createLoad(fact));
-
- Member getClass = MemberImpl.method(UnresolvedType.OBJECT, 0, UnresolvedType.JL_CLASS, "getClass", UnresolvedType.NONE);
- il.append(Utility.createInvoke(fact, world, getClass));
- // aload annotationClass
- il.append(fact.createConstant(new ObjectType(hasAnnotation.getAnnotationType().getName())));
- // int annClassIndex = fact.getConstantPool().addClass(hasAnnotation.getAnnotationType().getSignature());
- // il.append(new LDC_W(annClassIndex));
- Member isAnnotationPresent = MemberImpl.method(UnresolvedType.JL_CLASS, 0, UnresolvedType.BOOLEAN, "isAnnotationPresent",
- new UnresolvedType[] { UnresolvedType.JL_CLASS });
- il.append(Utility.createInvoke(fact, world, isAnnotationPresent));
- il.append(createJumpBasedOnBooleanOnStack());
- instructions.insert(il);
- hasAnnotation.getVar().accept(this);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.aspectj.weaver.ast.ITestVisitor#visit(org.aspectj.weaver.internal.tools.MatchingContextBasedTest)
- */
- public void visit(MatchingContextBasedTest matchingContextTest) {
- throw new UnsupportedOperationException("matching context extension not supported in bytecode weaving");
- }
-
- private InstructionList createJumpBasedOnBooleanOnStack() {
- InstructionList il = new InstructionList();
- if (sk == fk) {
- // don't bother generating if it doesn't matter
- if (sk != next) {
- il.insert(InstructionFactory.createBranchInstruction(Constants.GOTO, sk));
- }
- return il;
- }
-
- if (fk == next) {
- il.insert(InstructionFactory.createBranchInstruction(Constants.IFNE, sk));
- } else if (sk == next) {
- il.insert(InstructionFactory.createBranchInstruction(Constants.IFEQ, fk));
- } else {
- il.insert(InstructionFactory.createBranchInstruction(Constants.GOTO, sk));
- il.insert(InstructionFactory.createBranchInstruction(Constants.IFEQ, fk));
- }
- return il;
- }
-
- public void visit(Literal literal) {
- if (literal == Literal.FALSE) {
- throw new BCException("visiting a false expression");
- }
- }
-
- public void visit(Call call) {
- Member method = call.getMethod();
- // assert method.isStatic()
- Expr[] args = call.getArgs();
- InstructionList callIl = new InstructionList();
- for (int i = 0, len = args.length; i < len; i++) {
- // XXX only correct for static method calls
- Type desiredType = BcelWorld.makeBcelType(method.getParameterTypes()[i]);
- Expr arg = args[i];
- // if arg is null it is because we couldn't bind it properly, for example see 162135
- if (arg == null) {
- InstructionList iList = new InstructionList();
- iList.append(InstructionFactory.createNull(desiredType));
- callIl.append(iList);
- } else {
- callIl.append(renderExpr(fact, world, arg, desiredType));
- }
- }
- // System.out.println("rendered args: " + callIl);
- callIl.append(Utility.createInvoke(fact, world, method));
- callIl.append(createJumpBasedOnBooleanOnStack());
- instructions.insert(callIl);
- }
-
- public void visit(FieldGetCall fieldGetCall) {
- Member field = fieldGetCall.getField();
- Member method = fieldGetCall.getMethod();
- InstructionList il = new InstructionList();
- il.append(Utility.createGet(fact, field));
- // assert !method.isStatic()
- Expr[] args = fieldGetCall.getArgs();
- // System.out.println("args: " + Arrays.asList(args));
- il.append(renderExprs(fact, world, args));
- // System.out.println("rendered args: " + callIl);
- il.append(Utility.createInvoke(fact, world, method));
- il.append(createJumpBasedOnBooleanOnStack());
- instructions.insert(il);
- }
-
- // ---- expr visitors
-
- public void visit(Var var) {
- BcelVar bvar = (BcelVar) var;
- bvar.insertLoad(instructions, fact);
- }
-
- public void visit(FieldGet fieldGet) {
- Member field = fieldGet.getField();
- // assert field.isStatic()
- instructions.insert(Utility.createGet(fact, field));
- }
-
- public void visit(CallExpr call) {
- Member method = call.getMethod();
- // assert method.isStatic()
- Expr[] args = call.getArgs();
- InstructionList callIl = renderExprs(fact, world, args);
- callIl.append(Utility.createInvoke(fact, world, method));
- instructions.insert(callIl);
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
deleted file mode 100644
index c93a0f26e..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
+++ /dev/null
@@ -1,3425 +0,0 @@
-/* *******************************************************************
- * 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
- * Alexandre Vasseur support for @AJ aspects
- * ******************************************************************/
-
-package org.aspectj.weaver.bcel;
-
-import java.lang.reflect.Modifier;
-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 org.aspectj.apache.bcel.Constants;
-import org.aspectj.apache.bcel.classfile.ConstantPool;
-import org.aspectj.apache.bcel.classfile.Field;
-import org.aspectj.apache.bcel.generic.ArrayType;
-import org.aspectj.apache.bcel.generic.FieldInstruction;
-import org.aspectj.apache.bcel.generic.INVOKEINTERFACE;
-import org.aspectj.apache.bcel.generic.Instruction;
-import org.aspectj.apache.bcel.generic.InstructionBranch;
-import org.aspectj.apache.bcel.generic.InstructionConstants;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionHandle;
-import org.aspectj.apache.bcel.generic.InstructionLV;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.apache.bcel.generic.InstructionTargeter;
-import org.aspectj.apache.bcel.generic.InvokeInstruction;
-import org.aspectj.apache.bcel.generic.LineNumberTag;
-import org.aspectj.apache.bcel.generic.LocalVariableTag;
-import org.aspectj.apache.bcel.generic.MULTIANEWARRAY;
-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.ISourceLocation;
-import org.aspectj.weaver.Advice;
-import org.aspectj.weaver.AdviceKind;
-import org.aspectj.weaver.AjcMemberMaker;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.ConcreteTypeMunger;
-import org.aspectj.weaver.IntMap;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.MemberImpl;
-import org.aspectj.weaver.NameMangler;
-import org.aspectj.weaver.NewConstructorTypeMunger;
-import org.aspectj.weaver.NewFieldTypeMunger;
-import org.aspectj.weaver.NewMethodTypeMunger;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedMemberImpl;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.Shadow;
-import org.aspectj.weaver.ShadowMunger;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.WeaverMessages;
-import org.aspectj.weaver.World;
-import org.aspectj.weaver.ast.Var;
-import org.aspectj.weaver.patterns.AbstractPatternNodeVisitor;
-import org.aspectj.weaver.patterns.AndPointcut;
-import org.aspectj.weaver.patterns.NotPointcut;
-import org.aspectj.weaver.patterns.OrPointcut;
-import org.aspectj.weaver.patterns.ThisOrTargetPointcut;
-
-/*
- * Some fun implementation stuff:
- *
- * * expressionKind advice is non-execution advice
- * * may have a target.
- * * if the body is extracted, it will be extracted into
- * a static method. The first argument to the static
- * method is the target
- * * advice may expose a this object, but that's the advice's
- * consideration, not ours. This object will NOT be cached in another
- * local, but will always come from frame zero.
- *
- * * non-expressionKind advice is execution advice
- * * may have a this.
- * * target is same as this, and is exposed that way to advice
- * (i.e., target will not be cached, will always come from frame zero)
- * * if the body is extracted, it will be extracted into a method
- * with same static/dynamic modifier as enclosing method. If non-static,
- * target of callback call will be this.
- *
- * * because of these two facts, the setup of the actual arguments (including
- * possible target) callback method is the same for both kinds of advice:
- * push the targetVar, if it exists (it will not exist for advice on static
- * things), then push all the argVars.
- *
- * Protected things:
- *
- * * the above is sufficient for non-expressionKind advice for protected things,
- * since the target will always be this.
- *
- * * For expressionKind things, we have to modify the signature of the callback
- * method slightly. For non-static expressionKind things, we modify
- * the first argument of the callback method NOT to be the type specified
- * by the method/field signature (the owner), but rather we type it to
- * the currentlyEnclosing type. We are guaranteed this will be fine,
- * since the verifier verifies that the target is a subtype of the currently
- * enclosingType.
- *
- * Worries:
- *
- * * ConstructorCalls will be weirder than all of these, since they
- * supposedly don't have a target (according to AspectJ), but they clearly
- * do have a target of sorts, just one that needs to be pushed on the stack,
- * dupped, and not touched otherwise until the constructor runs.
- *
- * @author Jim Hugunin
- * @author Erik Hilsdale
- *
- */
-
-public class BcelShadow extends Shadow {
-
- private static final String[] NoDeclaredExceptions = new String[0];
-
- private ShadowRange range;
- private final BcelWorld world;
- private final LazyMethodGen enclosingMethod;
-
- // TESTING this will tell us if the optimisation succeeded *on the last shadow processed*
- public static boolean appliedLazyTjpOptimization;
-
- // Some instructions have a target type that will vary
- // from the signature (pr109728) (1.4 declaring type issue)
- private String actualInstructionTargetType;
-
- /**
- * 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) {
- super(kind, signature, enclosingShadow);
- this.world = world;
- this.enclosingMethod = enclosingMethod;
- }
-
- // ---- copies all state, including Shadow's mungers...
-
- public BcelShadow copyInto(LazyMethodGen recipient, BcelShadow enclosing) {
- BcelShadow s = new BcelShadow(world, getKind(), getSignature(), recipient, enclosing);
- if (mungers.size() > 0) {
- List<ShadowMunger> src = mungers;
- if (s.mungers == Collections.EMPTY_LIST) {
- s.mungers = new ArrayList<ShadowMunger>();
- }
- List<ShadowMunger> dest = s.mungers;
- for (Iterator<ShadowMunger> i = src.iterator(); i.hasNext();) {
- dest.add(i.next());
- }
- }
- return s;
- }
-
- // ---- overridden behaviour
-
- @Override
- public World getIWorld() {
- return world;
- }
-
- // see comment in deleteNewAndDup
- // } else if (inst.opcode == Constants.DUP_X2) {
- // // This code seen in the wild (by Brad):
- // // 40: new #12; //class java/lang/StringBuffer
- // // STACK: STRINGBUFFER
- // // 43: dup
- // // STACK: STRINGBUFFER/STRINGBUFFER
- // // 44: aload_0
- // // STACK: STRINGBUFFER/STRINGBUFFER/THIS
- // // 45: dup_x2
- // // STACK: THIS/STRINGBUFFER/STRINGBUFFER/THIS
- // // 46: getfield #36; //Field value:Ljava/lang/String;
- // // STACK: THIS/STRINGBUFFER/STRINGBUFFER/STRING<value>
- // // 49: invokestatic #37; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
- // // STACK: THIS/STRINGBUFFER/STRINGBUFFER/STRING
- // // 52: invokespecial #19; //Method java/lang/StringBuffer."<init>":(Ljava/lang/String;)V
- // // STACK: THIS/STRINGBUFFER
- // // 55: aload_1
- // // STACK: THIS/STRINGBUFFER/LOCAL1
- // // 56: invokevirtual #22; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
- // // STACK: THIS/STRINGBUFFER
- // // 59: invokevirtual #34; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
- // // STACK: THIS/STRING
- // // 62: putfield #36; //Field value:Ljava/lang/String;
- // // STACK: <empty>
- // // 65: return
- //
- // // if we attempt to match on the ctor call to StringBuffer.<init> then we get into trouble.
- // // if we simply delete the new/dup pair without fixing up the dup_x2 then the dup_x2 will fail due to there
- // // not being 3 elements on the stack for it to work with. The fix *in this situation* is to change it to
- // // a simple 'dup'
- //
- // // this fix is *not* very clean - but a general purpose decent solution will take much longer and this
- // // bytecode sequence has only been seen once in the wild.
- // ih.setInstruction(InstructionConstants.DUP);
-
- /**
- * The new/dup (or new/dup_x1/swap) are removed and will be readded later (after the advice call) by the caller of this method.
- * The groovy compiler produces unusual code where the new/dup isn't visible (when making a this() call from an existing ctor),
- * an aload_0 is used to load the uninitialized object (as an example see the ctors in grails.util.BuildSettings).
- *
- * @return true if managed to remove them
- */
- private boolean deleteNewAndDup() {
- final ConstantPool cpool = getEnclosingClass().getConstantPool();
- int depth = 1;
- InstructionHandle ih = range.getStart();
-
- // Go back from where we are looking for 'NEW' that takes us to a stack depth of 0. INVOKESPECIAL <init>
- while (ih != null) {
- Instruction inst = ih.getInstruction();
- if (inst.opcode == Constants.INVOKESPECIAL && ((InvokeInstruction) inst).getName(cpool).equals("<init>")) {
- depth++;
- } else if (inst.opcode == Constants.NEW) {
- depth--;
- if (depth == 0) {
- break;
- }
- // need a testcase to show this can really happen in a modern compiler - removed due to 315398 - moved this out to
- // comment proceeding this method:
-
- }
- ih = ih.getPrev();
- }
- if (ih == null) {
- return false;
- }
- // now IH points to the NEW. We're followed by the DUP, and that is followed
- // by the actual instruction we care about.
- InstructionHandle newHandle = ih;
- InstructionHandle endHandle = newHandle.getNext();
- InstructionHandle nextHandle;
- if (endHandle.getInstruction().opcode == Constants.DUP) {
- nextHandle = endHandle.getNext();
- retargetFrom(newHandle, nextHandle);
- retargetFrom(endHandle, nextHandle);
- } else if (endHandle.getInstruction().opcode == Constants.DUP_X1) {
- InstructionHandle dupHandle = endHandle;
- endHandle = endHandle.getNext();
- nextHandle = endHandle.getNext();
- boolean skipEndRepositioning = false;
- if (endHandle.getInstruction().opcode == Constants.SWAP) {
- } else if (endHandle.getInstruction().opcode == Constants.IMPDEP1) {
- skipEndRepositioning = true; // pr186884
- } else {
- // XXX see next XXX comment
- throw new RuntimeException("Unhandled kind of new " + endHandle);
- }
- // Now make any jumps to the 'new', the 'dup' or the 'end' now target the nextHandle
- retargetFrom(newHandle, nextHandle);
- retargetFrom(dupHandle, nextHandle);
- if (!skipEndRepositioning) {
- retargetFrom(endHandle, nextHandle);
- }
- } else {
- endHandle = newHandle;
- nextHandle = endHandle.getNext();
- retargetFrom(newHandle, nextHandle);
- // add a POP here... we found a NEW w/o a dup or anything else, so
- // we must be in statement context.
- getRange().insert(InstructionConstants.POP, Range.OutsideAfter);
- }
- // assert (dupHandle.getInstruction() instanceof DUP);
-
- try {
- range.getBody().delete(newHandle, endHandle);
- } catch (TargetLostException e) {
- throw new BCException("shouldn't happen");
- }
- return true;
- }
-
- private void retargetFrom(InstructionHandle old, InstructionHandle fresh) {
- for (InstructionTargeter targeter : old.getTargetersCopy()) {
- if (targeter instanceof ExceptionRange) {
- ExceptionRange it = (ExceptionRange) targeter;
- it.updateTarget(old, fresh, it.getBody());
- } else {
- targeter.updateTarget(old, fresh);
- }
- }
- }
-
- // records advice that is stopping us doing the lazyTjp optimization
- private List<BcelAdvice> badAdvice = null;
-
- public void addAdvicePreventingLazyTjp(BcelAdvice advice) {
- if (badAdvice == null) {
- badAdvice = new ArrayList<BcelAdvice>();
- }
- badAdvice.add(advice);
- }
-
- @Override
- protected void prepareForMungers() {
- // if we're a constructor call, we need to remove the new:dup or the new:dup_x1:swap,
- // and store all our arguments on the frame.
-
- // ??? This is a bit of a hack (for the Java langauge). We do this because
- // we sometime add code "outsideBefore" when dealing with weaving join points. We only
- // do this for exposing state that is on the stack. It turns out to just work for
- // everything except for constructor calls and exception handlers. If we were to clean
- // this up, every ShadowRange would have three instructionHandle points, the start of
- // the arg-setup code, the start of the running code, and the end of the running code.
- boolean deletedNewAndDup = true;
- if (getKind() == ConstructorCall) {
- if (!world.isJoinpointArrayConstructionEnabled() || !this.getSignature().getDeclaringType().isArray()) {
- deletedNewAndDup = deleteNewAndDup(); // no new/dup for new array construction
- }
- initializeArgVars();
- } else if (getKind() == PreInitialization) { // pr74952
- ShadowRange range = getRange();
- range.insert(InstructionConstants.NOP, Range.InsideAfter);
- } else if (getKind() == ExceptionHandler) {
-
- ShadowRange range = getRange();
- InstructionList body = range.getBody();
- InstructionHandle start = range.getStart();
-
- // Create a store instruction to put the value from the top of the
- // stack into a local variable slot. This is a trimmed version of
- // what is in initializeArgVars() (since there is only one argument
- // at a handler jp and only before advice is supported) (pr46298)
- argVars = new BcelVar[1];
- // int positionOffset = (hasTarget() ? 1 : 0) + ((hasThis() && !getKind().isTargetSameAsThis()) ? 1 : 0);
- UnresolvedType tx = getArgType(0);
- argVars[0] = genTempVar(tx, "ajc$arg0");
- InstructionHandle insertedInstruction = range.insert(argVars[0].createStore(getFactory()), Range.OutsideBefore);
-
- // Now the exception range starts just after our new instruction.
- // The next bit of code changes the exception range to point at
- // the store instruction
- for (InstructionTargeter t : start.getTargetersCopy()) {
- if (t instanceof ExceptionRange) {
- ExceptionRange er = (ExceptionRange) t;
- er.updateTarget(start, insertedInstruction, body);
- }
- }
- }
-
- // now we ask each munger to request our state
- isThisJoinPointLazy = true;// world.isXlazyTjp(); // lazy is default now
-
- badAdvice = null;
- for (ShadowMunger munger : mungers) {
- munger.specializeOn(this);
- }
-
- initializeThisJoinPoint();
-
- if (thisJoinPointVar != null && !isThisJoinPointLazy && badAdvice != null && badAdvice.size() > 1) {
- // something stopped us making it a lazy tjp
- // can't build tjp lazily, no suitable test...
- int valid = 0;
- for (Iterator<BcelAdvice> iter = badAdvice.iterator(); iter.hasNext();) {
- BcelAdvice element = iter.next();
- ISourceLocation sLoc = element.getSourceLocation();
- if (sLoc != null && sLoc.getLine() > 0) {
- valid++;
- }
- }
- if (valid != 0) {
- ISourceLocation[] badLocs = new ISourceLocation[valid];
- int i = 0;
- for (Iterator<BcelAdvice> iter = badAdvice.iterator(); iter.hasNext();) {
- BcelAdvice element = iter.next();
- ISourceLocation sLoc = element.getSourceLocation();
- if (sLoc != null) {
- badLocs[i++] = sLoc;
- }
- }
- world.getLint().multipleAdviceStoppingLazyTjp
- .signal(new String[] { this.toString() }, getSourceLocation(), badLocs);
- }
- }
- badAdvice = null;
-
- // If we are an expression kind, we require our target/arguments on the stack
- // before we do our actual thing. However, they may have been removed
- // from the stack as the shadowMungers have requested state.
- // if any of our shadowMungers requested either the arguments or target,
- // the munger will have added code
- // to pop the target/arguments into temporary variables, represented by
- // targetVar and argVars. In such a case, we must make sure to re-push the
- // values.
-
- // If we are nonExpressionKind, we don't expect arguments on the stack
- // so this is moot. If our argVars happen to be null, then we know that
- // no ShadowMunger has squirrelled away our arguments, so they're still
- // on the stack.
- InstructionFactory fact = getFactory();
- if (getKind().argsOnStack() && argVars != null) {
-
- // Special case first (pr46298). If we are an exception handler and the instruction
- // just after the shadow is a POP then we should remove the pop. The code
- // above which generated the store instruction has already cleared the stack.
- // We also don't generate any code for the arguments in this case as it would be
- // an incorrect aload.
- if (getKind() == ExceptionHandler && range.getEnd().getNext().getInstruction().equals(InstructionConstants.POP)) {
- // easier than deleting it ...
- range.getEnd().getNext().setInstruction(InstructionConstants.NOP);
- } else {
- range.insert(BcelRenderer.renderExprs(fact, world, argVars), Range.InsideBefore);
- if (targetVar != null) {
- range.insert(BcelRenderer.renderExpr(fact, world, targetVar), Range.InsideBefore);
- }
- if (getKind() == ConstructorCall) {
- if (!world.isJoinpointArrayConstructionEnabled() || !this.getSignature().getDeclaringType().isArray()) {
- if (deletedNewAndDup) { // if didnt delete them, dont insert any!
- range.insert(InstructionFactory.createDup(1), Range.InsideBefore);
- range.insert(fact.createNew((ObjectType) BcelWorld.makeBcelType(getSignature().getDeclaringType())),
- Range.InsideBefore);
- }
- }
- }
- }
- }
- }
-
- // ---- getters
-
- public ShadowRange getRange() {
- return range;
- }
-
- public void setRange(ShadowRange range) {
- this.range = range;
- }
-
- private int sourceline = -1;
-
- public int getSourceLine() {
- // if the kind of join point for which we are a shadow represents
- // a method or constructor execution, then the best source line is
- // the one from the enclosingMethod declarationLineNumber if available.
- if (sourceline != -1) {
- return sourceline;
- }
- Kind kind = getKind();
- if ((kind == MethodExecution) || (kind == ConstructorExecution) || (kind == AdviceExecution)
- || (kind == StaticInitialization) || (kind == PreInitialization) || (kind == Initialization)) {
- if (getEnclosingMethod().hasDeclaredLineNumberInfo()) {
- sourceline = getEnclosingMethod().getDeclarationLineNumber();
- return sourceline;
- }
- }
-
- if (range == null) {
- if (getEnclosingMethod().hasBody()) {
- sourceline = Utility.getSourceLine(getEnclosingMethod().getBody().getStart());
- return sourceline;
- } else {
- sourceline = 0;
- return sourceline;
- }
- }
- sourceline = Utility.getSourceLine(range.getStart());
- if (sourceline < 0) {
- sourceline = 0;
- }
- return sourceline;
- }
-
- @Override
- public ResolvedType getEnclosingType() {
- return getEnclosingClass().getType();
- }
-
- public LazyClassGen getEnclosingClass() {
- return enclosingMethod.getEnclosingClass();
- }
-
- public BcelWorld getWorld() {
- return world;
- }
-
- // ---- factory methods
-
- public static BcelShadow makeConstructorExecution(BcelWorld world, LazyMethodGen enclosingMethod,
- InstructionHandle justBeforeStart) {
- final InstructionList body = enclosingMethod.getBody();
- BcelShadow s = new BcelShadow(world, ConstructorExecution, world.makeJoinPointSignatureFromMethod(enclosingMethod,
- Member.CONSTRUCTOR), enclosingMethod, null);
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- r.associateWithTargets(Range.genStart(body, justBeforeStart.getNext()), Range.genEnd(body));
- return s;
- }
-
- public static BcelShadow makeStaticInitialization(BcelWorld world, LazyMethodGen enclosingMethod) {
- InstructionList body = enclosingMethod.getBody();
- // move the start past ajc$preClinit
- InstructionHandle clinitStart = body.getStart();
- if (clinitStart.getInstruction() instanceof InvokeInstruction) {
- InvokeInstruction ii = (InvokeInstruction) clinitStart.getInstruction();
- if (ii.getName(enclosingMethod.getEnclosingClass().getConstantPool()).equals(NameMangler.AJC_PRE_CLINIT_NAME)) {
- clinitStart = clinitStart.getNext();
- }
- }
-
- InstructionHandle clinitEnd = body.getEnd();
-
- // XXX should move the end before the postClinit, but the return is then tricky...
- // if (clinitEnd.getInstruction() instanceof InvokeInstruction) {
- // InvokeInstruction ii = (InvokeInstruction)clinitEnd.getInstruction();
- // if (ii.getName(enclosingMethod.getEnclosingClass().getConstantPool()).equals(NameMangler.AJC_POST_CLINIT_NAME)) {
- // clinitEnd = clinitEnd.getPrev();
- // }
- // }
-
- BcelShadow s = new BcelShadow(world, StaticInitialization, world.makeJoinPointSignatureFromMethod(enclosingMethod,
- Member.STATIC_INITIALIZATION), enclosingMethod, null);
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- r.associateWithTargets(Range.genStart(body, clinitStart), Range.genEnd(body, clinitEnd));
- return s;
- }
-
- /**
- * Make the shadow for an exception handler. Currently makes an empty shadow that only allows before advice to be woven into it.
- */
-
- public static BcelShadow makeExceptionHandler(BcelWorld world, ExceptionRange exceptionRange, LazyMethodGen enclosingMethod,
- InstructionHandle startOfHandler, BcelShadow enclosingShadow) {
- InstructionList body = enclosingMethod.getBody();
- UnresolvedType catchType = exceptionRange.getCatchType();
- UnresolvedType inType = enclosingMethod.getEnclosingClass().getType();
-
- ResolvedMemberImpl sig = MemberImpl.makeExceptionHandlerSignature(inType, catchType);
- sig.setParameterNames(new String[] { findHandlerParamName(startOfHandler) });
-
- BcelShadow s = new BcelShadow(world, ExceptionHandler, sig, enclosingMethod, enclosingShadow);
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- InstructionHandle start = Range.genStart(body, startOfHandler);
- InstructionHandle end = Range.genEnd(body, start);
-
- r.associateWithTargets(start, end);
- exceptionRange.updateTarget(startOfHandler, start, body);
- return s;
- }
-
- private static String findHandlerParamName(InstructionHandle startOfHandler) {
- if (startOfHandler.getInstruction().isStoreInstruction() && startOfHandler.getNext() != null) {
- int slot = startOfHandler.getInstruction().getIndex();
- // System.out.println("got store: " + startOfHandler.getInstruction() + ", " + index);
- Iterator<InstructionTargeter> tIter = startOfHandler.getNext().getTargeters().iterator();
- while (tIter.hasNext()) {
- InstructionTargeter targeter = tIter.next();
- if (targeter instanceof LocalVariableTag) {
- LocalVariableTag t = (LocalVariableTag) targeter;
- if (t.getSlot() == slot) {
- return t.getName();
- }
- }
- }
- }
-
- return "<missing>";
- }
-
- /** create an init join point associated w/ an interface in the body of a constructor */
-
- public static BcelShadow makeIfaceInitialization(BcelWorld world, LazyMethodGen constructor,
- Member interfaceConstructorSignature) {
- // this call marks the instruction list as changed
- constructor.getBody();
- // UnresolvedType inType = constructor.getEnclosingClass().getType();
- BcelShadow s = new BcelShadow(world, Initialization, interfaceConstructorSignature, constructor, null);
- // s.fallsThrough = true;
- // ShadowRange r = new ShadowRange(body);
- // r.associateWithShadow(s);
- // InstructionHandle start = Range.genStart(body, handle);
- // InstructionHandle end = Range.genEnd(body, handle);
- //
- // r.associateWithTargets(start, end);
- return s;
- }
-
- public void initIfaceInitializer(InstructionHandle end) {
- final InstructionList body = enclosingMethod.getBody();
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(this);
- InstructionHandle nop = body.insert(end, InstructionConstants.NOP);
-
- r.associateWithTargets(Range.genStart(body, nop), Range.genEnd(body, nop));
- }
-
- // public static BcelShadow makeIfaceConstructorExecution(
- // BcelWorld world,
- // LazyMethodGen constructor,
- // InstructionHandle next,
- // Member interfaceConstructorSignature)
- // {
- // // final InstructionFactory fact = constructor.getEnclosingClass().getFactory();
- // InstructionList body = constructor.getBody();
- // // UnresolvedType inType = constructor.getEnclosingClass().getType();
- // BcelShadow s =
- // new BcelShadow(
- // world,
- // ConstructorExecution,
- // interfaceConstructorSignature,
- // constructor,
- // null);
- // s.fallsThrough = true;
- // ShadowRange r = new ShadowRange(body);
- // r.associateWithShadow(s);
- // // ??? this may or may not work
- // InstructionHandle start = Range.genStart(body, next);
- // //InstructionHandle end = Range.genEnd(body, body.append(start, fact.NOP));
- // InstructionHandle end = Range.genStart(body, next);
- // //body.append(start, fact.NOP);
- //
- // r.associateWithTargets(start, end);
- // return s;
- // }
-
- /**
- * Create an initialization join point associated with a constructor, but not with any body of code yet. If this is actually
- * matched, it's range will be set when we inline self constructors.
- *
- * @param constructor The constructor starting this initialization.
- */
- public static BcelShadow makeUnfinishedInitialization(BcelWorld world, LazyMethodGen constructor) {
- BcelShadow ret = new BcelShadow(world, Initialization, world.makeJoinPointSignatureFromMethod(constructor,
- Member.CONSTRUCTOR), constructor, null);
- if (constructor.getEffectiveSignature() != null) {
- ret.setMatchingSignature(constructor.getEffectiveSignature().getEffectiveSignature());
- }
- return ret;
- }
-
- public static BcelShadow makeUnfinishedPreinitialization(BcelWorld world, LazyMethodGen constructor) {
- BcelShadow ret = new BcelShadow(world, PreInitialization, world.makeJoinPointSignatureFromMethod(constructor,
- Member.CONSTRUCTOR), constructor, null);
- if (constructor.getEffectiveSignature() != null) {
- ret.setMatchingSignature(constructor.getEffectiveSignature().getEffectiveSignature());
- }
- return ret;
- }
-
- public static BcelShadow makeMethodExecution(BcelWorld world, LazyMethodGen enclosingMethod, boolean lazyInit) {
- if (!lazyInit) {
- return makeMethodExecution(world, enclosingMethod);
- }
-
- BcelShadow s = new BcelShadow(world, MethodExecution, enclosingMethod.getMemberView(), enclosingMethod, null);
-
- return s;
- }
-
- public void init() {
- if (range != null) {
- return;
- }
-
- final InstructionList body = enclosingMethod.getBody();
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(this);
- r.associateWithTargets(Range.genStart(body), Range.genEnd(body));
- }
-
- public static BcelShadow makeMethodExecution(BcelWorld world, LazyMethodGen enclosingMethod) {
- return makeShadowForMethod(world, enclosingMethod, MethodExecution, enclosingMethod.getMemberView());
- }
-
- public static BcelShadow makeShadowForMethod(BcelWorld world, LazyMethodGen enclosingMethod, Shadow.Kind kind, Member sig) {
- final InstructionList body = enclosingMethod.getBody();
- BcelShadow s = new BcelShadow(world, kind, sig, enclosingMethod, null);
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- r.associateWithTargets(// OPTIMIZE this occurs lots of times for all jp kinds...
- Range.genStart(body), Range.genEnd(body));
- return s;
- }
-
- public static BcelShadow makeAdviceExecution(BcelWorld world, LazyMethodGen enclosingMethod) {
- final InstructionList body = enclosingMethod.getBody();
- BcelShadow s = new BcelShadow(world, AdviceExecution,
- world.makeJoinPointSignatureFromMethod(enclosingMethod, Member.ADVICE), enclosingMethod, null);
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- r.associateWithTargets(Range.genStart(body), Range.genEnd(body));
- return s;
- }
-
- // constructor call shadows are <em>initially</em> just around the
- // call to the constructor. If ANY advice gets put on it, we move
- // the NEW instruction inside the join point, which involves putting
- // all the arguments in temps.
- public static BcelShadow makeConstructorCall(BcelWorld world, LazyMethodGen enclosingMethod, InstructionHandle callHandle,
- BcelShadow enclosingShadow) {
- final InstructionList body = enclosingMethod.getBody();
-
- Member sig = world.makeJoinPointSignatureForMethodInvocation(enclosingMethod.getEnclosingClass(),
- (InvokeInstruction) callHandle.getInstruction());
-
- BcelShadow s = new BcelShadow(world, ConstructorCall, sig, enclosingMethod, enclosingShadow);
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- r.associateWithTargets(Range.genStart(body, callHandle), Range.genEnd(body, callHandle));
- retargetAllBranches(callHandle, r.getStart());
- return s;
- }
-
- public static BcelShadow makeArrayConstructorCall(BcelWorld world, LazyMethodGen enclosingMethod,
- InstructionHandle arrayInstruction, BcelShadow enclosingShadow) {
- final InstructionList body = enclosingMethod.getBody();
- Member sig = world.makeJoinPointSignatureForArrayConstruction(enclosingMethod.getEnclosingClass(), arrayInstruction);
- BcelShadow s = new BcelShadow(world, ConstructorCall, sig, enclosingMethod, enclosingShadow);
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- r.associateWithTargets(Range.genStart(body, arrayInstruction), Range.genEnd(body, arrayInstruction));
- retargetAllBranches(arrayInstruction, r.getStart());
- return s;
- }
-
- public static BcelShadow makeMonitorEnter(BcelWorld world, LazyMethodGen enclosingMethod, InstructionHandle monitorInstruction,
- BcelShadow enclosingShadow) {
- final InstructionList body = enclosingMethod.getBody();
- Member sig = world.makeJoinPointSignatureForMonitorEnter(enclosingMethod.getEnclosingClass(), monitorInstruction);
- BcelShadow s = new BcelShadow(world, SynchronizationLock, sig, enclosingMethod, enclosingShadow);
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- r.associateWithTargets(Range.genStart(body, monitorInstruction), Range.genEnd(body, monitorInstruction));
- retargetAllBranches(monitorInstruction, r.getStart());
- return s;
- }
-
- public static BcelShadow makeMonitorExit(BcelWorld world, LazyMethodGen enclosingMethod, InstructionHandle monitorInstruction,
- BcelShadow enclosingShadow) {
- final InstructionList body = enclosingMethod.getBody();
- Member sig = world.makeJoinPointSignatureForMonitorExit(enclosingMethod.getEnclosingClass(), monitorInstruction);
- BcelShadow s = new BcelShadow(world, SynchronizationUnlock, sig, enclosingMethod, enclosingShadow);
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- r.associateWithTargets(Range.genStart(body, monitorInstruction), Range.genEnd(body, monitorInstruction));
- retargetAllBranches(monitorInstruction, r.getStart());
- return s;
- }
-
- // see pr77166
- // public static BcelShadow makeArrayLoadCall(
- // BcelWorld world,
- // LazyMethodGen enclosingMethod,
- // InstructionHandle arrayInstruction,
- // BcelShadow enclosingShadow)
- // {
- // final InstructionList body = enclosingMethod.getBody();
- // Member sig = world.makeJoinPointSignatureForArrayLoad(enclosingMethod.getEnclosingClass(),arrayInstruction);
- // BcelShadow s =
- // new BcelShadow(
- // world,
- // MethodCall,
- // sig,
- // enclosingMethod,
- // enclosingShadow);
- // ShadowRange r = new ShadowRange(body);
- // r.associateWithShadow(s);
- // r.associateWithTargets(
- // Range.genStart(body, arrayInstruction),
- // Range.genEnd(body, arrayInstruction));
- // retargetAllBranches(arrayInstruction, r.getStart());
- // return s;
- // }
-
- public static BcelShadow makeMethodCall(BcelWorld world, LazyMethodGen enclosingMethod, InstructionHandle callHandle,
- BcelShadow enclosingShadow) {
- final InstructionList body = enclosingMethod.getBody();
- BcelShadow s = new BcelShadow(world, MethodCall, world.makeJoinPointSignatureForMethodInvocation(
- enclosingMethod.getEnclosingClass(), (InvokeInstruction) callHandle.getInstruction()), enclosingMethod,
- enclosingShadow);
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- r.associateWithTargets(Range.genStart(body, callHandle), Range.genEnd(body, callHandle));
- retargetAllBranches(callHandle, r.getStart());
- return s;
- }
-
- public static BcelShadow makeShadowForMethodCall(BcelWorld world, LazyMethodGen enclosingMethod, InstructionHandle callHandle,
- BcelShadow enclosingShadow, Kind kind, ResolvedMember sig) {
- final InstructionList body = enclosingMethod.getBody();
- BcelShadow s = new BcelShadow(world, kind, sig, enclosingMethod, enclosingShadow);
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- r.associateWithTargets(Range.genStart(body, callHandle), Range.genEnd(body, callHandle));
- retargetAllBranches(callHandle, r.getStart());
- return s;
- }
-
- public static BcelShadow makeFieldGet(BcelWorld world, ResolvedMember field, LazyMethodGen enclosingMethod,
- InstructionHandle getHandle, BcelShadow enclosingShadow) {
- final InstructionList body = enclosingMethod.getBody();
- BcelShadow s = new BcelShadow(world, FieldGet, field,
- // BcelWorld.makeFieldSignature(
- // enclosingMethod.getEnclosingClass(),
- // (FieldInstruction) getHandle.getInstruction()),
- enclosingMethod, enclosingShadow);
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- r.associateWithTargets(Range.genStart(body, getHandle), Range.genEnd(body, getHandle));
- retargetAllBranches(getHandle, r.getStart());
- return s;
- }
-
- public static BcelShadow makeFieldSet(BcelWorld world, ResolvedMember field, LazyMethodGen enclosingMethod,
- InstructionHandle setHandle, BcelShadow enclosingShadow) {
- final InstructionList body = enclosingMethod.getBody();
- BcelShadow s = new BcelShadow(world, FieldSet, field,
- // BcelWorld.makeFieldJoinPointSignature(
- // enclosingMethod.getEnclosingClass(),
- // (FieldInstruction) setHandle.getInstruction()),
- enclosingMethod, enclosingShadow);
- ShadowRange r = new ShadowRange(body);
- r.associateWithShadow(s);
- r.associateWithTargets(Range.genStart(body, setHandle), Range.genEnd(body, setHandle));
- retargetAllBranches(setHandle, r.getStart());
- return s;
- }
-
- public static void retargetAllBranches(InstructionHandle from, InstructionHandle to) {
- for (InstructionTargeter source : from.getTargetersCopy()) {
- if (source instanceof InstructionBranch) {
- source.updateTarget(from, to);
- }
- }
- }
-
- // // ---- type access methods
- // private ObjectType getTargetBcelType() {
- // return (ObjectType) BcelWorld.makeBcelType(getTargetType());
- // }
- // private Type getArgBcelType(int arg) {
- // return BcelWorld.makeBcelType(getArgType(arg));
- // }
-
- // ---- kinding
-
- /**
- * If the end of my range has no real instructions following then my context needs a return at the end.
- */
- public boolean terminatesWithReturn() {
- return getRange().getRealNext() == null;
- }
-
- /**
- * Is arg0 occupied with the value of this
- */
- public boolean arg0HoldsThis() {
- if (getKind().isEnclosingKind()) {
- return !Modifier.isStatic(getSignature().getModifiers());
- } else if (enclosingShadow == null) {
- // XXX this is mostly right
- // this doesn't do the right thing for calls in the pre part of introduced constructors.
- return !enclosingMethod.isStatic();
- } else {
- return ((BcelShadow) enclosingShadow).arg0HoldsThis();
- }
- }
-
- // ---- argument getting methods
-
- private BcelVar thisVar = null;
- private BcelVar targetVar = null;
- private BcelVar[] argVars = null;
- private Map<ResolvedType, AnnotationAccessVar> kindedAnnotationVars = null;
- private Map<ResolvedType, TypeAnnotationAccessVar> thisAnnotationVars = null;
- private Map<ResolvedType, TypeAnnotationAccessVar> targetAnnotationVars = null;
- // private Map/* <UnresolvedType,BcelVar> */[] argAnnotationVars = null;
- private Map<ResolvedType, AnnotationAccessVar> withinAnnotationVars = null;
- private Map<ResolvedType, AnnotationAccessVar> withincodeAnnotationVars = null;
- private boolean allArgVarsInitialized = false;
-
- @Override
- public Var getThisVar() {
- if (!hasThis()) {
- throw new IllegalStateException("no this");
- }
- initializeThisVar();
- return thisVar;
- }
-
- @Override
- public Var getThisAnnotationVar(UnresolvedType forAnnotationType) {
- if (!hasThis()) {
- throw new IllegalStateException("no this");
- }
- initializeThisAnnotationVars(); // FIXME asc Why bother with this if we always return one?
- // Even if we can't find one, we have to return one as we might have this annotation at runtime
- Var v = thisAnnotationVars.get(forAnnotationType);
- if (v == null) {
- v = new TypeAnnotationAccessVar(forAnnotationType.resolve(world), (BcelVar) getThisVar());
- }
- return v;
- }
-
- @Override
- public Var getTargetVar() {
- if (!hasTarget()) {
- throw new IllegalStateException("no target");
- }
- initializeTargetVar();
- return targetVar;
- }
-
- @Override
- public Var getTargetAnnotationVar(UnresolvedType forAnnotationType) {
- if (!hasTarget()) {
- throw new IllegalStateException("no target");
- }
- initializeTargetAnnotationVars(); // FIXME asc why bother with this if we always return one?
- Var v = targetAnnotationVars.get(forAnnotationType);
- // Even if we can't find one, we have to return one as we might have this annotation at runtime
- if (v == null) {
- v = new TypeAnnotationAccessVar(forAnnotationType.resolve(world), (BcelVar) getTargetVar());
- }
- return v;
- }
-
- @Override
- public Var getArgVar(int i) {
- ensureInitializedArgVar(i);
- return argVars[i];
- }
-
- @Override
- public Var getArgAnnotationVar(int i, UnresolvedType forAnnotationType) {
- return new TypeAnnotationAccessVar(forAnnotationType.resolve(world), (BcelVar) getArgVar(i));
- // initializeArgAnnotationVars();
- //
- // Var v = (Var) argAnnotationVars[i].get(forAnnotationType);
- // if (v == null) {
- // v = new TypeAnnotationAccessVar(forAnnotationType.resolve(world), (BcelVar) getArgVar(i));
- // }
- // return v;
- }
-
- @Override
- public Var getKindedAnnotationVar(UnresolvedType forAnnotationType) {
- initializeKindedAnnotationVars();
- return kindedAnnotationVars.get(forAnnotationType);
- }
-
- @Override
- public Var getWithinAnnotationVar(UnresolvedType forAnnotationType) {
- initializeWithinAnnotationVars();
- return withinAnnotationVars.get(forAnnotationType);
- }
-
- @Override
- public Var getWithinCodeAnnotationVar(UnresolvedType forAnnotationType) {
- initializeWithinCodeAnnotationVars();
- return withincodeAnnotationVars.get(forAnnotationType);
- }
-
- // reflective thisJoinPoint support
- private BcelVar thisJoinPointVar = null;
- private boolean isThisJoinPointLazy;
- private int lazyTjpConsumers = 0;
- private BcelVar thisJoinPointStaticPartVar = null;
-
- // private BcelVar thisEnclosingJoinPointStaticPartVar = null;
-
- @Override
- public final Var getThisJoinPointStaticPartVar() {
- return getThisJoinPointStaticPartBcelVar();
- }
-
- @Override
- public final Var getThisEnclosingJoinPointStaticPartVar() {
- return getThisEnclosingJoinPointStaticPartBcelVar();
- }
-
- public void requireThisJoinPoint(boolean hasGuardTest, boolean isAround) {
- if (!isAround) {
- if (!hasGuardTest) {
- isThisJoinPointLazy = false;
- } else {
- lazyTjpConsumers++;
- }
- }
- // if (!hasGuardTest) {
- // isThisJoinPointLazy = false;
- // } else {
- // lazyTjpConsumers++;
- // }
- if (thisJoinPointVar == null) {
- thisJoinPointVar = genTempVar(UnresolvedType.forName("org.aspectj.lang.JoinPoint"));
- }
- }
-
- @Override
- public Var getThisJoinPointVar() {
- requireThisJoinPoint(false, false);
- return thisJoinPointVar;
- }
-
- void initializeThisJoinPoint() {
- if (thisJoinPointVar == null) {
- return;
- }
-
- if (isThisJoinPointLazy) {
- isThisJoinPointLazy = checkLazyTjp();
- }
-
- if (isThisJoinPointLazy) {
- appliedLazyTjpOptimization = true;
- createThisJoinPoint(); // make sure any state needed is initialized, but throw the instructions out
-
- if (lazyTjpConsumers == 1) {
- return; // special case only one lazyTjpUser
- }
-
- InstructionFactory fact = getFactory();
- InstructionList il = new InstructionList();
- il.append(InstructionConstants.ACONST_NULL);
- il.append(thisJoinPointVar.createStore(fact));
- range.insert(il, Range.OutsideBefore);
- } else {
- appliedLazyTjpOptimization = false;
- InstructionFactory fact = getFactory();
- InstructionList il = createThisJoinPoint();
- il.append(thisJoinPointVar.createStore(fact));
- range.insert(il, Range.OutsideBefore);
- }
- }
-
- private boolean checkLazyTjp() {
- // check for around advice
- for (Iterator<ShadowMunger> i = mungers.iterator(); i.hasNext();) {
- ShadowMunger munger = i.next();
- if (munger instanceof Advice) {
- if (((Advice) munger).getKind() == AdviceKind.Around) {
- if (munger.getSourceLocation() != null) { // do we know enough to bother reporting?
- if (world.getLint().canNotImplementLazyTjp.isEnabled()) {
- world.getLint().canNotImplementLazyTjp.signal(new String[] { toString() }, getSourceLocation(),
- new ISourceLocation[] { munger.getSourceLocation() });
- }
- }
- return false;
- }
- }
- }
-
- return true;
- }
-
- InstructionList loadThisJoinPoint() {
- InstructionFactory fact = getFactory();
- InstructionList il = new InstructionList();
-
- if (isThisJoinPointLazy) {
- // If we're lazy, build the join point right here.
- il.append(createThisJoinPoint());
-
- // Does someone else need it? If so, store it for later retrieval
- if (lazyTjpConsumers > 1) {
- il.append(thisJoinPointVar.createStore(fact));
-
- InstructionHandle end = il.append(thisJoinPointVar.createLoad(fact));
-
- il.insert(InstructionFactory.createBranchInstruction(Constants.IFNONNULL, end));
- il.insert(thisJoinPointVar.createLoad(fact));
- }
- } else {
- // If not lazy, its already been built and stored, just retrieve it
- thisJoinPointVar.appendLoad(il, fact);
- }
-
- return il;
- }
-
- InstructionList createThisJoinPoint() {
- InstructionFactory fact = getFactory();
- InstructionList il = new InstructionList();
-
- BcelVar staticPart = getThisJoinPointStaticPartBcelVar();
- staticPart.appendLoad(il, fact);
- if (hasThis()) {
- ((BcelVar) getThisVar()).appendLoad(il, fact);
- } else {
- il.append(InstructionConstants.ACONST_NULL);
- }
- if (hasTarget()) {
- ((BcelVar) getTargetVar()).appendLoad(il, fact);
- } else {
- il.append(InstructionConstants.ACONST_NULL);
- }
-
- switch (getArgCount()) {
- case 0:
- il.append(fact.createInvoke("org.aspectj.runtime.reflect.Factory", "makeJP", LazyClassGen.tjpType, new Type[] {
- LazyClassGen.staticTjpType, Type.OBJECT, Type.OBJECT }, Constants.INVOKESTATIC));
- break;
- case 1:
- ((BcelVar) getArgVar(0)).appendLoadAndConvert(il, fact, world.getCoreType(ResolvedType.OBJECT));
- il.append(fact.createInvoke("org.aspectj.runtime.reflect.Factory", "makeJP", LazyClassGen.tjpType, new Type[] {
- LazyClassGen.staticTjpType, Type.OBJECT, Type.OBJECT, Type.OBJECT }, Constants.INVOKESTATIC));
- break;
- case 2:
- ((BcelVar) getArgVar(0)).appendLoadAndConvert(il, fact, world.getCoreType(ResolvedType.OBJECT));
- ((BcelVar) getArgVar(1)).appendLoadAndConvert(il, fact, world.getCoreType(ResolvedType.OBJECT));
- il.append(fact.createInvoke("org.aspectj.runtime.reflect.Factory", "makeJP", LazyClassGen.tjpType, new Type[] {
- LazyClassGen.staticTjpType, Type.OBJECT, Type.OBJECT, Type.OBJECT, Type.OBJECT }, Constants.INVOKESTATIC));
- break;
- default:
- il.append(makeArgsObjectArray());
- il.append(fact.createInvoke("org.aspectj.runtime.reflect.Factory", "makeJP", LazyClassGen.tjpType, new Type[] {
- LazyClassGen.staticTjpType, Type.OBJECT, Type.OBJECT, new ArrayType(Type.OBJECT, 1) }, Constants.INVOKESTATIC));
- break;
- }
-
- return il;
- }
-
- public BcelVar getThisJoinPointStaticPartBcelVar() {
- return getThisJoinPointStaticPartBcelVar(false);
- }
-
- @Override
- public BcelVar getThisAspectInstanceVar(ResolvedType aspectType) {
- return new AspectInstanceVar(aspectType);
- }
-
- /**
- * Get the Var for the xxxxJpStaticPart, xxx = this or enclosing
- *
- * @param isEnclosingJp true to have the enclosingJpStaticPart
- * @return
- */
- public BcelVar getThisJoinPointStaticPartBcelVar(final boolean isEnclosingJp) {
- if (thisJoinPointStaticPartVar == null) {
- Field field = getEnclosingClass().getTjpField(this, isEnclosingJp);
- ResolvedType sjpType = null;
- if (world.isTargettingAspectJRuntime12()) { // TAG:SUPPORTING12: We didn't have different jpsp types in 1.2
- sjpType = world.getCoreType(UnresolvedType.JOINPOINT_STATICPART);
- } else {
- sjpType = isEnclosingJp ? world.getCoreType(UnresolvedType.JOINPOINT_ENCLOSINGSTATICPART) : world
- .getCoreType(UnresolvedType.JOINPOINT_STATICPART);
- }
- thisJoinPointStaticPartVar = new BcelFieldRef(sjpType, getEnclosingClass().getClassName(), field.getName());
- // getEnclosingClass().warnOnAddedStaticInitializer(this,munger.getSourceLocation());
- }
- return thisJoinPointStaticPartVar;
- }
-
- /**
- * Get the Var for the enclosingJpStaticPart
- *
- * @return
- */
- public BcelVar getThisEnclosingJoinPointStaticPartBcelVar() {
- if (enclosingShadow == null) {
- // the enclosing of an execution is itself
- return getThisJoinPointStaticPartBcelVar(true);
- } else {
- return ((BcelShadow) enclosingShadow).getThisJoinPointStaticPartBcelVar(true);
- }
- }
-
- // ??? need to better understand all the enclosing variants
- @Override
- public Member getEnclosingCodeSignature() {
- if (getKind().isEnclosingKind()) {
- return getSignature();
- } else if (getKind() == Shadow.PreInitialization) {
- // PreInit doesn't enclose code but its signature
- // is correctly the signature of the ctor.
- return getSignature();
- } else if (enclosingShadow == null) {
- return getEnclosingMethod().getMemberView();
- } else {
- return enclosingShadow.getSignature();
- }
- }
-
- public Member getRealEnclosingCodeSignature() {
- return enclosingMethod.getMemberView();
- }
-
- // public Member getEnclosingCodeSignatureForModel() {
- // if (getKind().isEnclosingKind()) {
- // return getSignature();
- // } else if (getKind() == Shadow.PreInitialization) {
- // // PreInit doesn't enclose code but its signature
- // // is correctly the signature of the ctor.
- // return getSignature();
- // } else if (enclosingShadow == null) {
- // return getEnclosingMethod().getMemberView();
- // } else {
- // if (enclosingShadow.getKind() == Shadow.MethodExecution && enclosingMethod.getEffectiveSignature() != null) {
- //
- // } else {
- // return enclosingShadow.getSignature();
- // }
- // }
- // }
-
- private InstructionList makeArgsObjectArray() {
- InstructionFactory fact = getFactory();
- BcelVar arrayVar = genTempVar(UnresolvedType.OBJECTARRAY);
- final InstructionList il = new InstructionList();
- int alen = getArgCount();
- il.append(Utility.createConstant(fact, alen));
- il.append(fact.createNewArray(Type.OBJECT, (short) 1));
- arrayVar.appendStore(il, fact);
-
- int stateIndex = 0;
- for (int i = 0, len = getArgCount(); i < len; i++) {
- arrayVar.appendConvertableArrayStore(il, fact, stateIndex, (BcelVar) getArgVar(i));
- stateIndex++;
- }
- arrayVar.appendLoad(il, fact);
- return il;
- }
-
- // ---- initializing var tables
-
- /*
- * initializing this is doesn't do anything, because this is protected from side-effects, so we don't need to copy its location
- */
-
- private void initializeThisVar() {
- if (thisVar != null) {
- return;
- }
- thisVar = new BcelVar(getThisType().resolve(world), 0);
- thisVar.setPositionInAroundState(0);
- }
-
- public void initializeTargetVar() {
- InstructionFactory fact = getFactory();
- if (targetVar != null) {
- return;
- }
- if (getKind().isTargetSameAsThis()) {
- if (hasThis()) {
- initializeThisVar();
- }
- targetVar = thisVar;
- } else {
- initializeArgVars(); // gotta pop off the args before we find the target
- UnresolvedType type = getTargetType();
- type = ensureTargetTypeIsCorrect(type);
- targetVar = genTempVar(type, "ajc$target");
- range.insert(targetVar.createStore(fact), Range.OutsideBefore);
- targetVar.setPositionInAroundState(hasThis() ? 1 : 0);
- }
- }
-
- /*
- * PR 72528 This method double checks the target type under certain conditions. The Java 1.4 compilers seem to take calls to
- * clone methods on array types and create bytecode that looks like clone is being called on Object. If we advise a clone call
- * with around advice we extract the call into a helper method which we can then refer to. Because the type in the bytecode for
- * the call to clone is Object we create a helper method with an Object parameter - this is not correct as we have lost the fact
- * that the actual type is an array type. If we don't do the check below we will create code that fails java verification. This
- * method checks for the peculiar set of conditions and if they are true, it has a sneak peek at the code before the call to see
- * what is on the stack.
- */
- public UnresolvedType ensureTargetTypeIsCorrect(UnresolvedType tx) {
-
- Member msig = getSignature();
- if (msig.getArity() == 0 && getKind() == MethodCall && msig.getName().charAt(0) == 'c' && tx.equals(ResolvedType.OBJECT)
- && msig.getReturnType().equals(ResolvedType.OBJECT) && msig.getName().equals("clone")) {
-
- // Lets go back through the code from the start of the shadow
- InstructionHandle searchPtr = range.getStart().getPrev();
- while (Range.isRangeHandle(searchPtr) || searchPtr.getInstruction().isStoreInstruction()) { // ignore this instruction -
- // it doesnt give us the
- // info we want
- searchPtr = searchPtr.getPrev();
- }
-
- // A load instruction may tell us the real type of what the clone() call is on
- if (searchPtr.getInstruction().isLoadInstruction()) {
- LocalVariableTag lvt = LazyMethodGen.getLocalVariableTag(searchPtr, searchPtr.getInstruction().getIndex());
- if (lvt != null) {
- return UnresolvedType.forSignature(lvt.getType());
- }
- }
- // A field access instruction may tell us the real type of what the clone() call is on
- if (searchPtr.getInstruction() instanceof FieldInstruction) {
- FieldInstruction si = (FieldInstruction) searchPtr.getInstruction();
- Type t = si.getFieldType(getEnclosingClass().getConstantPool());
- return BcelWorld.fromBcel(t);
- }
- // A new array instruction obviously tells us it is an array type !
- if (searchPtr.getInstruction().opcode == Constants.ANEWARRAY) {
- // ANEWARRAY ana = (ANEWARRAY)searchPoint.getInstruction();
- // Type t = ana.getType(getEnclosingClass().getConstantPool());
- // Just use a standard java.lang.object array - that will work fine
- return BcelWorld.fromBcel(new ArrayType(Type.OBJECT, 1));
- }
- // A multi new array instruction obviously tells us it is an array type !
- if (searchPtr.getInstruction() instanceof MULTIANEWARRAY) {
- MULTIANEWARRAY ana = (MULTIANEWARRAY) searchPtr.getInstruction();
- // Type t = ana.getType(getEnclosingClass().getConstantPool());
- // t = new ArrayType(t,ana.getDimensions());
- // Just use a standard java.lang.object array - that will work fine
- return BcelWorld.fromBcel(new ArrayType(Type.OBJECT, ana.getDimensions()));
- }
- throw new BCException("Can't determine real target of clone() when processing instruction "
- + searchPtr.getInstruction() + ". Perhaps avoid selecting clone with your pointcut?");
- }
- return tx;
- }
-
- public void ensureInitializedArgVar(int argNumber) {
- if (allArgVarsInitialized || (argVars != null && argVars[argNumber] != null)) {
- return;
- }
- InstructionFactory fact = getFactory();
- int len = getArgCount();
- if (argVars == null) {
- argVars = new BcelVar[len];
- }
-
- // Need to initialize argument i
- int positionOffset = (hasTarget() ? 1 : 0) + ((hasThis() && !getKind().isTargetSameAsThis()) ? 1 : 0);
-
- if (getKind().argsOnStack()) {
- // Let's just do them all now since they are on the stack
- // we move backwards because we're popping off the stack
- for (int i = len - 1; i >= 0; i--) {
- UnresolvedType type = getArgType(i);
- BcelVar tmp = genTempVar(type, "ajc$arg" + i);
- range.insert(tmp.createStore(getFactory()), Range.OutsideBefore);
- int position = i;
- position += positionOffset;
- tmp.setPositionInAroundState(position);
- argVars[i] = tmp;
- }
- allArgVarsInitialized = true;
- } else {
- int index = 0;
- if (arg0HoldsThis()) {
- index++;
- }
- boolean allInited = true;
- for (int i = 0; i < len; i++) {
- UnresolvedType type = getArgType(i);
- if (i == argNumber) {
- argVars[argNumber] = genTempVar(type, "ajc$arg" + argNumber);
- range.insert(argVars[argNumber].createCopyFrom(fact, index), Range.OutsideBefore);
- argVars[argNumber].setPositionInAroundState(argNumber + positionOffset);
- }
- allInited = allInited && argVars[i] != null;
- index += type.getSize();
- }
- if (allInited && (argNumber + 1) == len) {
- allArgVarsInitialized = true;
- }
- }
- }
-
- /**
- * Initialize all the available arguments at the shadow. This means creating a copy of them that we can then use for advice
- * calls (the copy ensures we are not affected by other advice changing the values). This method initializes all arguments
- * whereas the method ensureInitializedArgVar will only ensure a single argument is setup.
- */
- public void initializeArgVars() {
- if (allArgVarsInitialized) {
- return;
- }
- InstructionFactory fact = getFactory();
- int len = getArgCount();
- if (argVars == null) {
- argVars = new BcelVar[len];
- }
- int positionOffset = (hasTarget() ? 1 : 0) + ((hasThis() && !getKind().isTargetSameAsThis()) ? 1 : 0);
-
- if (getKind().argsOnStack()) {
- // we move backwards because we're popping off the stack
- for (int i = len - 1; i >= 0; i--) {
- UnresolvedType type = getArgType(i);
- BcelVar tmp = genTempVar(type, "ajc$arg" + i);
- range.insert(tmp.createStore(getFactory()), Range.OutsideBefore);
- int position = i;
- position += positionOffset;
- tmp.setPositionInAroundState(position);
- argVars[i] = tmp;
- }
- } else {
- int index = 0;
- if (arg0HoldsThis()) {
- index++;
- }
-
- for (int i = 0; i < len; i++) {
- UnresolvedType type = getArgType(i);
- if (argVars[i] == null) {
- BcelVar tmp = genTempVar(type, "ajc$arg" + i);
- range.insert(tmp.createCopyFrom(fact, index), Range.OutsideBefore);
- argVars[i] = tmp;
- tmp.setPositionInAroundState(i + positionOffset);
- }
- index += type.resolve(world).getSize();
- }
- }
- allArgVarsInitialized = true;
-
- }
-
- public void initializeForAroundClosure() {
- initializeArgVars();
- if (hasTarget()) {
- initializeTargetVar();
- }
- if (hasThis()) {
- initializeThisVar();
- // System.out.println("initialized: " + this + " thisVar = " + thisVar);
- }
- }
-
- public void initializeThisAnnotationVars() {
- if (thisAnnotationVars != null) {
- return;
- }
- thisAnnotationVars = new HashMap<ResolvedType, TypeAnnotationAccessVar>();
- // populate..
- }
-
- public void initializeTargetAnnotationVars() {
- if (targetAnnotationVars != null) {
- return;
- }
- if (getKind().isTargetSameAsThis()) {
- if (hasThis()) {
- initializeThisAnnotationVars();
- }
- targetAnnotationVars = thisAnnotationVars;
- } else {
- targetAnnotationVars = new HashMap<ResolvedType, TypeAnnotationAccessVar>();
- ResolvedType[] rtx = this.getTargetType().resolve(world).getAnnotationTypes(); // what about annotations we havent
- // gotten yet but we will get in
- // subclasses?
- for (int i = 0; i < rtx.length; i++) {
- ResolvedType typeX = rtx[i];
- targetAnnotationVars.put(typeX, new TypeAnnotationAccessVar(typeX, (BcelVar) getTargetVar()));
- }
- // populate.
- }
- }
-
- // public void initializeArgAnnotationVars() {
- // if (argAnnotationVars != null) {
- // return;
- // }
- // int numArgs = getArgCount();
- // argAnnotationVars = new Map[numArgs];
- // for (int i = 0; i < argAnnotationVars.length; i++) {
- // argAnnotationVars[i] = new HashMap();
- // // FIXME asc just delete this logic - we always build the Var on demand, as we don't know at weave time
- // // what the full set of annotations could be (due to static/dynamic type differences...)
- // }
- // }
-
- protected ResolvedMember getRelevantMember(ResolvedMember foundMember, Member relevantMember, ResolvedType relevantType) {
- if (foundMember != null) {
- return foundMember;
- }
-
- foundMember = getSignature().resolve(world);
- if (foundMember == null && relevantMember != null) {
- foundMember = relevantType.lookupMemberWithSupersAndITDs(relevantMember);
- }
-
- // check the ITD'd dooberries
- List<ConcreteTypeMunger> mungers = relevantType.resolve(world).getInterTypeMungers();
- for (ConcreteTypeMunger typeMunger : mungers) {
- if (typeMunger.getMunger() instanceof NewMethodTypeMunger || typeMunger.getMunger() instanceof NewConstructorTypeMunger) {
- ResolvedMember fakerm = typeMunger.getSignature();
- if (fakerm.getName().equals(getSignature().getName())
- && fakerm.getParameterSignature().equals(getSignature().getParameterSignature())) {
- if (foundMember.getKind() == ResolvedMember.CONSTRUCTOR) {
- foundMember = AjcMemberMaker.interConstructor(relevantType, foundMember, typeMunger.getAspectType());
- } else {
- foundMember = AjcMemberMaker.interMethod(foundMember, typeMunger.getAspectType(), false);
- // ResolvedMember o = AjcMemberMaker.interMethodBody(fakerm, typeMunger.getAspectType());
- // // Object os = o.getAnnotations();
- // ResolvedMember foundMember2 = findMethod(typeMunger.getAspectType(), o);
- // Object os2 = foundMember2.getAnnotations();
- // int stop = 1;
- // foundMember = foundMember2;
- // foundMember = AjcMemberMaker.interMethod(foundMember, typeMunger.getAspectType());
- }
- // in the above.. what about if it's on an Interface? Can that happen?
- // then the last arg of the above should be true
- return foundMember;
- }
- }
- }
- return foundMember;
- }
-
- protected ResolvedType[] getAnnotations(ResolvedMember foundMember, Member relevantMember, ResolvedType relevantType) {
- if (foundMember == null) {
- // check the ITD'd dooberries
- List<ConcreteTypeMunger> mungers = relevantType.resolve(world).getInterTypeMungers();
- for (Iterator<ConcreteTypeMunger> iter = mungers.iterator(); iter.hasNext();) {
- Object munger = iter.next();
- ConcreteTypeMunger typeMunger = (ConcreteTypeMunger) munger;
- if (typeMunger.getMunger() instanceof NewMethodTypeMunger
- || typeMunger.getMunger() instanceof NewConstructorTypeMunger) {
- ResolvedMember fakerm = typeMunger.getSignature();
- // if (fakerm.hasAnnotations())
-
- ResolvedMember ajcMethod = (getSignature().getKind() == ResolvedMember.CONSTRUCTOR ? AjcMemberMaker
- .postIntroducedConstructor(typeMunger.getAspectType(), fakerm.getDeclaringType(),
- fakerm.getParameterTypes()) : AjcMemberMaker.interMethodDispatcher(fakerm,
- typeMunger.getAspectType()));
- // AjcMemberMaker.interMethodBody(fakerm,typeMunger.getAspectType()));
- ResolvedMember rmm = findMethod(typeMunger.getAspectType(), ajcMethod);
- if (fakerm.getName().equals(getSignature().getName())
- && fakerm.getParameterSignature().equals(getSignature().getParameterSignature())) {
- relevantType = typeMunger.getAspectType();
- foundMember = rmm;
- return foundMember.getAnnotationTypes();
- }
- }
- }
- // didn't find in ITDs, look in supers
- foundMember = relevantType.lookupMemberWithSupersAndITDs(relevantMember);
- if (foundMember == null) {
- throw new IllegalStateException("Couldn't find member " + relevantMember + " for type " + relevantType);
- }
- }
- return foundMember.getAnnotationTypes();
- }
-
- /**
- * 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.
- */
- public void initializeKindedAnnotationVars() {
- if (kindedAnnotationVars != null) {
- return;
- }
- kindedAnnotationVars = new HashMap<ResolvedType, AnnotationAccessVar>();
-
- ResolvedType[] annotations = null;
- Member shadowSignature = getSignature();
- Member annotationHolder = getSignature();
- ResolvedType relevantType = shadowSignature.getDeclaringType().resolve(world);
-
- if (relevantType.isRawType() || relevantType.isParameterizedType()) {
- relevantType = relevantType.getGenericType();
- }
-
- // Determine the annotations that are of interest
- if (getKind() == Shadow.StaticInitialization) {
- annotations = relevantType.resolve(world).getAnnotationTypes();
- } else if (getKind() == Shadow.MethodCall || getKind() == Shadow.ConstructorCall) {
- 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) {
- annotationHolder = findField(relevantType.getDeclaredFields(), getSignature());
-
- if (annotationHolder == null) {
- // check the ITD'd dooberries
- List<ConcreteTypeMunger> mungers = relevantType.resolve(world).getInterTypeMungers();
- for (ConcreteTypeMunger typeMunger : mungers) {
- if (typeMunger.getMunger() instanceof NewFieldTypeMunger) {
- ResolvedMember fakerm = typeMunger.getSignature();
- // if (fakerm.hasAnnotations())
- ResolvedMember ajcMethod = AjcMemberMaker.interFieldInitializer(fakerm, typeMunger.getAspectType());
- ResolvedMember rmm = findMethod(typeMunger.getAspectType(), ajcMethod);
- if (fakerm.equals(getSignature())) {
- relevantType = typeMunger.getAspectType();
- annotationHolder = rmm;
- }
- }
- }
- }
- annotations = ((ResolvedMember) annotationHolder).getAnnotationTypes();
-
- } else if (getKind() == Shadow.MethodExecution || getKind() == Shadow.ConstructorExecution
- || getKind() == Shadow.AdviceExecution) {
-
- ResolvedMember foundMember = findMethod2(relevantType.getDeclaredMethods(), getSignature());
- annotations = getAnnotations(foundMember, shadowSignature, relevantType);
- annotationHolder = getRelevantMember(foundMember, annotationHolder, relevantType);
- UnresolvedType ut = annotationHolder.getDeclaringType();
- relevantType = ut.resolve(world);
-
- } else if (getKind() == Shadow.ExceptionHandler) {
- relevantType = getSignature().getParameterTypes()[0].resolve(world);
- annotations = relevantType.getAnnotationTypes();
-
- } else if (getKind() == Shadow.PreInitialization || getKind() == Shadow.Initialization) {
- ResolvedMember found = findMethod2(relevantType.getDeclaredMethods(), getSignature());
- annotations = found.getAnnotationTypes();
- }
-
- if (annotations == null) {
- // We can't have recognized the shadow - should blow up now to be on the safe side
- throw new BCException("Could not discover annotations for shadow: " + getKind());
- }
-
- for (ResolvedType annotationType : annotations) {
- AnnotationAccessVar accessVar = new AnnotationAccessVar(this, getKind(), annotationType.resolve(world), relevantType,
- annotationHolder, false);
- kindedAnnotationVars.put(annotationType, accessVar);
- }
- }
-
- private ResolvedMember findMethod2(ResolvedMember members[], Member sig) {
- String signatureName = sig.getName();
- String parameterSignature = sig.getParameterSignature();
- for (ResolvedMember member : members) {
- if (member.getName().equals(signatureName) && member.getParameterSignature().equals(parameterSignature)) {
- return member;
- }
- }
- return null;
- }
-
- private ResolvedMember findMethod(ResolvedType aspectType, ResolvedMember ajcMethod) {
- ResolvedMember decMethods[] = aspectType.getDeclaredMethods();
- for (int i = 0; i < decMethods.length; i++) {
- ResolvedMember member = decMethods[i];
- if (member.equals(ajcMethod)) {
- return member;
- }
- }
- return null;
- }
-
- private ResolvedMember findField(ResolvedMember[] members, Member lookingFor) {
- for (int i = 0; i < members.length; i++) {
- ResolvedMember member = members[i];
- if (member.getName().equals(getSignature().getName()) && member.getType().equals(getSignature().getType())) {
- return member;
- }
- }
- return null;
- }
-
- public void initializeWithinAnnotationVars() {
- if (withinAnnotationVars != null) {
- return;
- }
- withinAnnotationVars = new HashMap<ResolvedType, AnnotationAccessVar>();
-
- ResolvedType[] annotations = getEnclosingType().resolve(world).getAnnotationTypes();
- for (int i = 0; i < annotations.length; i++) {
- ResolvedType ann = annotations[i];
- Kind k = Shadow.StaticInitialization;
- withinAnnotationVars.put(ann, new AnnotationAccessVar(this, k, ann, getEnclosingType(), null, true));
- }
- }
-
- public void initializeWithinCodeAnnotationVars() {
- if (withincodeAnnotationVars != null) {
- return;
- }
- withincodeAnnotationVars = new HashMap<ResolvedType, AnnotationAccessVar>();
-
- // For some shadow we are interested in annotations on the method containing that shadow.
- ResolvedType[] annotations = getEnclosingMethod().getMemberView().getAnnotationTypes();
- for (int i = 0; i < annotations.length; i++) {
- ResolvedType ann = annotations[i];
- Kind k = (getEnclosingMethod().getMemberView().getKind() == Member.CONSTRUCTOR ? Shadow.ConstructorExecution
- : Shadow.MethodExecution);
- withincodeAnnotationVars.put(ann, new AnnotationAccessVar(this, k, ann, getEnclosingType(),
- getEnclosingCodeSignature(), true));
- }
- }
-
- // ---- weave methods
-
- void weaveBefore(BcelAdvice munger) {
- range.insert(munger.getAdviceInstructions(this, null, range.getRealStart()), Range.InsideBefore);
- }
-
- public void weaveAfter(BcelAdvice munger) {
- weaveAfterThrowing(munger, UnresolvedType.THROWABLE);
- weaveAfterReturning(munger);
- }
-
- /**
- * The basic strategy here is to add a set of instructions at the end of the shadow range that dispatch the advice, and then
- * return whatever the shadow was going to return anyway.
- *
- * To achieve this, we note all the return statements in the advice, and replace them with code that: 1) stores the return value
- * on top of the stack in a temp var 2) jumps to the start of our advice block 3) restores the return value at the end of the
- * advice block before ultimately returning
- *
- * We also need to bind the return value into a returning parameter, if the advice specified one.
- */
- public void weaveAfterReturning(BcelAdvice munger) {
- List<InstructionHandle> 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<InstructionHandle> i = returns.iterator(); i.hasNext();) {
- InstructionHandle ih = i.next();
- retargetReturnInstruction(munger.hasExtraParameter(), returnValueVar, gotoTarget, ih);
- }
- }
-
- range.append(advice);
- range.append(retList);
- }
-
- /**
- * @return a list of all the return instructions in the range of this shadow
- */
- private List<InstructionHandle> findReturnInstructions() {
- List<InstructionHandle> returns = new ArrayList<InstructionHandle>();
- for (InstructionHandle ih = range.getStart(); ih != range.getEnd(); ih = ih.getNext()) {
- if (ih.getInstruction().isReturnInstruction()) {
- returns.add(ih);
- }
- }
- return returns;
- }
-
- /**
- * Given a list containing all the return instruction handles for this shadow, finds the last return instruction and copies it,
- * making this the ultimate return. If the shadow has a non-void return type, we also create a temporary variable to hold the
- * return value, and load the value from this var before returning (see pr148007 for why we do this - it works around a JRockit
- * bug, and is also closer to what javac generates)
- *
- * Sometimes the 'last return' isnt the right one - some rogue code can include the real return from the body of a subroutine
- * that exists at the end of the method. In this case the last return is RETURN but that may not be correct for a method with a
- * non-void return type... pr151673
- *
- * @param returns list of all the return instructions in the shadow
- * @param returnInstructions instruction list into which the return instructions should be generated
- * @return the variable holding the return value, if needed
- */
- private BcelVar generateReturnInstructions(List<InstructionHandle> returns, InstructionList returnInstructions) {
- BcelVar returnValueVar = null;
- if (this.hasANonVoidReturnType()) {
- // Find the last *correct* return - this is a method with a non-void return type
- // so ignore RETURN
- Instruction newReturnInstruction = null;
- int i = returns.size() - 1;
- while (newReturnInstruction == null && i >= 0) {
- InstructionHandle ih = returns.get(i);
- if (ih.getInstruction().opcode != Constants.RETURN) {
- newReturnInstruction = Utility.copyInstruction(ih.getInstruction());
- }
- i--;
- }
- returnValueVar = genTempVar(this.getReturnType());
- returnValueVar.appendLoad(returnInstructions, getFactory());
- returnInstructions.append(newReturnInstruction);
- } else {
- InstructionHandle lastReturnHandle = returns.get(returns.size() - 1);
- Instruction newReturnInstruction = Utility.copyInstruction(lastReturnHandle.getInstruction());
- returnInstructions.append(newReturnInstruction);
- }
- return returnValueVar;
- }
-
- /**
- * @return true, iff this shadow returns a value
- */
- private boolean hasANonVoidReturnType() {
- return !this.getReturnType().equals(UnresolvedType.VOID);
- }
-
- /**
- * Get the list of instructions used to dispatch to the after advice
- *
- * @param munger
- * @param firstInstructionInReturnSequence
- * @return
- */
- private InstructionList getAfterReturningAdviceDispatchInstructions(BcelAdvice munger,
- InstructionHandle firstInstructionInReturnSequence) {
- InstructionList advice = new InstructionList();
-
- BcelVar tempVar = null;
- if (munger.hasExtraParameter()) {
- tempVar = insertAdviceInstructionsForBindingReturningParameter(advice);
- }
- advice.append(munger.getAdviceInstructions(this, tempVar, firstInstructionInReturnSequence));
- return advice;
- }
-
- /**
- * If the after() returning(Foo f) form is used, bind the return value to the parameter. If the shadow returns void, bind null.
- *
- * @param advice
- * @return
- */
- private BcelVar insertAdviceInstructionsForBindingReturningParameter(InstructionList advice) {
- BcelVar tempVar;
- UnresolvedType tempVarType = getReturnType();
- if (tempVarType.equals(UnresolvedType.VOID)) {
- tempVar = genTempVar(UnresolvedType.OBJECT);
- advice.append(InstructionConstants.ACONST_NULL);
- tempVar.appendStore(advice, getFactory());
- } else {
- tempVar = genTempVar(tempVarType);
- advice.append(InstructionFactory.createDup(tempVarType.getSize()));
- tempVar.appendStore(advice, getFactory());
- }
- return tempVar;
- }
-
- /**
- * Helper method for weaveAfterReturning
- *
- * Each return instruction in the method body is retargeted by calling this method. The return instruction is replaced by up to
- * three instructions: 1) if the shadow returns a value, and that value is bound to an after returning parameter, then we DUP
- * the return value on the top of the stack 2) if the shadow returns a value, we store it in the returnValueVar (it will be
- * retrieved from here when we ultimately return after the advice dispatch) 3) if the return was the last instruction, we add a
- * NOP (it will fall through to the advice dispatch), otherwise we add a GOTO that branches to the supplied gotoTarget (start of
- * the advice dispatch)
- */
- private void retargetReturnInstruction(boolean hasReturningParameter, BcelVar returnValueVar, InstructionHandle gotoTarget,
- InstructionHandle returnHandle) {
- // pr148007, work around JRockit bug
- // replace ret with store into returnValueVar, followed by goto if not
- // at the end of the instruction list...
- InstructionList newInstructions = new InstructionList();
- if (returnValueVar != null) {
- if (hasReturningParameter) {
- // we have to dup the return val before consuming it...
- newInstructions.append(InstructionFactory.createDup(this.getReturnType().getSize()));
- }
- // store the return value into this var
- returnValueVar.appendStore(newInstructions, getFactory());
- }
- if (!isLastInstructionInRange(returnHandle, range)) {
- newInstructions.append(InstructionFactory.createBranchInstruction(Constants.GOTO, gotoTarget));
- }
- if (newInstructions.isEmpty()) {
- newInstructions.append(InstructionConstants.NOP);
- }
- Utility.replaceInstruction(returnHandle, newInstructions, enclosingMethod);
- }
-
- private boolean isLastInstructionInRange(InstructionHandle ih, ShadowRange aRange) {
- return ih.getNext() == aRange.getEnd();
- }
-
- public void weaveAfterThrowing(BcelAdvice munger, UnresolvedType catchType) {
- // a good optimization would be not to generate anything here
- // if the shadow is GUARANTEED empty (i.e., there's NOTHING, not even
- // a shadow, inside me).
- if (getRange().getStart().getNext() == getRange().getEnd()) {
- return;
- }
- InstructionFactory fact = getFactory();
- InstructionList handler = new InstructionList();
- BcelVar exceptionVar = genTempVar(catchType);
- exceptionVar.appendStore(handler, fact);
-
- // pr62642
- // I will now jump through some firey BCEL hoops to generate a trivial bit of code:
- // if (exc instanceof ExceptionInInitializerError)
- // throw (ExceptionInInitializerError)exc;
- if (this.getEnclosingMethod().getName().equals("<clinit>")) {
- ResolvedType eiieType = world.resolve("java.lang.ExceptionInInitializerError");
- ObjectType eiieBcelType = (ObjectType) BcelWorld.makeBcelType(eiieType);
- InstructionList ih = new InstructionList(InstructionConstants.NOP);
- handler.append(exceptionVar.createLoad(fact));
- handler.append(fact.createInstanceOf(eiieBcelType));
- InstructionBranch bi = InstructionFactory.createBranchInstruction(Constants.IFEQ, ih.getStart());
- handler.append(bi);
- handler.append(exceptionVar.createLoad(fact));
- handler.append(fact.createCheckCast(eiieBcelType));
- handler.append(InstructionConstants.ATHROW);
- handler.append(ih);
- }
-
- InstructionList endHandler = new InstructionList(exceptionVar.createLoad(fact));
- handler.append(munger.getAdviceInstructions(this, exceptionVar, endHandler.getStart()));
- handler.append(endHandler);
- handler.append(InstructionConstants.ATHROW);
- InstructionHandle handlerStart = handler.getStart();
-
- if (isFallsThrough()) {
- InstructionHandle jumpTarget = handler.append(InstructionConstants.NOP);
- handler.insert(InstructionFactory.createBranchInstruction(Constants.GOTO, jumpTarget));
- }
- InstructionHandle protectedEnd = handler.getStart();
- range.insert(handler, Range.InsideAfter);
-
- enclosingMethod.addExceptionHandler(range.getStart().getNext(), protectedEnd.getPrev(), handlerStart,
- (ObjectType) BcelWorld.makeBcelType(catchType), // ???Type.THROWABLE,
- // high priority if our args are on the stack
- getKind().hasHighPriorityExceptions());
- }
-
- // ??? this shares a lot of code with the above weaveAfterThrowing
- // ??? would be nice to abstract that to say things only once
- public void weaveSoftener(BcelAdvice munger, UnresolvedType catchType) {
- // a good optimization would be not to generate anything here
- // if the shadow is GUARANTEED empty (i.e., there's NOTHING, not even
- // a shadow, inside me).
- if (getRange().getStart().getNext() == getRange().getEnd()) {
- return;
- }
-
- InstructionFactory fact = getFactory();
- InstructionList handler = new InstructionList();
- InstructionList rtExHandler = new InstructionList();
- BcelVar exceptionVar = genTempVar(catchType);
-
- handler.append(fact.createNew(NameMangler.SOFT_EXCEPTION_TYPE));
- handler.append(InstructionFactory.createDup(1));
- handler.append(exceptionVar.createLoad(fact));
- handler.append(fact.createInvoke(NameMangler.SOFT_EXCEPTION_TYPE, "<init>", Type.VOID, new Type[] { Type.THROWABLE },
- Constants.INVOKESPECIAL)); // ??? special
- handler.append(InstructionConstants.ATHROW);
-
- // ENH 42737
- exceptionVar.appendStore(rtExHandler, fact);
- // aload_1
- rtExHandler.append(exceptionVar.createLoad(fact));
- // instanceof class java/lang/RuntimeException
- rtExHandler.append(fact.createInstanceOf(new ObjectType("java.lang.RuntimeException")));
- // ifeq go to new SOFT_EXCEPTION_TYPE instruction
- rtExHandler.append(InstructionFactory.createBranchInstruction(Constants.IFEQ, handler.getStart()));
- // aload_1
- rtExHandler.append(exceptionVar.createLoad(fact));
- // athrow
- rtExHandler.append(InstructionFactory.ATHROW);
-
- InstructionHandle handlerStart = rtExHandler.getStart();
-
- if (isFallsThrough()) {
- InstructionHandle jumpTarget = range.getEnd();// handler.append(fact.NOP);
- rtExHandler.insert(InstructionFactory.createBranchInstruction(Constants.GOTO, jumpTarget));
- }
-
- rtExHandler.append(handler);
-
- InstructionHandle protectedEnd = rtExHandler.getStart();
- range.insert(rtExHandler, Range.InsideAfter);
-
- enclosingMethod.addExceptionHandler(range.getStart().getNext(), protectedEnd.getPrev(), handlerStart,
- (ObjectType) BcelWorld.makeBcelType(catchType),
- // high priority if our args are on the stack
- getKind().hasHighPriorityExceptions());
- }
-
- public void weavePerObjectEntry(final BcelAdvice munger, final BcelVar onVar) {
- final InstructionFactory fact = getFactory();
-
- InstructionList entryInstructions = new InstructionList();
- InstructionList entrySuccessInstructions = new InstructionList();
- onVar.appendLoad(entrySuccessInstructions, fact);
-
- entrySuccessInstructions
- .append(Utility.createInvoke(fact, world, AjcMemberMaker.perObjectBind(munger.getConcreteAspect())));
-
- InstructionList testInstructions = munger.getTestInstructions(this, entrySuccessInstructions.getStart(),
- range.getRealStart(), entrySuccessInstructions.getStart());
-
- entryInstructions.append(testInstructions);
- entryInstructions.append(entrySuccessInstructions);
-
- range.insert(entryInstructions, Range.InsideBefore);
- }
-
- // PTWIMPL Create static initializer to call the aspect factory
- /**
- * Causes the aspect instance to be *set* for later retrievable through localAspectof()/aspectOf()
- */
- public void weavePerTypeWithinAspectInitialization(final BcelAdvice munger, UnresolvedType t) {
- ResolvedType tResolved = t.resolve(world);
- if (tResolved.isInterface()) {
- return; // Don't initialize statics in interfaces
- }
- ResolvedType aspectRT = munger.getConcreteAspect();
- BcelWorld.getBcelObjectType(aspectRT);
-
- // Although matched, if the visibility rules prevent the aspect from seeing this type, don't
- // insert any code (easier to do it here than try to affect the matching logic, unfortunately)
- if (!(tResolved.canBeSeenBy(aspectRT) || aspectRT.isPrivilegedAspect())) {
- return;
- }
-
- final InstructionFactory fact = getFactory();
-
- InstructionList entryInstructions = new InstructionList();
- InstructionList entrySuccessInstructions = new InstructionList();
-
- String aspectname = munger.getConcreteAspect().getName();
-
- String ptwField = NameMangler.perTypeWithinFieldForTarget(munger.getConcreteAspect());
- entrySuccessInstructions.append(InstructionFactory.PUSH(fact.getConstantPool(), t.getName()));
-
- entrySuccessInstructions.append(fact.createInvoke(aspectname, "ajc$createAspectInstance", new ObjectType(aspectname),
- new Type[] { new ObjectType("java.lang.String") }, Constants.INVOKESTATIC));
- entrySuccessInstructions.append(fact.createPutStatic(t.getName(), ptwField, new ObjectType(aspectname)));
-
- entryInstructions.append(entrySuccessInstructions);
-
- range.insert(entryInstructions, Range.InsideBefore);
- }
-
- public void weaveCflowEntry(final BcelAdvice munger, final Member cflowField) {
- final boolean isPer = munger.getKind() == AdviceKind.PerCflowBelowEntry || munger.getKind() == AdviceKind.PerCflowEntry;
- if (!isPer && getKind() == PreInitialization) {
- return;
- }
- final Type objectArrayType = new ArrayType(Type.OBJECT, 1);
- final InstructionFactory fact = getFactory();
-
- final BcelVar testResult = genTempVar(UnresolvedType.BOOLEAN);
-
- InstructionList entryInstructions = new InstructionList();
- {
- InstructionList entrySuccessInstructions = new InstructionList();
-
- if (munger.hasDynamicTests()) {
- entryInstructions.append(Utility.createConstant(fact, 0));
- testResult.appendStore(entryInstructions, fact);
-
- entrySuccessInstructions.append(Utility.createConstant(fact, 1));
- testResult.appendStore(entrySuccessInstructions, fact);
- }
-
- if (isPer) {
- entrySuccessInstructions.append(fact.createInvoke(munger.getConcreteAspect().getName(),
- NameMangler.PERCFLOW_PUSH_METHOD, Type.VOID, new Type[] {}, Constants.INVOKESTATIC));
- } else {
- BcelVar[] cflowStateVars = munger.getExposedStateAsBcelVars(false);
-
- if (cflowStateVars.length == 0) {
- // This should be getting managed by a counter - lets make sure.
- if (!cflowField.getType().getName().endsWith("CFlowCounter")) {
- throw new RuntimeException("Incorrectly attempting counter operation on stacked cflow");
- }
- entrySuccessInstructions.append(Utility.createGet(fact, cflowField));
- // arrayVar.appendLoad(entrySuccessInstructions, fact);
- entrySuccessInstructions.append(fact.createInvoke(NameMangler.CFLOW_COUNTER_TYPE, "inc", Type.VOID,
- new Type[] {}, Constants.INVOKEVIRTUAL));
- } else {
- BcelVar arrayVar = genTempVar(UnresolvedType.OBJECTARRAY);
-
- int alen = cflowStateVars.length;
- entrySuccessInstructions.append(Utility.createConstant(fact, alen));
- entrySuccessInstructions.append(fact.createNewArray(Type.OBJECT, (short) 1));
- arrayVar.appendStore(entrySuccessInstructions, fact);
-
- for (int i = 0; i < alen; i++) {
- arrayVar.appendConvertableArrayStore(entrySuccessInstructions, fact, i, cflowStateVars[i]);
- }
-
- entrySuccessInstructions.append(Utility.createGet(fact, cflowField));
- arrayVar.appendLoad(entrySuccessInstructions, fact);
-
- entrySuccessInstructions.append(fact.createInvoke(NameMangler.CFLOW_STACK_TYPE, "push", Type.VOID,
- new Type[] { objectArrayType }, Constants.INVOKEVIRTUAL));
- }
- }
-
- InstructionList testInstructions = munger.getTestInstructions(this, entrySuccessInstructions.getStart(),
- range.getRealStart(), entrySuccessInstructions.getStart());
- entryInstructions.append(testInstructions);
- entryInstructions.append(entrySuccessInstructions);
- }
-
- BcelAdvice exitAdvice = new BcelAdvice(null, null, null, 0, 0, 0, null, munger.getConcreteAspect()) {
- @Override
- public InstructionList getAdviceInstructions(BcelShadow s, BcelVar extraArgVar, InstructionHandle ifNoAdvice) {
- InstructionList exitInstructions = new InstructionList();
- if (munger.hasDynamicTests()) {
- testResult.appendLoad(exitInstructions, fact);
- exitInstructions.append(InstructionFactory.createBranchInstruction(Constants.IFEQ, ifNoAdvice));
- }
- exitInstructions.append(Utility.createGet(fact, cflowField));
- if (munger.getKind() != AdviceKind.PerCflowEntry && munger.getKind() != AdviceKind.PerCflowBelowEntry
- && munger.getExposedStateAsBcelVars(false).length == 0) {
- exitInstructions.append(fact.createInvoke(NameMangler.CFLOW_COUNTER_TYPE, "dec", Type.VOID, new Type[] {},
- Constants.INVOKEVIRTUAL));
- } else {
- exitInstructions.append(fact.createInvoke(NameMangler.CFLOW_STACK_TYPE, "pop", Type.VOID, new Type[] {},
- Constants.INVOKEVIRTUAL));
- }
- return exitInstructions;
- }
- };
-// if (getKind() == PreInitialization) {
-// weaveAfterReturning(exitAdvice);
-// }
-// else {
- weaveAfter(exitAdvice);
-// }
-
- range.insert(entryInstructions, Range.InsideBefore);
- }
-
- /*
- * Implementation notes:
- *
- * AroundInline still extracts the instructions of the original shadow into an extracted method. This allows inlining of even
- * that advice that doesn't call proceed or calls proceed more than once.
- *
- * It extracts the instructions of the original shadow into a method.
- *
- * Then it extracts the instructions of the advice into a new method defined on this enclosing class. This new method can then
- * be specialized as below.
- *
- * Then it searches in the instructions of the advice for any call to the proceed method.
- *
- * At such a call, there is stuff on the stack representing the arguments to proceed. Pop these into the frame.
- *
- * Now build the stack for the call to the extracted method, taking values either from the join point state or from the new
- * frame locs from proceed. Now call the extracted method. The right return value should be on the stack, so no cast is
- * necessary.
- *
- * If only one call to proceed is made, we can re-inline the original shadow. We are not doing that presently.
- *
- * If the body of the advice can be determined to not alter the stack, or if this shadow doesn't care about the stack, i.e.
- * method-execution, then the new method for the advice can also be re-lined. We are not doing that presently.
- */
- public void weaveAroundInline(BcelAdvice munger, boolean hasDynamicTest) {
- // !!! THIS BLOCK OF CODE SHOULD BE IN A METHOD CALLED weaveAround(...);
- Member mungerSig = munger.getSignature();
- // Member originalSig = mungerSig; // If mungerSig is on a parameterized type, originalSig is the member on the generic type
- if (mungerSig instanceof ResolvedMember) {
- ResolvedMember rm = (ResolvedMember) mungerSig;
- if (rm.hasBackingGenericMember()) {
- mungerSig = rm.getBackingGenericMember();
- }
- }
- ResolvedType declaringAspectType = world.resolve(mungerSig.getDeclaringType(), true);
- if (declaringAspectType.isMissing()) {
- world.getLint().cantFindType.signal(
- new String[] { WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_DURING_AROUND_WEAVE,
- declaringAspectType.getClassName()) }, getSourceLocation(),
- new ISourceLocation[] { munger.getSourceLocation() });
- }
-
- // ??? might want some checks here to give better errors
- ResolvedType rt = (declaringAspectType.isParameterizedType() ? declaringAspectType.getGenericType() : declaringAspectType);
- BcelObjectType ot = BcelWorld.getBcelObjectType(rt);
- LazyMethodGen adviceMethod = ot.getLazyClassGen().getLazyMethodGen(mungerSig);
- if (!adviceMethod.getCanInline()) {
- weaveAroundClosure(munger, hasDynamicTest);
- return;
- }
-
- // specific test for @AJ proceedInInners
- if (isAnnotationStylePassingProceedingJoinPointOutOfAdvice(munger, hasDynamicTest, adviceMethod)) {
- return;
- }
-
- // We can't inline around methods if they have around advice on them, this
- // is because the weaving will extract the body and hence the proceed call.
-
- // TODO should consider optimizations to recognize simple cases that don't require body extraction
-
- enclosingMethod.setCanInline(false);
-
- LazyClassGen shadowClass = getEnclosingClass();
-
- // Extract the shadow into a new method. For example:
- // "private static final void method_aroundBody0(M, M, String, org.aspectj.lang.JoinPoint)"
- // Parameters are: this if there is one, target if there is one and its different to this, then original arguments
- // at the shadow, then tjp
- String extractedShadowMethodName = NameMangler.aroundShadowMethodName(getSignature(), shadowClass.getNewGeneratedNameTag());
- List<String> parameterNames = new ArrayList<String>();
- boolean shadowClassIsInterface = shadowClass.isInterface();
- LazyMethodGen extractedShadowMethod = extractShadowInstructionsIntoNewMethod(extractedShadowMethodName,
- shadowClassIsInterface?Modifier.PUBLIC:Modifier.PRIVATE,
- munger.getSourceLocation(), parameterNames,shadowClassIsInterface);
-
- List<BcelVar> argsToCallLocalAdviceMethodWith = new ArrayList<BcelVar>();
- List<BcelVar> proceedVarList = new ArrayList<BcelVar>();
- int extraParamOffset = 0;
-
- // Create the extra parameters that are needed for passing to proceed
- // This code is very similar to that found in makeCallToCallback and should
- // be rationalized in the future
-
- if (thisVar != null) {
- argsToCallLocalAdviceMethodWith.add(thisVar);
- proceedVarList.add(new BcelVar(thisVar.getType(), extraParamOffset));
- extraParamOffset += thisVar.getType().getSize();
- }
-
- if (targetVar != null && targetVar != thisVar) {
- argsToCallLocalAdviceMethodWith.add(targetVar);
- proceedVarList.add(new BcelVar(targetVar.getType(), extraParamOffset));
- extraParamOffset += targetVar.getType().getSize();
- }
- for (int i = 0, len = getArgCount(); i < len; i++) {
- argsToCallLocalAdviceMethodWith.add(argVars[i]);
- proceedVarList.add(new BcelVar(argVars[i].getType(), extraParamOffset));
- extraParamOffset += argVars[i].getType().getSize();
- }
- if (thisJoinPointVar != null) {
- argsToCallLocalAdviceMethodWith.add(thisJoinPointVar);
- proceedVarList.add(new BcelVar(thisJoinPointVar.getType(), extraParamOffset));
- extraParamOffset += thisJoinPointVar.getType().getSize();
- }
-
- // 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());
-
- // 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
- adviceMethod.getArgumentTypes();
-
- Type[] extractedMethodParameterTypes = extractedShadowMethod.getArgumentTypes();
-
- Type[] parameterTypes = new Type[extractedMethodParameterTypes.length + adviceParameterTypes.length + 1];
- int parameterIndex = 0;
- System.arraycopy(extractedMethodParameterTypes, 0, parameterTypes, parameterIndex, extractedMethodParameterTypes.length);
- parameterIndex += extractedMethodParameterTypes.length;
- parameterTypes[parameterIndex++] = BcelWorld.makeBcelType(adviceMethod.getEnclosingClass().getType());
- System.arraycopy(adviceParameterTypes, 0, parameterTypes, parameterIndex, adviceParameterTypes.length);
-
- // Extract the advice into a new method. This will go in the same type as the shadow
- // name will be something like foo_aroundBody1$advice
- String localAdviceMethodName = NameMangler.aroundAdviceMethodName(getSignature(), shadowClass.getNewGeneratedNameTag());
- int localAdviceMethodModifiers = Modifier.PRIVATE | (world.useFinal() & !shadowClassIsInterface ? Modifier.FINAL : 0) | Modifier.STATIC;
- LazyMethodGen localAdviceMethod = new LazyMethodGen(localAdviceMethodModifiers, BcelWorld.makeBcelType(mungerSig.getReturnType()), localAdviceMethodName, parameterTypes,
- NoDeclaredExceptions, shadowClass);
-
- // Doesnt work properly, so leave it out:
- // String aspectFilename = adviceMethod.getEnclosingClass().getInternalFileName();
- // String shadowFilename = shadowClass.getInternalFileName();
- // if (!aspectFilename.equals(shadowFilename)) {
- // localAdviceMethod.fromFilename = aspectFilename;
- // shadowClass.addInlinedSourceFileInfo(aspectFilename, adviceMethod.highestLineNumber);
- // }
-
- shadowClass.addMethodGen(localAdviceMethod);
-
- // create a map that will move all slots in advice method forward by extraParamOffset
- // in order to make room for the new proceed-required arguments that are added at
- // the beginning of the parameter list
- int nVars = adviceMethod.getMaxLocals() + extraParamOffset;
- IntMap varMap = IntMap.idMap(nVars);
- for (int i = extraParamOffset; i < nVars; i++) {
- varMap.put(i - extraParamOffset, i);
- }
-
- final InstructionFactory fact = getFactory();
-
- localAdviceMethod.getBody().insert(
- BcelClassWeaver.genInlineInstructions(adviceMethod, localAdviceMethod, varMap, fact, true));
-
- localAdviceMethod.setMaxLocals(nVars);
-
- // the shadow is now empty. First, create a correct call
- // to the around advice. This includes both the call (which may involve
- // value conversion of the advice arguments) and the return
- // (which may involve value conversion of the return value). Right now
- // we push a null for the unused closure. It's sad, but there it is.
-
- InstructionList advice = new InstructionList();
- // InstructionHandle adviceMethodInvocation;
- {
- for (Iterator<BcelVar> i = argsToCallLocalAdviceMethodWith.iterator(); i.hasNext();) {
- BcelVar var = i.next();
- var.appendLoad(advice, fact);
- }
- // ??? we don't actually need to push NULL for the closure if we take care
- boolean isAnnoStyleConcreteAspect = munger.getConcreteAspect().isAnnotationStyleAspect();
- boolean isAnnoStyleDeclaringAspect = munger.getDeclaringAspect() != null ? munger.getDeclaringAspect().resolve(world)
- .isAnnotationStyleAspect() : false;
-
- InstructionList iList = null;
- if (isAnnoStyleConcreteAspect && isAnnoStyleDeclaringAspect) {
- iList = this.loadThisJoinPoint();
- iList.append(Utility.createConversion(getFactory(), LazyClassGen.tjpType, LazyClassGen.proceedingTjpType));
- } else {
- iList = new InstructionList(InstructionConstants.ACONST_NULL);
- }
- advice.append(munger.getAdviceArgSetup(this, null, iList));
- // adviceMethodInvocation =
- advice.append(Utility.createInvoke(fact, localAdviceMethod)); // (fact, getWorld(), munger.getSignature()));
- advice.append(Utility.createConversion(getFactory(), BcelWorld.makeBcelType(mungerSig.getReturnType()),
- extractedShadowMethod.getReturnType(), world.isInJava5Mode()));
- if (!isFallsThrough()) {
- advice.append(InstructionFactory.createReturn(extractedShadowMethod.getReturnType()));
- }
- }
-
- // now, situate the call inside the possible dynamic tests,
- // and actually add the whole mess to the shadow
- if (!hasDynamicTest) {
- range.append(advice);
- } else {
- InstructionList afterThingie = new InstructionList(InstructionConstants.NOP);
- InstructionList callback = makeCallToCallback(extractedShadowMethod);
- if (terminatesWithReturn()) {
- callback.append(InstructionFactory.createReturn(extractedShadowMethod.getReturnType()));
- } else {
- // InstructionHandle endNop = range.insert(fact.NOP, Range.InsideAfter);
- advice.append(InstructionFactory.createBranchInstruction(Constants.GOTO, afterThingie.getStart()));
- }
- range.append(munger.getTestInstructions(this, advice.getStart(), callback.getStart(), advice.getStart()));
- range.append(advice);
- range.append(callback);
- range.append(afterThingie);
- }
-
- // now search through the advice, looking for a call to PROCEED.
- // Then we replace the call to proceed with some argument setup, and a
- // call to the extracted method.
-
- // inlining support for code style aspects
- if (!munger.getDeclaringType().isAnnotationStyleAspect()) {
- String proceedName = NameMangler.proceedMethodName(munger.getSignature().getName());
-
- InstructionHandle curr = localAdviceMethod.getBody().getStart();
- InstructionHandle end = localAdviceMethod.getBody().getEnd();
- ConstantPool cpg = localAdviceMethod.getEnclosingClass().getConstantPool();
- while (curr != end) {
- InstructionHandle next = curr.getNext();
- Instruction inst = curr.getInstruction();
- if ((inst.opcode == Constants.INVOKESTATIC) && proceedName.equals(((InvokeInstruction) inst).getMethodName(cpg))) {
-
- localAdviceMethod.getBody().append(curr,
- getRedoneProceedCall(fact, extractedShadowMethod, munger, localAdviceMethod, proceedVarList));
- Utility.deleteInstruction(curr, localAdviceMethod);
- }
- curr = next;
- }
- // and that's it.
- } else {
- // ATAJ inlining support for @AJ aspects
- // [TODO document @AJ code rule: don't manipulate 2 jps proceed at the same time.. in an advice body]
- InstructionHandle curr = localAdviceMethod.getBody().getStart();
- InstructionHandle end = localAdviceMethod.getBody().getEnd();
- ConstantPool cpg = localAdviceMethod.getEnclosingClass().getConstantPool();
- while (curr != end) {
- InstructionHandle next = curr.getNext();
- Instruction inst = curr.getInstruction();
- if ((inst instanceof INVOKEINTERFACE) && "proceed".equals(((INVOKEINTERFACE) inst).getMethodName(cpg))) {
- final boolean isProceedWithArgs;
- if (((INVOKEINTERFACE) inst).getArgumentTypes(cpg).length == 1) {
- // proceed with args as a boxed Object[]
- isProceedWithArgs = true;
- } else {
- isProceedWithArgs = false;
- }
- InstructionList insteadProceedIl = getRedoneProceedCallForAnnotationStyle(fact, extractedShadowMethod, munger,
- localAdviceMethod, proceedVarList, isProceedWithArgs);
- localAdviceMethod.getBody().append(curr, insteadProceedIl);
- Utility.deleteInstruction(curr, localAdviceMethod);
- }
- curr = next;
- }
- }
-
- // if (parameterNames.size() == 0) {
- // On return we have inserted the advice body into the local advice method. We have remapped all the local variables
- // that were referenced in the advice as we did the copy, and so the local variable table for localAdviceMethod is
- // now lacking any information about all the initial variables.
- InstructionHandle start = localAdviceMethod.getBody().getStart();
- InstructionHandle end = localAdviceMethod.getBody().getEnd();
-
- // Find the real start and end
- while (start.getInstruction().opcode == Constants.IMPDEP1) {
- start = start.getNext();
- }
- while (end.getInstruction().opcode == Constants.IMPDEP1) {
- end = end.getPrev();
- }
- Type[] args = localAdviceMethod.getArgumentTypes();
- int argNumber = 0;
- for (int slot = 0; slot < extraParamOffset; argNumber++) { // slot will increase by the argument size each time
- String argumentName = null;
- if (argNumber >= args.length || parameterNames.size() == 0 || argNumber >= parameterNames.size()) {
- // this should be unnecessary as I think all known joinpoints and helper methods
- // propagate the parameter names around correctly - but just in case let us do this
- // rather than fail. If a bug is raised reporting unknown as a local variable name
- // then investigate the joinpoint giving rise to the ResolvedMember and why it has
- // no parameter names specified
- argumentName = new StringBuffer("unknown").append(argNumber).toString();
- } else {
- argumentName = parameterNames.get(argNumber);
- }
- String argumentSignature = args[argNumber].getSignature();
- LocalVariableTag lvt = new LocalVariableTag(argumentSignature, argumentName, slot, 0);
- start.addTargeter(lvt);
- end.addTargeter(lvt);
- slot += args[argNumber].getSize();
- }
- }
-
- /**
- * Check if the advice method passes a pjp parameter out via an invoke instruction - if so we can't risk inlining.
- */
- private boolean isAnnotationStylePassingProceedingJoinPointOutOfAdvice(BcelAdvice munger, boolean hasDynamicTest,
- LazyMethodGen adviceMethod) {
- if (munger.getConcreteAspect().isAnnotationStyleAspect()) {
- // if we can't find one proceed() we suspect that the call
- // is happening in an inner class so we don't inline it.
- // Note: for code style, this is done at Aspect compilation time.
- boolean canSeeProceedPassedToOther = false;
- InstructionHandle curr = adviceMethod.getBody().getStart();
- InstructionHandle end = adviceMethod.getBody().getEnd();
- ConstantPool cpg = adviceMethod.getEnclosingClass().getConstantPool();
- while (curr != end) {
- InstructionHandle next = curr.getNext();
- Instruction inst = curr.getInstruction();
- if ((inst instanceof InvokeInstruction)
- && ((InvokeInstruction) inst).getSignature(cpg).indexOf("Lorg/aspectj/lang/ProceedingJoinPoint;") > 0) {
- // we may want to refine to exclude stuff returning jp ?
- // does code style skip inline if i write dump(thisJoinPoint) ?
- canSeeProceedPassedToOther = true;// we see one pjp passed around - dangerous
- break;
- }
- curr = next;
- }
- if (canSeeProceedPassedToOther) {
- // remember this decision to avoid re-analysis
- adviceMethod.setCanInline(false);
- weaveAroundClosure(munger, hasDynamicTest);
- return true;
- }
- }
- return false;
- }
-
- private InstructionList getRedoneProceedCall(InstructionFactory fact, LazyMethodGen callbackMethod, BcelAdvice munger,
- LazyMethodGen localAdviceMethod, List<BcelVar> argVarList) {
- InstructionList ret = new InstructionList();
- // we have on stack all the arguments for the ADVICE call.
- // we have in frame somewhere all the arguments for the non-advice call.
-
- BcelVar[] adviceVars = munger.getExposedStateAsBcelVars(true);
- IntMap proceedMap = makeProceedArgumentMap(adviceVars);
-
- // System.out.println(proceedMap + " for " + this);
- // System.out.println(argVarList);
-
- ResolvedType[] proceedParamTypes = world.resolve(munger.getSignature().getParameterTypes());
- // remove this*JoinPoint* as arguments to proceed
- if (munger.getBaseParameterCount() + 1 < proceedParamTypes.length) {
- int len = munger.getBaseParameterCount() + 1;
- ResolvedType[] newTypes = new ResolvedType[len];
- System.arraycopy(proceedParamTypes, 0, newTypes, 0, len);
- proceedParamTypes = newTypes;
- }
-
- // System.out.println("stateTypes: " + Arrays.asList(stateTypes));
- BcelVar[] proceedVars = Utility.pushAndReturnArrayOfVars(proceedParamTypes, ret, fact, localAdviceMethod);
-
- Type[] stateTypes = callbackMethod.getArgumentTypes();
- // System.out.println("stateTypes: " + Arrays.asList(stateTypes));
-
- for (int i = 0, len = stateTypes.length; i < len; i++) {
- Type stateType = stateTypes[i];
- ResolvedType stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
- if (proceedMap.hasKey(i)) {
- // throw new RuntimeException("unimplemented");
- proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX);
- } else {
- argVarList.get(i).appendLoad(ret, fact);
- }
- }
-
- ret.append(Utility.createInvoke(fact, callbackMethod));
- ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(),
- BcelWorld.makeBcelType(munger.getSignature().getReturnType()), world.isInJava5Mode()));
- return ret;
- }
-
- // private static boolean bindsThisOrTarget(Pointcut pointcut) {
- // ThisTargetFinder visitor = new ThisTargetFinder();
- // pointcut.accept(visitor, null);
- // return visitor.bindsThisOrTarget;
- // }
-
- // private static class ThisTargetFinder extends IdentityPointcutVisitor {
- // boolean bindsThisOrTarget = false;
- //
- // public Object visit(ThisOrTargetPointcut node, Object data) {
- // if (node.isBinding()) {
- // bindsThisOrTarget = true;
- // }
- // return node;
- // }
- //
- // public Object visit(AndPointcut node, Object data) {
- // if (!bindsThisOrTarget) node.getLeft().accept(this, data);
- // if (!bindsThisOrTarget) node.getRight().accept(this, data);
- // return node;
- // }
- //
- // public Object visit(NotPointcut node, Object data) {
- // if (!bindsThisOrTarget) node.getNegatedPointcut().accept(this, data);
- // return node;
- // }
- //
- // public Object visit(OrPointcut node, Object data) {
- // if (!bindsThisOrTarget) node.getLeft().accept(this, data);
- // if (!bindsThisOrTarget) node.getRight().accept(this, data);
- // return node;
- // }
- // }
-
- /**
- * Annotation style handling for inlining.
- *
- * Note: The proceedingjoinpoint is already on the stack (since the user was calling pjp.proceed(...)
- *
- * The proceed map is ignored (in terms of argument repositioning) since we have a fixed expected format for annotation style.
- * The aim here is to change the proceed() call into a call to the xxx_aroundBody0 method.
- *
- *
- */
- private InstructionList getRedoneProceedCallForAnnotationStyle(InstructionFactory fact, LazyMethodGen callbackMethod,
- BcelAdvice munger, LazyMethodGen localAdviceMethod, List<BcelVar> argVarList, boolean isProceedWithArgs) {
- InstructionList ret = new InstructionList();
-
- // store the Object[] array on stack if proceed with args
- if (isProceedWithArgs) {
-
- // STORE the Object[] into a local variable
- Type objectArrayType = Type.OBJECT_ARRAY;
- int theObjectArrayLocalNumber = localAdviceMethod.allocateLocal(objectArrayType);
- ret.append(InstructionFactory.createStore(objectArrayType, theObjectArrayLocalNumber));
-
- // STORE the ProceedingJoinPoint instance into a local variable
- Type proceedingJpType = Type.getType("Lorg/aspectj/lang/ProceedingJoinPoint;");
- int pjpLocalNumber = localAdviceMethod.allocateLocal(proceedingJpType);
- ret.append(InstructionFactory.createStore(proceedingJpType, pjpLocalNumber));
-
- // Aim here initially is to determine whether the user will have provided a new
- // this/target in the object array and consume them if they have, leaving us the rest of
- // the arguments to process as regular arguments to the invocation at the original join point
-
- boolean pointcutBindsThis = bindsThis(munger);
- boolean pointcutBindsTarget = bindsTarget(munger);
- boolean targetIsSameAsThis = getKind().isTargetSameAsThis();
-
- int nextArgumentToProvideForCallback = 0;
-
- if (hasThis()) {
- if (!(pointcutBindsTarget && targetIsSameAsThis)) {
- if (pointcutBindsThis) {
- // they have supplied new this as first entry in object array, consume it
- ret.append(InstructionFactory.createLoad(objectArrayType, theObjectArrayLocalNumber));
- ret.append(Utility.createConstant(fact, 0));
- ret.append(InstructionFactory.createArrayLoad(Type.OBJECT));
- ret.append(Utility.createConversion(fact, Type.OBJECT, callbackMethod.getArgumentTypes()[0]));
- } else {
- // use local variable 0
- ret.append(InstructionFactory.createALOAD(0));
- }
- nextArgumentToProvideForCallback++;
- }
- }
-
- if (hasTarget()) {
- if (pointcutBindsTarget) {
- if (getKind().isTargetSameAsThis()) {
- ret.append(InstructionFactory.createLoad(objectArrayType, theObjectArrayLocalNumber));
- ret.append(Utility.createConstant(fact, pointcutBindsThis ? 1 : 0));
- ret.append(InstructionFactory.createArrayLoad(Type.OBJECT));
- ret.append(Utility.createConversion(fact, Type.OBJECT, callbackMethod.getArgumentTypes()[0]));
- } else {
- int position = (hasThis() && pointcutBindsThis)? 1 : 0;
- ret.append(InstructionFactory.createLoad(objectArrayType, theObjectArrayLocalNumber));
- ret.append(Utility.createConstant(fact, position));
- ret.append(InstructionFactory.createArrayLoad(Type.OBJECT));
- ret.append(Utility.createConversion(fact, Type.OBJECT, callbackMethod.getArgumentTypes()[nextArgumentToProvideForCallback]));
- }
- nextArgumentToProvideForCallback++;
- } else {
- if (getKind().isTargetSameAsThis()) {
- // ret.append(new ALOAD(0));
- } else {
- ret.append(InstructionFactory.createLoad(localAdviceMethod.getArgumentTypes()[0], hasThis() ? 1 : 0));
- nextArgumentToProvideForCallback++;
- }
- }
- }
-
- // Where to start in the object array in order to pick up arguments
- int indexIntoObjectArrayForArguments = (pointcutBindsThis ? 1 : 0) + (pointcutBindsTarget ? 1 : 0);
-
- int len = callbackMethod.getArgumentTypes().length;
- for (int i = nextArgumentToProvideForCallback; i < len; i++) {
- Type stateType = callbackMethod.getArgumentTypes()[i];
- BcelWorld.fromBcel(stateType).resolve(world);
- if ("Lorg/aspectj/lang/JoinPoint;".equals(stateType.getSignature())) {
- ret.append(new InstructionLV(Constants.ALOAD, pjpLocalNumber));
- } else {
- ret.append(InstructionFactory.createLoad(objectArrayType, theObjectArrayLocalNumber));
- ret.append(Utility
- .createConstant(fact, i - nextArgumentToProvideForCallback + indexIntoObjectArrayForArguments));
- ret.append(InstructionFactory.createArrayLoad(Type.OBJECT));
- ret.append(Utility.createConversion(fact, Type.OBJECT, stateType));
- }
- }
-
- } else {
- Type proceedingJpType = Type.getType("Lorg/aspectj/lang/ProceedingJoinPoint;");
- int localJp = localAdviceMethod.allocateLocal(proceedingJpType);
- ret.append(InstructionFactory.createStore(proceedingJpType, localJp));
-
- int idx = 0;
- for (int i = 0, len = callbackMethod.getArgumentTypes().length; i < len; i++) {
- Type stateType = callbackMethod.getArgumentTypes()[i];
- /* ResolvedType stateTypeX = */
- BcelWorld.fromBcel(stateType).resolve(world);
- if ("Lorg/aspectj/lang/JoinPoint;".equals(stateType.getSignature())) {
- ret.append(InstructionFactory.createALOAD(localJp));// from localAdvice signature
- // } else if ("Lorg/aspectj/lang/ProceedingJoinPoint;".equals(stateType.getSignature())) {
- // //FIXME ALEX?
- // ret.append(new ALOAD(localJp));// from localAdvice signature
- // // ret.append(fact.createCheckCast(
- // // (ReferenceType) BcelWorld.makeBcelType(stateTypeX)
- // // ));
- // // cast ?
- //
- idx++;
- } else {
- ret.append(InstructionFactory.createLoad(stateType, idx));
- idx += stateType.getSize();
- }
- }
- }
-
- // do the callback invoke
- ret.append(Utility.createInvoke(fact, callbackMethod));
-
- // box it again. Handles cases where around advice does return something else than Object
- if (!UnresolvedType.OBJECT.equals(munger.getSignature().getReturnType())) {
- ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(), Type.OBJECT));
- }
- ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(),
- BcelWorld.makeBcelType(munger.getSignature().getReturnType()), world.isInJava5Mode()));
-
- return ret;
-
- //
- //
- //
- // if (proceedMap.hasKey(i)) {
- // ret.append(new ALOAD(i));
- // //throw new RuntimeException("unimplemented");
- // //proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX);
- // } else {
- // //((BcelVar) argVarList.get(i)).appendLoad(ret, fact);
- // //ret.append(new ALOAD(i));
- // if ("Lorg/aspectj/lang/JoinPoint;".equals(stateType.getSignature())) {
- // ret.append(new ALOAD(i));
- // } else {
- // ret.append(new ALOAD(i));
- // }
- // }
- // }
- //
- // ret.append(Utility.createInvoke(fact, callbackMethod));
- // ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(),
- // BcelWorld.makeBcelType(munger.getSignature().getReturnType())));
- //
- // //ret.append(new ACONST_NULL());//will be POPed
- // if (true) return ret;
- //
- //
- //
- // // we have on stack all the arguments for the ADVICE call.
- // // we have in frame somewhere all the arguments for the non-advice call.
- //
- // BcelVar[] adviceVars = munger.getExposedStateAsBcelVars();
- // IntMap proceedMap = makeProceedArgumentMap(adviceVars);
- //
- // System.out.println(proceedMap + " for " + this);
- // System.out.println(argVarList);
- //
- // ResolvedType[] proceedParamTypes =
- // world.resolve(munger.getSignature().getParameterTypes());
- // // remove this*JoinPoint* as arguments to proceed
- // if (munger.getBaseParameterCount()+1 < proceedParamTypes.length) {
- // int len = munger.getBaseParameterCount()+1;
- // ResolvedType[] newTypes = new ResolvedType[len];
- // System.arraycopy(proceedParamTypes, 0, newTypes, 0, len);
- // proceedParamTypes = newTypes;
- // }
- //
- // //System.out.println("stateTypes: " + Arrays.asList(stateTypes));
- // BcelVar[] proceedVars =
- // Utility.pushAndReturnArrayOfVars(proceedParamTypes, ret, fact, localAdviceMethod);
- //
- // Type[] stateTypes = callbackMethod.getArgumentTypes();
- // // System.out.println("stateTypes: " + Arrays.asList(stateTypes));
- //
- // for (int i=0, len=stateTypes.length; i < len; i++) {
- // Type stateType = stateTypes[i];
- // ResolvedType stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
- // if (proceedMap.hasKey(i)) {
- // //throw new RuntimeException("unimplemented");
- // proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX);
- // } else {
- // ((BcelVar) argVarList.get(i)).appendLoad(ret, fact);
- // }
- // }
- //
- // ret.append(Utility.createInvoke(fact, callbackMethod));
- // ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(),
- // BcelWorld.makeBcelType(munger.getSignature().getReturnType())));
- // return ret;
- }
-
- private boolean bindsThis(BcelAdvice munger) {
- UsesThisVisitor utv = new UsesThisVisitor();
- munger.getPointcut().accept(utv, null);
- return utv.usesThis;
- }
-
- private boolean bindsTarget(BcelAdvice munger) {
- UsesTargetVisitor utv = new UsesTargetVisitor();
- munger.getPointcut().accept(utv, null);
- return utv.usesTarget;
- }
-
- private static class UsesThisVisitor extends AbstractPatternNodeVisitor {
- boolean usesThis = false;
-
- @Override
- public Object visit(ThisOrTargetPointcut node, Object data) {
- if (node.isThis() && node.isBinding()) {
- usesThis = true;
- }
- return node;
- }
-
- @Override
- public Object visit(AndPointcut node, Object data) {
- if (!usesThis) {
- node.getLeft().accept(this, data);
- }
- if (!usesThis) {
- node.getRight().accept(this, data);
- }
- return node;
- }
-
- @Override
- public Object visit(NotPointcut node, Object data) {
- if (!usesThis) {
- node.getNegatedPointcut().accept(this, data);
- }
- return node;
- }
-
- @Override
- public Object visit(OrPointcut node, Object data) {
- if (!usesThis) {
- node.getLeft().accept(this, data);
- }
- if (!usesThis) {
- node.getRight().accept(this, data);
- }
- return node;
- }
- }
-
- private static class UsesTargetVisitor extends AbstractPatternNodeVisitor {
- boolean usesTarget = false;
-
- @Override
- public Object visit(ThisOrTargetPointcut node, Object data) {
- if (!node.isThis() && node.isBinding()) {
- usesTarget = true;
- }
- return node;
- }
-
- @Override
- public Object visit(AndPointcut node, Object data) {
- if (!usesTarget) {
- node.getLeft().accept(this, data);
- }
- if (!usesTarget) {
- node.getRight().accept(this, data);
- }
- return node;
- }
-
- @Override
- public Object visit(NotPointcut node, Object data) {
- if (!usesTarget) {
- node.getNegatedPointcut().accept(this, data);
- }
- return node;
- }
-
- @Override
- public Object visit(OrPointcut node, Object data) {
- if (!usesTarget) {
- node.getLeft().accept(this, data);
- }
- if (!usesTarget) {
- node.getRight().accept(this, data);
- }
- return node;
- }
- }
-
- public void weaveAroundClosure(BcelAdvice munger, boolean hasDynamicTest) {
- InstructionFactory fact = getFactory();
-
- enclosingMethod.setCanInline(false);
-
- int linenumber = getSourceLine();
- // MOVE OUT ALL THE INSTRUCTIONS IN MY SHADOW INTO ANOTHER METHOD!
-
- // callbackMethod will be something like: "static final void m_aroundBody0(I)"
- boolean shadowClassIsInterface = getEnclosingClass().isInterface();
- LazyMethodGen callbackMethod = extractShadowInstructionsIntoNewMethod(
- NameMangler.aroundShadowMethodName(getSignature(), getEnclosingClass().getNewGeneratedNameTag()), shadowClassIsInterface?Modifier.PUBLIC:0,
- munger.getSourceLocation(), new ArrayList<String>(),shadowClassIsInterface);
-
- BcelVar[] adviceVars = munger.getExposedStateAsBcelVars(true);
-
- String closureClassName = NameMangler.makeClosureClassName(getEnclosingClass().getType(), getEnclosingClass()
- .getNewGeneratedNameTag());
-
- Member constructorSig = new MemberImpl(Member.CONSTRUCTOR, UnresolvedType.forName(closureClassName), 0, "<init>",
- "([Ljava/lang/Object;)V");
-
- BcelVar closureHolder = null;
-
- // This is not being used currently since getKind() == preinitializaiton
- // cannot happen in around advice
- if (getKind() == PreInitialization) {
- closureHolder = genTempVar(AjcMemberMaker.AROUND_CLOSURE_TYPE);
- }
-
- InstructionList closureInstantiation = makeClosureInstantiation(constructorSig, closureHolder);
-
- /* LazyMethodGen constructor = */
- makeClosureClassAndReturnConstructor(closureClassName, callbackMethod, makeProceedArgumentMap(adviceVars));
-
- InstructionList returnConversionCode;
- if (getKind() == PreInitialization) {
- returnConversionCode = new InstructionList();
-
- BcelVar stateTempVar = genTempVar(UnresolvedType.OBJECTARRAY);
- closureHolder.appendLoad(returnConversionCode, fact);
-
- returnConversionCode.append(Utility.createInvoke(fact, world, AjcMemberMaker.aroundClosurePreInitializationGetter()));
- stateTempVar.appendStore(returnConversionCode, fact);
-
- Type[] stateTypes = getSuperConstructorParameterTypes();
-
- returnConversionCode.append(InstructionConstants.ALOAD_0); // put "this" back on the stack
- for (int i = 0, len = stateTypes.length; i < len; i++) {
- UnresolvedType bcelTX = BcelWorld.fromBcel(stateTypes[i]);
- ResolvedType stateRTX = world.resolve(bcelTX, true);
- if (stateRTX.isMissing()) {
- world.getLint().cantFindType.signal(
- new String[] { WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_DURING_AROUND_WEAVE_PREINIT,
- bcelTX.getClassName()) }, getSourceLocation(),
- new ISourceLocation[] { munger.getSourceLocation() });
- // IMessage msg = new Message(
- // WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_DURING_AROUND_WEAVE_PREINIT,bcelTX.getClassName()),
- // "",IMessage.ERROR,getSourceLocation(),null,
- // new ISourceLocation[]{ munger.getSourceLocation()});
- // world.getMessageHandler().handleMessage(msg);
- }
- stateTempVar.appendConvertableArrayLoad(returnConversionCode, fact, i, stateRTX);
- }
- } else {
- // pr226201
- Member mungerSignature = munger.getSignature();
- if (munger.getSignature() instanceof ResolvedMember) {
- if (((ResolvedMember) mungerSignature).hasBackingGenericMember()) {
- mungerSignature = ((ResolvedMember) mungerSignature).getBackingGenericMember();
- }
- }
- UnresolvedType returnType = mungerSignature.getReturnType();
- returnConversionCode = Utility.createConversion(getFactory(), BcelWorld.makeBcelType(returnType),
- callbackMethod.getReturnType(), world.isInJava5Mode());
- if (!isFallsThrough()) {
- returnConversionCode.append(InstructionFactory.createReturn(callbackMethod.getReturnType()));
- }
- }
-
- // initialize the bit flags for this shadow
- int bitflags = 0x000000;
- if (getKind().isTargetSameAsThis()) {
- bitflags |= 0x010000;
- }
- if (hasThis()) {
- bitflags |= 0x001000;
- }
- if (bindsThis(munger)) {
- bitflags |= 0x000100;
- }
- if (hasTarget()) {
- bitflags |= 0x000010;
- }
- if (bindsTarget(munger)) {
- bitflags |= 0x000001;
- }
-
- // ATAJ for @AJ aspect we need to link the closure with the joinpoint instance
- 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(Integer.valueOf(bitflags)));
- closureInstantiation.append(Utility.createInvoke(getFactory(), getWorld(),
- new MemberImpl(Member.METHOD, UnresolvedType.forName("org.aspectj.runtime.internal.AroundClosure"),
- Modifier.PUBLIC, "linkClosureAndJoinPoint", String.format("%s%s", "(I)", "Lorg/aspectj/lang/ProceedingJoinPoint;"))));
- }
-
- InstructionList advice = new InstructionList();
- advice.append(munger.getAdviceArgSetup(this, null, closureInstantiation));
-
- // invoke the advice
- advice.append(munger.getNonTestAdviceInstructions(this));
- advice.append(returnConversionCode);
- if (getKind() == Shadow.MethodExecution && linenumber > 0) {
- advice.getStart().addTargeter(new LineNumberTag(linenumber));
- }
-
- if (!hasDynamicTest) {
- range.append(advice);
- } else {
- InstructionList callback = makeCallToCallback(callbackMethod);
- InstructionList postCallback = new InstructionList();
- if (terminatesWithReturn()) {
- callback.append(InstructionFactory.createReturn(callbackMethod.getReturnType()));
- } else {
- advice.append(InstructionFactory.createBranchInstruction(Constants.GOTO,
- postCallback.append(InstructionConstants.NOP)));
- }
- range.append(munger.getTestInstructions(this, advice.getStart(), callback.getStart(), advice.getStart()));
- range.append(advice);
- range.append(callback);
- range.append(postCallback);
- }
- }
-
- // exposed for testing
- InstructionList makeCallToCallback(LazyMethodGen callbackMethod) {
- InstructionFactory fact = getFactory();
- InstructionList callback = new InstructionList();
- if (thisVar != null) {
- callback.append(InstructionConstants.ALOAD_0);
- }
- if (targetVar != null && targetVar != thisVar) {
- callback.append(BcelRenderer.renderExpr(fact, world, targetVar));
- }
- callback.append(BcelRenderer.renderExprs(fact, world, argVars));
- // remember to render tjps
- if (thisJoinPointVar != null) {
- callback.append(BcelRenderer.renderExpr(fact, world, thisJoinPointVar));
- }
- callback.append(Utility.createInvoke(fact, callbackMethod));
- return callback;
- }
-
- /** side-effect-free */
- private InstructionList makeClosureInstantiation(Member constructor, BcelVar holder) {
-
- // LazyMethodGen constructor) {
- InstructionFactory fact = getFactory();
- BcelVar arrayVar = genTempVar(UnresolvedType.OBJECTARRAY);
- // final Type objectArrayType = new ArrayType(Type.OBJECT, 1);
- final InstructionList il = new InstructionList();
- int alen = getArgCount() + (thisVar == null ? 0 : 1) + ((targetVar != null && targetVar != thisVar) ? 1 : 0)
- + (thisJoinPointVar == null ? 0 : 1);
- il.append(Utility.createConstant(fact, alen));
- il.append(fact.createNewArray(Type.OBJECT, (short) 1));
- arrayVar.appendStore(il, fact);
-
- int stateIndex = 0;
- if (thisVar != null) {
- arrayVar.appendConvertableArrayStore(il, fact, stateIndex, thisVar);
- thisVar.setPositionInAroundState(stateIndex);
- stateIndex++;
- }
- if (targetVar != null && targetVar != thisVar) {
- arrayVar.appendConvertableArrayStore(il, fact, stateIndex, targetVar);
- targetVar.setPositionInAroundState(stateIndex);
- stateIndex++;
- }
- for (int i = 0, len = getArgCount(); i < len; i++) {
- arrayVar.appendConvertableArrayStore(il, fact, stateIndex, argVars[i]);
- argVars[i].setPositionInAroundState(stateIndex);
- stateIndex++;
- }
- if (thisJoinPointVar != null) {
- arrayVar.appendConvertableArrayStore(il, fact, stateIndex, thisJoinPointVar);
- thisJoinPointVar.setPositionInAroundState(stateIndex);
- stateIndex++;
- }
- il.append(fact.createNew(new ObjectType(constructor.getDeclaringType().getName())));
- il.append(InstructionConstants.DUP);
- arrayVar.appendLoad(il, fact);
- il.append(Utility.createInvoke(fact, world, constructor));
- if (getKind() == PreInitialization) {
- il.append(InstructionConstants.DUP);
- holder.appendStore(il, fact);
- }
- return il;
- }
-
- private IntMap makeProceedArgumentMap(BcelVar[] adviceArgs) {
- // System.err.println("coming in with " + Arrays.asList(adviceArgs));
-
- IntMap ret = new IntMap();
- for (int i = 0, len = adviceArgs.length; i < len; i++) {
- BcelVar v = adviceArgs[i];
- if (v == null) {
- continue; // XXX we don't know why this is required
- }
- int pos = v.getPositionInAroundState();
- if (pos >= 0) { // need this test to avoid args bound via cflow
- ret.put(pos, i);
- }
- }
- // System.err.println("returning " + ret);
-
- return ret;
- }
-
- /**
- *
- * @param callbackMethod the method we will call back to when our run method gets called.
- * @param proceedMap A map from state position to proceed argument position. May be non covering on state position.
- */
- private LazyMethodGen makeClosureClassAndReturnConstructor(String closureClassName, LazyMethodGen callbackMethod,
- IntMap proceedMap) {
- String superClassName = "org.aspectj.runtime.internal.AroundClosure";
- Type objectArrayType = new ArrayType(Type.OBJECT, 1);
-
- LazyClassGen closureClass = new LazyClassGen(closureClassName, superClassName, getEnclosingClass().getFileName(),
- Modifier.PUBLIC, new String[] {}, getWorld());
- closureClass.setMajorMinor(getEnclosingClass().getMajor(), getEnclosingClass().getMinor());
- InstructionFactory fact = new InstructionFactory(closureClass.getConstantPool());
-
- // constructor
- LazyMethodGen constructor = new LazyMethodGen(Modifier.PUBLIC, Type.VOID, "<init>", new Type[] { objectArrayType },
- new String[] {}, closureClass);
- InstructionList cbody = constructor.getBody();
- cbody.append(InstructionFactory.createLoad(Type.OBJECT, 0));
- cbody.append(InstructionFactory.createLoad(objectArrayType, 1));
- cbody.append(fact
- .createInvoke(superClassName, "<init>", Type.VOID, new Type[] { objectArrayType }, Constants.INVOKESPECIAL));
- cbody.append(InstructionFactory.createReturn(Type.VOID));
-
- closureClass.addMethodGen(constructor);
-
- // Create the 'Object run(Object[])' method
- LazyMethodGen runMethod = new LazyMethodGen(Modifier.PUBLIC, Type.OBJECT, "run", new Type[] { objectArrayType },
- new String[] {}, closureClass);
- InstructionList mbody = runMethod.getBody();
- BcelVar proceedVar = new BcelVar(UnresolvedType.OBJECTARRAY.resolve(world), 1);
- // int proceedVarIndex = 1;
- BcelVar stateVar = new BcelVar(UnresolvedType.OBJECTARRAY.resolve(world), runMethod.allocateLocal(1));
- // int stateVarIndex = runMethod.allocateLocal(1);
- mbody.append(InstructionFactory.createThis());
- mbody.append(fact.createGetField(superClassName, "state", objectArrayType));
- mbody.append(stateVar.createStore(fact));
- // mbody.append(fact.createStore(objectArrayType, stateVarIndex));
-
- Type[] stateTypes = callbackMethod.getArgumentTypes();
-
- for (int i = 0, len = stateTypes.length; i < len; i++) {
- ResolvedType resolvedStateType = BcelWorld.fromBcel(stateTypes[i]).resolve(world);
- if (proceedMap.hasKey(i)) {
- mbody.append(proceedVar.createConvertableArrayLoad(fact, proceedMap.get(i), resolvedStateType));
- } else {
- mbody.append(stateVar.createConvertableArrayLoad(fact, i, resolvedStateType));
- }
- }
-
- mbody.append(Utility.createInvoke(fact, callbackMethod));
-
- if (getKind() == PreInitialization) {
- mbody.append(Utility.createSet(fact, AjcMemberMaker.aroundClosurePreInitializationField()));
- mbody.append(InstructionConstants.ACONST_NULL);
- } else {
- mbody.append(Utility.createConversion(fact, callbackMethod.getReturnType(), Type.OBJECT));
- }
- mbody.append(InstructionFactory.createReturn(Type.OBJECT));
-
- closureClass.addMethodGen(runMethod);
-
- // class
- getEnclosingClass().addGeneratedInner(closureClass);
-
- return constructor;
- }
-
- // ---- extraction methods
-
- /**
- * Extract the instructions in the shadow to a new method.
- *
- * @param extractedMethodName name for the new method
- * @param extractedMethodVisibilityModifier visibility modifiers for the new method
- * @param adviceSourceLocation source location of the advice affecting the shadow
- * @param beingPlacedInInterface is this new method going into an interface
- */
- LazyMethodGen extractShadowInstructionsIntoNewMethod(String extractedMethodName, int extractedMethodVisibilityModifier,
- ISourceLocation adviceSourceLocation, List<String> parameterNames, boolean beingPlacedInInterface) {
- // LazyMethodGen.assertGoodBody(range.getBody(), extractedMethodName);
- if (!getKind().allowsExtraction()) {
- throw new BCException("Attempt to extract method from a shadow kind (" + getKind()
- + ") that does not support this operation");
- }
- LazyMethodGen newMethod = createShadowMethodGen(extractedMethodName, extractedMethodVisibilityModifier, parameterNames, beingPlacedInInterface);
- IntMap remapper = makeRemap();
- range.extractInstructionsInto(newMethod, remapper, (getKind() != PreInitialization) && isFallsThrough());
- if (getKind() == PreInitialization) {
- addPreInitializationReturnCode(newMethod, getSuperConstructorParameterTypes());
- }
- getEnclosingClass().addMethodGen(newMethod, adviceSourceLocation);
- return newMethod;
- }
-
- private void addPreInitializationReturnCode(LazyMethodGen extractedMethod, Type[] superConstructorTypes) {
- InstructionList body = extractedMethod.getBody();
- final InstructionFactory fact = getFactory();
-
- BcelVar arrayVar = new BcelVar(world.getCoreType(UnresolvedType.OBJECTARRAY), extractedMethod.allocateLocal(1));
-
- int len = superConstructorTypes.length;
-
- body.append(Utility.createConstant(fact, len));
-
- body.append(fact.createNewArray(Type.OBJECT, (short) 1));
- arrayVar.appendStore(body, fact);
-
- for (int i = len - 1; i >= 0; i++) {
- // convert thing on top of stack to object
- body.append(Utility.createConversion(fact, superConstructorTypes[i], Type.OBJECT));
- // push object array
- arrayVar.appendLoad(body, fact);
- // swap
- body.append(InstructionConstants.SWAP);
- // do object array store.
- body.append(Utility.createConstant(fact, i));
- body.append(InstructionConstants.SWAP);
- body.append(InstructionFactory.createArrayStore(Type.OBJECT));
- }
- arrayVar.appendLoad(body, fact);
- body.append(InstructionConstants.ARETURN);
- }
-
- private Type[] getSuperConstructorParameterTypes() {
- // assert getKind() == PreInitialization
- InstructionHandle superCallHandle = getRange().getEnd().getNext();
- InvokeInstruction superCallInstruction = (InvokeInstruction) superCallHandle.getInstruction();
- return superCallInstruction.getArgumentTypes(getEnclosingClass().getConstantPool());
- }
-
- /**
- * make a map from old frame location to new frame location. Any unkeyed frame location picks out a copied local
- */
- private IntMap makeRemap() {
- IntMap ret = new IntMap(5);
- int reti = 0;
- if (thisVar != null) {
- ret.put(0, reti++); // thisVar guaranteed to be 0
- }
- if (targetVar != null && targetVar != thisVar) {
- ret.put(targetVar.getSlot(), reti++);
- }
- for (int i = 0, len = argVars.length; i < len; i++) {
- ret.put(argVars[i].getSlot(), reti);
- reti += argVars[i].getType().getSize();
- }
- if (thisJoinPointVar != null) {
- ret.put(thisJoinPointVar.getSlot(), reti++);
- }
- // we not only need to put the arguments, we also need to remap their
- // aliases, which we so helpfully put into temps at the beginning of this join
- // point.
- if (!getKind().argsOnStack()) {
- int oldi = 0;
- int newi = 0;
- // if we're passing in a this and we're not argsOnStack we're always
- // passing in a target too
- if (arg0HoldsThis()) {
- ret.put(0, 0);
- oldi++;
- newi += 1;
- }
- // assert targetVar == thisVar
- for (int i = 0; i < getArgCount(); i++) {
- UnresolvedType type = getArgType(i);
- ret.put(oldi, newi);
- oldi += type.getSize();
- newi += type.getSize();
- }
- }
-
- // System.err.println("making remap for : " + this);
- // if (targetVar != null) System.err.println("target slot : " + targetVar.getSlot());
- // if (thisVar != null) System.err.println(" this slot : " + thisVar.getSlot());
- // System.err.println(ret);
-
- return ret;
- }
-
- /**
- * The new method always static. It may take some extra arguments: this, target. If it's argsOnStack, then it must take both
- * this/target If it's argsOnFrame, it shares this and target. ??? rewrite this to do less array munging, please
- */
- private LazyMethodGen createShadowMethodGen(String newMethodName, int visibilityModifier, List<String> parameterNames, boolean beingPlacedInInterface) {
- Type[] shadowParameterTypes = BcelWorld.makeBcelTypes(getArgTypes());
- int modifiers = (world.useFinal() && !beingPlacedInInterface ? Modifier.FINAL : 0) | Modifier.STATIC | visibilityModifier;
- if (targetVar != null && targetVar != thisVar) {
- UnresolvedType targetType = getTargetType();
- targetType = ensureTargetTypeIsCorrect(targetType);
- // 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 || getKind() == FieldSet) && getActualTargetType() != null
- && !getActualTargetType().equals(targetType.getName())) {
- targetType = UnresolvedType.forName(getActualTargetType()).resolve(world);
- }
- ResolvedMember resolvedMember = getSignature().resolve(world);
-
- // pr230075, pr197719
- if (resolvedMember != null && Modifier.isProtected(resolvedMember.getModifiers())
- && !samePackage(resolvedMember.getDeclaringType().getPackageName(), getEnclosingType().getPackageName())
- && !resolvedMember.getName().equals("clone")) {
- if (!hasThis()) { // pr197719 - static accessor has been created to handle the call
- if (Modifier.isStatic(enclosingMethod.getAccessFlags()) && enclosingMethod.getName().startsWith("access$")) {
- targetType = BcelWorld.fromBcel(enclosingMethod.getArgumentTypes()[0]);
- }
- } else {
- if (!targetType.resolve(world).isAssignableFrom(getThisType().resolve(world))) {
- throw new BCException("bad bytecode");
- }
- targetType = getThisType();
- }
- }
- parameterNames.add("target");
- // There is a 'target' and it is not the same as 'this', so add it to the parameter list
- shadowParameterTypes = addTypeToFront(BcelWorld.makeBcelType(targetType), shadowParameterTypes);
- }
-
- if (thisVar != null) {
- UnresolvedType thisType = getThisType();
- parameterNames.add(0, "ajc$this");
- shadowParameterTypes = addTypeToFront(BcelWorld.makeBcelType(thisType), shadowParameterTypes);
- }
-
- if (this.getKind() == Shadow.FieldSet || this.getKind() == Shadow.FieldGet) {
- parameterNames.add(getSignature().getName());
- } else {
- String[] pnames = getSignature().getParameterNames(world);
- if (pnames != null) {
- for (int i = 0; i < pnames.length; i++) {
- if (i == 0 && pnames[i].equals("this")) {
- parameterNames.add("ajc$this");
- } else {
- parameterNames.add(pnames[i]);
- }
- }
- }
- }
-
- // We always want to pass down thisJoinPoint in case we have already woven
- // some advice in here. If we only have a single piece of around advice on a
- // join point, it is unnecessary to accept (and pass) tjp.
- if (thisJoinPointVar != null) {
- parameterNames.add("thisJoinPoint");
- shadowParameterTypes = addTypeToEnd(LazyClassGen.tjpType, shadowParameterTypes);
- }
-
- UnresolvedType returnType;
- if (getKind() == PreInitialization) {
- returnType = UnresolvedType.OBJECTARRAY;
- } else {
- if (getKind() == ConstructorCall) {
- returnType = getSignature().getDeclaringType();
- } else if (getKind() == FieldSet) {
- returnType = UnresolvedType.VOID;
- } else {
- returnType = getSignature().getReturnType().resolve(world);
- // returnType = getReturnType(); // for this and above lines, see pr137496
- }
- }
- return new LazyMethodGen(modifiers, BcelWorld.makeBcelType(returnType), newMethodName, shadowParameterTypes,
- NoDeclaredExceptions, getEnclosingClass());
- }
-
- private boolean samePackage(String p1, String p2) {
- if (p1 == null) {
- return p2 == null;
- }
- if (p2 == null) {
- return false;
- }
- return p1.equals(p2);
- }
-
- private Type[] addTypeToFront(Type type, Type[] types) {
- int len = types.length;
- Type[] ret = new Type[len + 1];
- ret[0] = type;
- System.arraycopy(types, 0, ret, 1, len);
- return ret;
- }
-
- private Type[] addTypeToEnd(Type type, Type[] types) {
- int len = types.length;
- Type[] ret = new Type[len + 1];
- ret[len] = type;
- System.arraycopy(types, 0, ret, 0, len);
- return ret;
- }
-
- public BcelVar genTempVar(UnresolvedType utype) {
- ResolvedType rtype = utype.resolve(world);
- return new BcelVar(rtype, genTempVarIndex(rtype.getSize()));
- }
-
- // public static final boolean CREATE_TEMP_NAMES = true;
-
- public BcelVar genTempVar(UnresolvedType typeX, String localName) {
- BcelVar tv = genTempVar(typeX);
-
- // if (CREATE_TEMP_NAMES) {
- // for (InstructionHandle ih = range.getStart(); ih != range.getEnd(); ih = ih.getNext()) {
- // if (Range.isRangeHandle(ih)) continue;
- // ih.addTargeter(new LocalVariableTag(typeX, localName, tv.getSlot()));
- // }
- // }
- return tv;
- }
-
- // eh doesn't think we need to garbage collect these (64K is a big number...)
- private int genTempVarIndex(int size) {
- return enclosingMethod.allocateLocal(size);
- }
-
- public InstructionFactory getFactory() {
- return getEnclosingClass().getFactory();
- }
-
- @Override
- public ISourceLocation getSourceLocation() {
- int sourceLine = getSourceLine();
- if (sourceLine == 0 || sourceLine == -1) {
- // Thread.currentThread().dumpStack();
- // System.err.println(this + ": " + range);
- return getEnclosingClass().getType().getSourceLocation();
- } else {
- // For staticinitialization, if we have a nice offset, don't build a new source loc
- if (getKind() == Shadow.StaticInitialization && getEnclosingClass().getType().getSourceLocation().getOffset() != 0) {
- return getEnclosingClass().getType().getSourceLocation();
- } else {
- int offset = 0;
- Kind kind = getKind();
- if ((kind == MethodExecution) || (kind == ConstructorExecution) || (kind == AdviceExecution)
- || (kind == StaticInitialization) || (kind == PreInitialization) || (kind == Initialization)) {
- if (getEnclosingMethod().hasDeclaredLineNumberInfo()) {
- offset = getEnclosingMethod().getDeclarationOffset();
- }
- }
- return getEnclosingClass().getType().getSourceContext().makeSourceLocation(sourceLine, offset);
- }
- }
- }
-
- public Shadow getEnclosingShadow() {
- return enclosingShadow;
- }
-
- public LazyMethodGen getEnclosingMethod() {
- return enclosingMethod;
- }
-
- public boolean isFallsThrough() {
- return !terminatesWithReturn();
- }
-
- public void setActualTargetType(String className) {
- this.actualInstructionTargetType = className;
- }
-
- public String getActualTargetType() {
- return actualInstructionTargetType;
- }
-} \ No newline at end of file
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java
deleted file mode 100644
index b92760fe9..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java
+++ /dev/null
@@ -1,2116 +0,0 @@
-/* *******************************************************************
- * 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
- * Alexandre Vasseur @AspectJ ITDs
- * ******************************************************************/
-
-package org.aspectj.weaver.bcel;
-
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-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.ClassFormatException;
-import org.aspectj.apache.bcel.classfile.ConstantPool;
-import org.aspectj.apache.bcel.classfile.Signature;
-import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
-import org.aspectj.apache.bcel.generic.FieldGen;
-import org.aspectj.apache.bcel.generic.InstructionBranch;
-import org.aspectj.apache.bcel.generic.InstructionConstants;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-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.generic.Type;
-import org.aspectj.asm.AsmManager;
-import org.aspectj.asm.IProgramElement;
-import org.aspectj.bridge.IMessage;
-import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.bridge.Message;
-import org.aspectj.bridge.MessageUtil;
-import org.aspectj.bridge.WeaveMessage;
-import org.aspectj.bridge.context.CompilationAndWeavingContext;
-import org.aspectj.bridge.context.ContextToken;
-import org.aspectj.weaver.AjcMemberMaker;
-import org.aspectj.weaver.AnnotationAJ;
-import org.aspectj.weaver.AnnotationOnTypeMunger;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.ConcreteTypeMunger;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.MemberUtils;
-import org.aspectj.weaver.MethodDelegateTypeMunger;
-import org.aspectj.weaver.NameMangler;
-import org.aspectj.weaver.NewConstructorTypeMunger;
-import org.aspectj.weaver.NewFieldTypeMunger;
-import org.aspectj.weaver.NewMemberClassTypeMunger;
-import org.aspectj.weaver.NewMethodTypeMunger;
-import org.aspectj.weaver.NewParentTypeMunger;
-import org.aspectj.weaver.PerObjectInterfaceTypeMunger;
-import org.aspectj.weaver.PrivilegedAccessMunger;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedMemberImpl;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.ResolvedTypeMunger;
-import org.aspectj.weaver.Shadow;
-import org.aspectj.weaver.TypeVariableReference;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.WeaverMessages;
-import org.aspectj.weaver.WeaverStateInfo;
-import org.aspectj.weaver.World;
-import org.aspectj.weaver.model.AsmRelationshipProvider;
-import org.aspectj.weaver.patterns.DeclareAnnotation;
-import org.aspectj.weaver.patterns.Pointcut;
-
-public class BcelTypeMunger extends ConcreteTypeMunger {
-
- public BcelTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) {
- super(munger, aspectType);
- }
-
- @Override
- public String toString() {
- return "(BcelTypeMunger " + getMunger() + ")";
- }
-
- @Override
- public boolean shouldOverwrite() {
- return false;
- }
-
- public boolean munge(BcelClassWeaver weaver) {
- ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.MUNGING_WITH, this);
- boolean changed = false;
- boolean worthReporting = true;
-
- if (weaver.getWorld().isOverWeaving()) {
- WeaverStateInfo typeWeaverState = weaver.getLazyClassGen().getType().getWeaverState();
- if (typeWeaverState != null && typeWeaverState.isAspectAlreadyApplied(getAspectType())) {
- return false;
- }
- }
-
- if (munger.getKind() == ResolvedTypeMunger.Field) {
- changed = mungeNewField(weaver, (NewFieldTypeMunger) munger);
- } else if (munger.getKind() == ResolvedTypeMunger.Method) {
- changed = mungeNewMethod(weaver, (NewMethodTypeMunger) munger);
- } else if (munger.getKind() == ResolvedTypeMunger.InnerClass) {
- changed = mungeNewMemberType(weaver, (NewMemberClassTypeMunger) munger);
- } else if (munger.getKind() == ResolvedTypeMunger.MethodDelegate2) {
- changed = mungeMethodDelegate(weaver, (MethodDelegateTypeMunger) munger);
- } else if (munger.getKind() == ResolvedTypeMunger.FieldHost) {
- changed = mungeFieldHost(weaver, (MethodDelegateTypeMunger.FieldHostTypeMunger) munger);
- } else if (munger.getKind() == ResolvedTypeMunger.PerObjectInterface) {
- changed = mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger) munger);
- worthReporting = false;
- } else if (munger.getKind() == ResolvedTypeMunger.PerTypeWithinInterface) {
- // PTWIMPL Transform the target type (add the aspect instance field)
- changed = mungePerTypeWithinTransformer(weaver);
- worthReporting = false;
- } else if (munger.getKind() == ResolvedTypeMunger.PrivilegedAccess) {
- changed = mungePrivilegedAccess(weaver, (PrivilegedAccessMunger) munger);
- worthReporting = false;
- } else if (munger.getKind() == ResolvedTypeMunger.Constructor) {
- changed = mungeNewConstructor(weaver, (NewConstructorTypeMunger) munger);
- } else if (munger.getKind() == ResolvedTypeMunger.Parent) {
- changed = mungeNewParent(weaver, (NewParentTypeMunger) munger);
- } else if (munger.getKind() == ResolvedTypeMunger.AnnotationOnType) {
- changed = mungeNewAnnotationOnType(weaver, (AnnotationOnTypeMunger) munger);
- worthReporting = false;
- } else {
- throw new RuntimeException("unimplemented");
- }
-
- if (changed && munger.changesPublicSignature()) {
- WeaverStateInfo info = weaver.getLazyClassGen().getOrCreateWeaverStateInfo(weaver.getReweavableMode());
- info.addConcreteMunger(this);
- }
-
- if (changed && worthReporting) {
- ResolvedType declaringAspect = null;
- AsmManager model = ((BcelWorld) getWorld()).getModelAsAsmManager();
- if (model != null) {
- if (munger instanceof NewParentTypeMunger) {
- NewParentTypeMunger nptMunger = (NewParentTypeMunger) munger;
- declaringAspect = nptMunger.getDeclaringType();
- if (declaringAspect.isParameterizedOrGenericType()) {
- declaringAspect = declaringAspect.getRawType();
- }
- ResolvedType thisAspect = getAspectType();
- AsmRelationshipProvider.addRelationship(model, weaver.getLazyClassGen().getType(), munger, thisAspect);
-
- // Add a relationship on the actual declaring aspect too
- if (!thisAspect.equals(declaringAspect)) {
- // Might be the case the declaring aspect is generic and thisAspect is parameterizing it. In that case
- // record the actual parameterizations
-
- ResolvedType target = weaver.getLazyClassGen().getType();
- ResolvedType newParent = nptMunger.getNewParent();
- IProgramElement thisAspectNode = model.getHierarchy().findElementForType(thisAspect.getPackageName(),
- thisAspect.getClassName());
- Map<String, List<String>> declareParentsMap = thisAspectNode.getDeclareParentsMap();
- if (declareParentsMap == null) {
- declareParentsMap = new HashMap<String, List<String>>();
- thisAspectNode.setDeclareParentsMap(declareParentsMap);
- }
- String tname = target.getName();
- String pname = newParent.getName();
- List<String> newparents = declareParentsMap.get(tname);
- if (newparents == null) {
- newparents = new ArrayList<String>();
- declareParentsMap.put(tname, newparents);
- }
- newparents.add(pname);
- AsmRelationshipProvider.addRelationship(model, weaver.getLazyClassGen().getType(), munger, declaringAspect);
- }
- } else {
- declaringAspect = getAspectType();
- AsmRelationshipProvider.addRelationship(model, weaver.getLazyClassGen().getType(), munger, declaringAspect);
- }
- }
- }
-
- // TAG: WeavingMessage
- if (changed && worthReporting && munger != null && !weaver.getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
- String tName = weaver.getLazyClassGen().getType().getSourceLocation().getSourceFile().getName();
- if (tName.indexOf("no debug info available") != -1) {
- tName = "no debug info available";
- } else {
- tName = getShortname(weaver.getLazyClassGen().getType().getSourceLocation().getSourceFile().getPath());
- }
- String fName = getShortname(getAspectType().getSourceLocation().getSourceFile().getPath());
- if (munger.getKind().equals(ResolvedTypeMunger.Parent)) {
- // This message could come out of AjLookupEnvironment.addParent
- // if doing parents munging at compile time only...
- NewParentTypeMunger parentTM = (NewParentTypeMunger) munger;
- if (parentTM.isMixin()) {
- weaver.getWorld()
- .getMessageHandler()
- .handleMessage(
- WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_MIXIN, new String[] {
- parentTM.getNewParent().getName(), fName, weaver.getLazyClassGen().getType().getName(),
- tName }, weaver.getLazyClassGen().getClassName(), getAspectType().getName()));
- } else {
- if (parentTM.getNewParent().isInterface()) {
- weaver.getWorld()
- .getMessageHandler()
- .handleMessage(
- WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSIMPLEMENTS,
- new String[] { weaver.getLazyClassGen().getType().getName(), tName,
- parentTM.getNewParent().getName(), fName }, weaver.getLazyClassGen()
- .getClassName(), getAspectType().getName()));
- } else {
- weaver.getWorld()
- .getMessageHandler()
- .handleMessage(
- WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSEXTENDS,
- new String[] { weaver.getLazyClassGen().getType().getName(), tName,
- parentTM.getNewParent().getName(), fName }));
- // TAG: WeavingMessage DECLARE PARENTS: EXTENDS
- // reportDeclareParentsMessage(WeaveMessage.
- // WEAVEMESSAGE_DECLAREPARENTSEXTENDS,sourceType,parent);
-
- }
- }
- } else if (munger.getKind().equals(ResolvedTypeMunger.FieldHost)) {
- // hidden
- } else {
- ResolvedMember declaredSig = munger.getSignature();
- String fromString = fName + ":'" + declaredSig + "'";
- // if (declaredSig==null) declaredSig= munger.getSignature();
- String kindString = munger.getKind().toString().toLowerCase();
- if (kindString.equals("innerclass")) {
- kindString = "member class";
- fromString = fName;
- }
- weaver.getWorld()
- .getMessageHandler()
- .handleMessage(
- WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ITD, new String[] {
- weaver.getLazyClassGen().getType().getName(), tName, kindString, getAspectType().getName(),
- fromString }, weaver.getLazyClassGen().getClassName(), getAspectType().getName()));
- }
- }
-
- CompilationAndWeavingContext.leavingPhase(tok);
- return changed;
- }
-
- private String getShortname(String path) {
- int takefrom = path.lastIndexOf('/');
- if (takefrom == -1) {
- takefrom = path.lastIndexOf('\\');
- }
- return path.substring(takefrom + 1);
- }
-
- private boolean mungeNewAnnotationOnType(BcelClassWeaver weaver, AnnotationOnTypeMunger munger) {
- // FIXME asc this has already been done up front, need to do it here too?
- try {
- BcelAnnotation anno = (BcelAnnotation) munger.getNewAnnotation();
- weaver.getLazyClassGen().addAnnotation(anno.getBcelAnnotation());
- } catch (ClassCastException cce) {
- throw new IllegalStateException("DiagnosticsFor318237: The typemunger "+munger+" contains an annotation of type "+
- munger.getNewAnnotation().getClass().getName()+" when it should be a BcelAnnotation",cce);
- }
- return true;
- }
-
- /**
- * For a long time, AspectJ did not allow binary weaving of declare parents. This restriction is now lifted but could do with
- * more testing!
- */
- private boolean mungeNewParent(BcelClassWeaver weaver, NewParentTypeMunger typeTransformer) {
- LazyClassGen newParentTarget = weaver.getLazyClassGen();
- ResolvedType newParent = typeTransformer.getNewParent();
-
- boolean performChange = true;
- performChange = enforceDecpRule1_abstractMethodsImplemented(weaver, typeTransformer.getSourceLocation(), newParentTarget,
- newParent);
- performChange = enforceDecpRule2_cantExtendFinalClass(weaver, typeTransformer.getSourceLocation(), newParentTarget,
- newParent) && performChange;
-
- List<ResolvedMember> methods = newParent.getMethodsWithoutIterator(false, true, false);
- for (ResolvedMember method : methods) {
- if (!method.getName().equals("<init>")) {
- LazyMethodGen subMethod = findMatchingMethod(newParentTarget, method);
- // FIXME asc is this safe for all bridge methods?
- if (subMethod != null && !subMethod.isBridgeMethod()) {
- if (!(subMethod.isSynthetic() && method.isSynthetic())) {
- if (!(subMethod.isStatic() && subMethod.getName().startsWith("access$"))) {
- // ignore generated accessors
- performChange = enforceDecpRule3_visibilityChanges(weaver, newParent, method, subMethod)
- && performChange;
- performChange = enforceDecpRule4_compatibleReturnTypes(weaver, method, subMethod) && performChange;
- performChange = enforceDecpRule5_cantChangeFromStaticToNonstatic(weaver,
- typeTransformer.getSourceLocation(), method, subMethod)
- && performChange;
- }
- }
- }
- }
- }
- if (!performChange) {
- // A rule was violated and an error message already reported
- return false;
- }
-
- if (newParent.isClass()) {
- // Changing the supertype
- if (!attemptToModifySuperCalls(weaver, newParentTarget, newParent)) {
- return false;
- }
- newParentTarget.setSuperClass(newParent);
- } else {
- // Add a new interface
- newParentTarget.addInterface(newParent, getSourceLocation());
- }
- return true;
- }
-
- /**
- * Rule 1: For the declare parents to be allowed, the target type must override and implement inherited abstract methods (if the
- * type is not declared abstract)
- */
- private boolean enforceDecpRule1_abstractMethodsImplemented(BcelClassWeaver weaver, ISourceLocation mungerLoc,
- LazyClassGen newParentTarget, ResolvedType newParent) {
- // Ignore abstract classes or interfaces
- if (newParentTarget.isAbstract() || newParentTarget.isInterface()) {
- return true;
- }
- boolean ruleCheckingSucceeded = true;
- List<ResolvedMember> newParentMethods = newParent.getMethodsWithoutIterator(false, true, false);
- for (ResolvedMember newParentMethod : newParentMethods) {
- String newParentMethodName = newParentMethod.getName();
- // Ignore abstract ajc$interField prefixed methods
- if (newParentMethod.isAbstract() && !newParentMethodName.startsWith("ajc$interField")) {
- ResolvedMember discoveredImpl = null;
- List<ResolvedMember> targetMethods = newParentTarget.getType().getMethodsWithoutIterator(false, true, false);
- for (ResolvedMember targetMethod : targetMethods) {
- if (!targetMethod.isAbstract() && targetMethod.getName().equals(newParentMethodName)) {
- String newParentMethodSig = newParentMethod.getParameterSignature(); // ([TT;)
- String targetMethodSignature = targetMethod.getParameterSignature(); // ([Ljava/lang/Object;)
- // could be a match
- if (targetMethodSignature.equals(newParentMethodSig)) {
- discoveredImpl = targetMethod;
- } else {
- // Does the erasure match? In which case a bridge method will be created later to
- // satisfy the abstract method
- if (targetMethod.hasBackingGenericMember()
- && targetMethod.getBackingGenericMember().getParameterSignature().equals(newParentMethodSig)) {
- discoveredImpl = targetMethod;
- } else if (newParentMethod.hasBackingGenericMember()) {
- if (newParentMethod.getBackingGenericMember().getParameterSignature().equals(targetMethodSignature)) { // newParentMethod.getBackingGenericMember().getParameterSignature gives: (Pjava/util/List<TI;>;) targetMethodSignature= (Ljava/util/List;)
- discoveredImpl = targetMethod;
- } else if (targetMethod instanceof BcelMethod) {
- // BcelMethod does not have backing generic member set (need to investigate why). For now, special case here:
- UnresolvedType[] targetMethodGenericParameterTypes = targetMethod.getGenericParameterTypes();
- if (targetMethodGenericParameterTypes !=null) {
- StringBuilder b = new StringBuilder("(");
- for (UnresolvedType p: targetMethodGenericParameterTypes) {
- b.append(p.getSignature());
- }
- b.append(')');
- if (b.toString().equals(newParentMethodSig)) {
- discoveredImpl = targetMethod;
- }
- }
- }
- }
- }
- if (discoveredImpl != null) {
- break;
- }
- }
- }
- if (discoveredImpl == null) {
- // didnt find a valid implementation, lets check the
- // ITDs on this type to see if they satisfy it
- boolean satisfiedByITD = false;
- for (ConcreteTypeMunger m : newParentTarget.getType().getInterTypeMungersIncludingSupers()) {
- if (m.getMunger() != null && m.getMunger().getKind() == ResolvedTypeMunger.Method) {
- ResolvedMember sig = m.getSignature();
- if (!Modifier.isAbstract(sig.getModifiers())) {
- // If the ITD shares a type variable with some target type, we need to tailor it
- // for that type
- if (m.isTargetTypeParameterized()) {
- ResolvedType genericOnType = getWorld().resolve(sig.getDeclaringType()).getGenericType();
- ResolvedType actualOccurrence = newParent.discoverActualOccurrenceOfTypeInHierarchy(genericOnType);
- if (actualOccurrence == null) {
- // Handle the case where the ITD is onto the type targeted by the declare parents (PR478003)
- actualOccurrence = newParentTarget.getType().discoverActualOccurrenceOfTypeInHierarchy(genericOnType);
- }
- m = m.parameterizedFor(actualOccurrence);
- // possible sig change when type parameters filled in
- sig = m.getSignature();
- }
- if (ResolvedType.matches(
- AjcMemberMaker.interMethod(sig, m.getAspectType(),
- sig.getDeclaringType().resolve(weaver.getWorld()).isInterface()), newParentMethod)) {
- satisfiedByITD = true;
- }
- }
- } else if (m.getMunger() != null && m.getMunger().getKind() == ResolvedTypeMunger.MethodDelegate2) {
- // AV - that should be enough, no need to check more
- satisfiedByITD = true;
- }
- }
- if (!satisfiedByITD) {
- error(weaver,
- "The type " + newParentTarget.getName() + " must implement the inherited abstract method "
- + newParentMethod.getDeclaringType() + "." + newParentMethodName
- + newParentMethod.getParameterSignature(), newParentTarget.getType().getSourceLocation(),
- new ISourceLocation[] { newParentMethod.getSourceLocation(), mungerLoc });
- ruleCheckingSucceeded = false;
- }
- }
- }
- }
- return ruleCheckingSucceeded;
- }
-
- /**
- * Rule 2. Can't extend final types
- */
- private boolean enforceDecpRule2_cantExtendFinalClass(BcelClassWeaver weaver, ISourceLocation transformerLoc,
- LazyClassGen targetType, ResolvedType newParent) {
- if (newParent.isFinal()) {
- error(weaver, "Cannot make type " + targetType.getName() + " extend final class " + newParent.getName(), targetType
- .getType().getSourceLocation(), new ISourceLocation[] { transformerLoc });
- return false;
- }
- return true;
- }
-
- /**
- * Rule 3. Can't narrow visibility of methods when overriding
- */
- private boolean enforceDecpRule3_visibilityChanges(BcelClassWeaver weaver, ResolvedType newParent, ResolvedMember superMethod,
- LazyMethodGen subMethod) {
- boolean cont = true;
- if (Modifier.isPublic(superMethod.getModifiers())) {
- if (subMethod.isProtected() || subMethod.isDefault() || subMethod.isPrivate()) {
- weaver.getWorld()
- .getMessageHandler()
- .handleMessage(
- MessageUtil.error("Cannot reduce the visibility of the inherited method '" + superMethod
- + "' from " + newParent.getName(), superMethod.getSourceLocation()));
- cont = false;
- }
- } else if (Modifier.isProtected(superMethod.getModifiers())) {
- if (subMethod.isDefault() || subMethod.isPrivate()) {
- weaver.getWorld()
- .getMessageHandler()
- .handleMessage(
- MessageUtil.error("Cannot reduce the visibility of the inherited method '" + superMethod
- + "' from " + newParent.getName(), superMethod.getSourceLocation()));
- cont = false;
- }
- } else if (superMethod.isDefault()) {
- if (subMethod.isPrivate()) {
- weaver.getWorld()
- .getMessageHandler()
- .handleMessage(
- MessageUtil.error("Cannot reduce the visibility of the inherited method '" + superMethod
- + "' from " + newParent.getName(), superMethod.getSourceLocation()));
- cont = false;
- }
- }
- return cont;
- }
-
- /**
- * Rule 4. Can't have incompatible return types
- */
- private boolean enforceDecpRule4_compatibleReturnTypes(BcelClassWeaver weaver, ResolvedMember superMethod,
- LazyMethodGen subMethod) {
- boolean cont = true;
- 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)) {
- weaver.getWorld()
- .getMessageHandler()
- .handleMessage(
- MessageUtil.error("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;
- }
-
- /**
- * Rule5. Method overrides can't change the staticality (word?) - you can't override and make an instance method static or
- * override and make a static method an instance method.
- */
- private boolean enforceDecpRule5_cantChangeFromStaticToNonstatic(BcelClassWeaver weaver, ISourceLocation mungerLoc,
- ResolvedMember superMethod, LazyMethodGen subMethod) {
- boolean superMethodStatic = Modifier.isStatic(superMethod.getModifiers());
- if (superMethodStatic && !subMethod.isStatic()) {
- error(weaver, "This instance method " + subMethod.getName() + subMethod.getParameterSignature()
- + " cannot override the static method from " + superMethod.getDeclaringType().getName(),
- subMethod.getSourceLocation(), new ISourceLocation[] { mungerLoc });
- return false;
- } else if (!superMethodStatic && subMethod.isStatic()) {
- error(weaver, "The static method " + subMethod.getName() + subMethod.getParameterSignature()
- + " cannot hide the instance method from " + superMethod.getDeclaringType().getName(),
- subMethod.getSourceLocation(), new ISourceLocation[] { mungerLoc });
- return false;
- }
- return true;
- }
-
- public void error(BcelClassWeaver weaver, String text, ISourceLocation primaryLoc, ISourceLocation[] extraLocs) {
- IMessage msg = new Message(text, primaryLoc, true, extraLocs);
- weaver.getWorld().getMessageHandler().handleMessage(msg);
- }
-
- /**
- * 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 type, ResolvedMember searchMethod) {
- String searchName = searchMethod.getName();
- String searchSig = searchMethod.getParameterSignature();
- for (LazyMethodGen method : type.getMethodGens()) {
- if (method.getName().equals(searchName) && method.getParameterSignature().equals(searchSig)) {
- return method;
- }
- }
- return null;
- }
-
- /**
- * The main part of implementing declare parents extends. Modify super ctor calls to target the new type.
- */
- public boolean attemptToModifySuperCalls(BcelClassWeaver weaver, LazyClassGen newParentTarget, ResolvedType newParent) {
- ResolvedType currentParentType = newParentTarget.getSuperClass();
- if (currentParentType.getGenericType() != null) {
- currentParentType = currentParentType.getGenericType();
- }
- String currentParent = currentParentType.getName();
- if (newParent.getGenericType() != null) {
- newParent = newParent.getGenericType(); // target new super calls at
- }
- // the generic type if its raw or parameterized
- List<LazyMethodGen> mgs = newParentTarget.getMethodGens();
-
- // Look for ctors to modify
- for (LazyMethodGen aMethod : mgs) {
- if (LazyMethodGen.isConstructor(aMethod)) {
- InstructionList insList = aMethod.getBody();
- InstructionHandle handle = insList.getStart();
- while (handle != null) {
- if (handle.getInstruction().opcode == Constants.INVOKESPECIAL) {
- ConstantPool cpg = newParentTarget.getConstantPool();
- InvokeInstruction invokeSpecial = (InvokeInstruction) handle.getInstruction();
- if (invokeSpecial.getClassName(cpg).equals(currentParent)
- && invokeSpecial.getMethodName(cpg).equals("<init>")) {
- // System.err.println("Transforming super call '<init>" + invokeSpecial.getSignature(cpg) + "'");
-
- // 1. Check there is a ctor in the new parent with
- // the same signature
- ResolvedMember newCtor = getConstructorWithSignature(newParent, invokeSpecial.getSignature(cpg));
-
- if (newCtor == null) {
-
- // 2. Check ITDCs to see if the necessary ctor is provided that way
- boolean satisfiedByITDC = false;
- for (Iterator<ConcreteTypeMunger> ii = newParentTarget.getType()
- .getInterTypeMungersIncludingSupers().iterator(); ii.hasNext() && !satisfiedByITDC;) {
- ConcreteTypeMunger m = ii.next();
- if (m.getMunger() instanceof NewConstructorTypeMunger) {
- if (m.getSignature().getSignature().equals(invokeSpecial.getSignature(cpg))) {
- satisfiedByITDC = true;
- }
- }
- }
-
- if (!satisfiedByITDC) {
- String csig = createReadableCtorSig(newParent, cpg, invokeSpecial);
- weaver.getWorld()
- .getMessageHandler()
- .handleMessage(
- MessageUtil.error(
- "Unable to modify hierarchy for " + newParentTarget.getClassName()
- + " - the constructor " + csig + " is missing",
- this.getSourceLocation()));
- return false;
- }
- }
-
- int idx = cpg.addMethodref(newParent.getName(), invokeSpecial.getMethodName(cpg),
- invokeSpecial.getSignature(cpg));
- invokeSpecial.setIndex(idx);
- }
- }
- handle = handle.getNext();
- }
- }
- }
- return true;
- }
-
- /**
- * Creates a nice signature for the ctor, something like "(int,Integer,String)"
- */
- private String createReadableCtorSig(ResolvedType newParent, ConstantPool cpg, InvokeInstruction invokeSpecial) {
- StringBuffer sb = new StringBuffer();
- Type[] ctorArgs = invokeSpecial.getArgumentTypes(cpg);
- sb.append(newParent.getClassName());
- sb.append("(");
- for (int i = 0; i < ctorArgs.length; i++) {
- String argtype = ctorArgs[i].toString();
- if (argtype.lastIndexOf(".") != -1) {
- sb.append(argtype.substring(argtype.lastIndexOf(".") + 1));
- } else {
- sb.append(argtype);
- }
- if (i + 1 < ctorArgs.length) {
- sb.append(",");
- }
- }
- sb.append(")");
- return sb.toString();
- }
-
- private ResolvedMember getConstructorWithSignature(ResolvedType type, String searchSig) {
- for (ResolvedMember method : type.getDeclaredJavaMethods()) {
- if (MemberUtils.isConstructor(method)) {
- if (method.getSignature().equals(searchSig)) {
- return method;
- }
- }
- }
- return null;
- }
-
- private boolean mungePrivilegedAccess(BcelClassWeaver weaver, PrivilegedAccessMunger munger) {
- LazyClassGen gen = weaver.getLazyClassGen();
- ResolvedMember member = munger.getMember();
-
- ResolvedType onType = weaver.getWorld().resolve(member.getDeclaringType(), munger.getSourceLocation());
- if (onType.isRawType()) {
- onType = onType.getGenericType();
- }
-
- // System.out.println("munging: " + gen + " with " + member);
- if (onType.equals(gen.getType())) {
- if (member.getKind() == Member.FIELD) {
- // System.out.println("matched: " + gen);
- addFieldGetter(gen, member,
- AjcMemberMaker.privilegedAccessMethodForFieldGet(aspectType, member, munger.shortSyntax));
- addFieldSetter(gen, member,
- AjcMemberMaker.privilegedAccessMethodForFieldSet(aspectType, member, munger.shortSyntax));
- return true;
- } else if (member.getKind() == Member.METHOD) {
- addMethodDispatch(gen, member, AjcMemberMaker.privilegedAccessMethodForMethod(aspectType, member));
- return true;
- } else if (member.getKind() == Member.CONSTRUCTOR) {
- for (Iterator<LazyMethodGen> i = gen.getMethodGens().iterator(); i.hasNext();) {
- LazyMethodGen m = i.next();
- if (m.getMemberView() != null && m.getMemberView().getKind() == Member.CONSTRUCTOR) {
- // m.getMemberView().equals(member)) {
- m.forcePublic();
- // return true;
- }
- }
- return true;
- // throw new BCException("no match for " + member + " in " +
- // gen);
- } else if (member.getKind() == Member.STATIC_INITIALIZATION) {
- gen.forcePublic();
- return true;
- } else {
- throw new RuntimeException("unimplemented");
- }
- }
- return false;
- }
-
- private void addFieldGetter(LazyClassGen gen, ResolvedMember field, ResolvedMember accessMethod) {
- LazyMethodGen mg = makeMethodGen(gen, accessMethod);
- InstructionList il = new InstructionList();
- InstructionFactory fact = gen.getFactory();
- if (Modifier.isStatic(field.getModifiers())) {
- il.append(fact.createFieldAccess(gen.getClassName(), field.getName(), BcelWorld.makeBcelType(field.getType()),
- Constants.GETSTATIC));
- } else {
- il.append(InstructionConstants.ALOAD_0);
- il.append(fact.createFieldAccess(gen.getClassName(), field.getName(), BcelWorld.makeBcelType(field.getType()),
- Constants.GETFIELD));
- }
- il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(field.getType())));
- mg.getBody().insert(il);
-
- gen.addMethodGen(mg, getSignature().getSourceLocation());
- }
-
- private void addFieldSetter(LazyClassGen gen, ResolvedMember field, ResolvedMember accessMethod) {
- LazyMethodGen mg = makeMethodGen(gen, accessMethod);
- InstructionList il = new InstructionList();
- InstructionFactory fact = gen.getFactory();
- Type fieldType = BcelWorld.makeBcelType(field.getType());
-
- if (Modifier.isStatic(field.getModifiers())) {
- il.append(InstructionFactory.createLoad(fieldType, 0));
- il.append(fact.createFieldAccess(gen.getClassName(), field.getName(), fieldType, Constants.PUTSTATIC));
- } else {
- il.append(InstructionConstants.ALOAD_0);
- il.append(InstructionFactory.createLoad(fieldType, 1));
- il.append(fact.createFieldAccess(gen.getClassName(), field.getName(), fieldType, Constants.PUTFIELD));
- }
- il.append(InstructionFactory.createReturn(Type.VOID));
- mg.getBody().insert(il);
-
- gen.addMethodGen(mg, getSignature().getSourceLocation());
- }
-
- private void addMethodDispatch(LazyClassGen gen, ResolvedMember method, ResolvedMember accessMethod) {
- LazyMethodGen mg = makeMethodGen(gen, accessMethod);
- InstructionList il = new InstructionList();
- InstructionFactory fact = gen.getFactory();
- Type[] paramTypes = BcelWorld.makeBcelTypes(method.getParameterTypes());
-
- int pos = 0;
-
- if (!Modifier.isStatic(method.getModifiers())) {
- il.append(InstructionConstants.ALOAD_0);
- pos++;
- }
- for (int i = 0, len = paramTypes.length; i < len; i++) {
- Type paramType = paramTypes[i];
- il.append(InstructionFactory.createLoad(paramType, pos));
- pos += paramType.getSize();
- }
- il.append(Utility.createInvoke(fact, (BcelWorld) aspectType.getWorld(), method));
- il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(method.getReturnType())));
-
- mg.getBody().insert(il);
-
- gen.addMethodGen(mg);
- }
-
- protected LazyMethodGen makeMethodGen(LazyClassGen gen, ResolvedMember member) {
- try {
- Type returnType = BcelWorld.makeBcelType(member.getReturnType());
- Type[] parameterTypes = BcelWorld.makeBcelTypes(member.getParameterTypes());
- LazyMethodGen ret = new LazyMethodGen(member.getModifiers(), returnType,
- member.getName(), parameterTypes, UnresolvedType.getNames(member
- .getExceptions()), gen);
-
- // 43972 : Static crosscutting makes interfaces unusable for javac
- // ret.makeSynthetic();
- return ret;
- } catch (ClassFormatException cfe) {
- throw new RuntimeException("Problem with makeMethodGen for method "+member.getName()+" in type "+gen.getName()+" ret="+member.getReturnType(),cfe);
- }
- }
-
- protected FieldGen makeFieldGen(LazyClassGen gen, ResolvedMember member) {
- return new FieldGen(member.getModifiers(), BcelWorld.makeBcelType(member.getReturnType()), member.getName(),
- gen.getConstantPool());
- }
-
- private boolean mungePerObjectInterface(BcelClassWeaver weaver, PerObjectInterfaceTypeMunger munger) {
- // System.err.println("Munging perobject ["+munger+"] onto "+weaver.
- // getLazyClassGen().getClassName());
- LazyClassGen gen = weaver.getLazyClassGen();
-
- if (couldMatch(gen.getBcelObjectType(), munger.getTestPointcut())) {
- FieldGen fg = makeFieldGen(gen, AjcMemberMaker.perObjectField(gen.getType(), aspectType));
-
- gen.addField(fg, getSourceLocation());
-
- Type fieldType = BcelWorld.makeBcelType(aspectType);
- LazyMethodGen mg = new LazyMethodGen(Modifier.PUBLIC, fieldType, NameMangler.perObjectInterfaceGet(aspectType),
- new Type[0], new String[0], gen);
- InstructionList il = new InstructionList();
- InstructionFactory fact = gen.getFactory();
- il.append(InstructionConstants.ALOAD_0);
- il.append(fact.createFieldAccess(gen.getClassName(), fg.getName(), fieldType, Constants.GETFIELD));
- il.append(InstructionFactory.createReturn(fieldType));
- mg.getBody().insert(il);
-
- gen.addMethodGen(mg);
-
- LazyMethodGen mg1 = new LazyMethodGen(Modifier.PUBLIC, Type.VOID, NameMangler.perObjectInterfaceSet(aspectType),
-
- new Type[] { fieldType, }, new String[0], gen);
- InstructionList il1 = new InstructionList();
- il1.append(InstructionConstants.ALOAD_0);
- il1.append(InstructionFactory.createLoad(fieldType, 1));
- il1.append(fact.createFieldAccess(gen.getClassName(), fg.getName(), fieldType, Constants.PUTFIELD));
- il1.append(InstructionFactory.createReturn(Type.VOID));
- mg1.getBody().insert(il1);
-
- gen.addMethodGen(mg1);
-
- gen.addInterface(munger.getInterfaceType().resolve(weaver.getWorld()), getSourceLocation());
-
- return true;
- } else {
- return false;
- }
- }
-
- // PTWIMPL Add field to hold aspect instance and an accessor
- private boolean mungePerTypeWithinTransformer(BcelClassWeaver weaver) {
- LazyClassGen gen = weaver.getLazyClassGen();
-
- // if (couldMatch(gen.getBcelObjectType(), munger.getTestPointcut())) {
-
- // Add (to the target type) the field that will hold the aspect instance
- // e.g ajc$com_blah_SecurityAspect$ptwAspectInstance
- FieldGen fg = makeFieldGen(gen, AjcMemberMaker.perTypeWithinField(gen.getType(), aspectType));
- gen.addField(fg, getSourceLocation());
- if (!gen.getType().canBeSeenBy(aspectType) && aspectType.isPrivilegedAspect()) {
- gen.forcePublic();
- }
- // Add an accessor for this new field, the
- // ajc$<aspectname>$localAspectOf() method
- // e.g.
- // "public com_blah_SecurityAspect ajc$com_blah_SecurityAspect$localAspectOf()"
- Type fieldType = BcelWorld.makeBcelType(aspectType);
- LazyMethodGen mg = new LazyMethodGen(Modifier.PUBLIC | Modifier.STATIC, fieldType,
- NameMangler.perTypeWithinLocalAspectOf(aspectType), new Type[0], new String[0], gen);
- InstructionList il = new InstructionList();
- // PTWIMPL ?? Should check if it is null and throw
- // NoAspectBoundException
- InstructionFactory fact = gen.getFactory();
- il.append(fact.createFieldAccess(gen.getClassName(), fg.getName(), fieldType, Constants.GETSTATIC));
- il.append(InstructionFactory.createReturn(fieldType));
- mg.getBody().insert(il);
- gen.addMethodGen(mg);
- return true;
- // } else {
- // return false;
- // }
- }
-
- // ??? Why do we have this method? I thought by now we would know if it
- // matched or not
- private boolean couldMatch(BcelObjectType bcelObjectType, Pointcut pointcut) {
- return !bcelObjectType.isInterface();
- }
-
- private boolean mungeNewMemberType(BcelClassWeaver classWeaver, NewMemberClassTypeMunger munger) {
- World world = classWeaver.getWorld();
- ResolvedType onType = world.resolve(munger.getTargetType());
- if (onType.isRawType()) {
- onType = onType.getGenericType();
- }
- return onType.equals(classWeaver.getLazyClassGen().getType());
- }
-
- private boolean mungeNewMethod(BcelClassWeaver classWeaver, NewMethodTypeMunger munger) {
- World world = classWeaver.getWorld();
-
- // Resolving it will sort out the tvars
- ResolvedMember unMangledInterMethod = munger.getSignature().resolve(world);
-
- // do matching on the unMangled one, but actually add them to the mangled method
- ResolvedMember interMethodBody = munger.getDeclaredInterMethodBody(aspectType, world);
- ResolvedMember interMethodDispatcher = munger.getDeclaredInterMethodDispatcher(aspectType, world);
- ResolvedMember memberHoldingAnyAnnotations = interMethodDispatcher;
- LazyClassGen classGen = classWeaver.getLazyClassGen();
-
- ResolvedType onType = world.resolve(unMangledInterMethod.getDeclaringType(), munger.getSourceLocation());
- if (onType.isRawType()) {
- onType = onType.getGenericType();
- }
-
- // Simple checks, can't ITD on annotations or enums
- if (onType.isAnnotation()) {
- signalError(WeaverMessages.ITDM_ON_ANNOTATION_NOT_ALLOWED, classWeaver, onType);
- return false;
- }
-
- if (onType.isEnum()) {
- signalError(WeaverMessages.ITDM_ON_ENUM_NOT_ALLOWED, classWeaver, onType);
- return false;
- }
-
- boolean mungingInterface = classGen.isInterface();
- boolean onInterface = onType.isInterface();
-
- if (onInterface
- && classGen.getLazyMethodGen(unMangledInterMethod.getName(), unMangledInterMethod.getSignature(), true) != null) {
- // this is ok, we could be providing the default implementation of a
- // method
- // that the target has already declared
- return false;
- }
-
- // If we are processing the intended ITD target type (might be an interface)
- if (onType.equals(classGen.getType())) {
- ResolvedMember mangledInterMethod = AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, onInterface);
-
- LazyMethodGen newMethod = makeMethodGen(classGen, mangledInterMethod);
- if (mungingInterface) {
- // we want the modifiers of the ITD to be used for all *implementors* of the
- // interface, but the method itself we add to the interface must be public abstract
- newMethod.setAccessFlags(Modifier.PUBLIC | Modifier.ABSTRACT);
- }
-
- // pr98901
- // For copying the annotations across, we have to discover the real
- // member in the aspect which is holding them.
- if (classWeaver.getWorld().isInJava5Mode()) {
- AnnotationAJ annotationsOnRealMember[] = null;
- ResolvedType toLookOn = aspectType;
- if (aspectType.isRawType()) {
- toLookOn = aspectType.getGenericType();
- }
- ResolvedMember realMember = getRealMemberForITDFromAspect(toLookOn, memberHoldingAnyAnnotations, false);
- // 266602 - consider it missing to mean that the corresponding aspect had errors
- if (realMember == null) {
- // signalWarning("Unable to apply any annotations attached to " + munger.getSignature(), weaver);
- // throw new BCException("Couldn't find ITD init member '" + interMethodBody + "' on aspect " + aspectType);
- } else {
- annotationsOnRealMember = realMember.getAnnotations();
- }
- Set<ResolvedType> addedAnnotations = new HashSet<ResolvedType>();
- if (annotationsOnRealMember != null) {
- for (AnnotationAJ anno : annotationsOnRealMember) {
- AnnotationGen a = ((BcelAnnotation) anno).getBcelAnnotation();
- AnnotationGen ag = new AnnotationGen(a, classGen.getConstantPool(), true);
- newMethod.addAnnotation(new BcelAnnotation(ag, classWeaver.getWorld()));
- addedAnnotations.add(anno.getType());
- }
- }
- if (realMember != null) {
- copyOverParameterAnnotations(newMethod, realMember);
- }
- // the code below was originally added to cope with the case where an aspect declares an annotation on an ITD
- // declared within itself (an unusual situation). However, it also addresses the case where we may not find the
- // annotation on the real representation of the ITD. This can happen in a load-time weaving situation where
- // we couldn't add the annotation in time - and so here we recheck the declare annotations. Not quite ideal but
- // works. pr288635
- List<DeclareAnnotation> allDecams = world.getDeclareAnnotationOnMethods();
- for (DeclareAnnotation declareAnnotationMC : allDecams) {
- if (declareAnnotationMC.matches(unMangledInterMethod, world)) {
- // && newMethod.getEnclosingClass().getType() == aspectType) {
- AnnotationAJ annotation = declareAnnotationMC.getAnnotation();
- if (!addedAnnotations.contains(annotation.getType())) {
- newMethod.addAnnotation(annotation);
- }
- }
- }
- }
-
- // If it doesn't target an interface and there is a body (i.e. it isnt abstract)
- if (!onInterface && !Modifier.isAbstract(mangledInterMethod.getModifiers())) {
- InstructionList body = newMethod.getBody();
- InstructionFactory fact = classGen.getFactory();
- int pos = 0;
-
- if (!Modifier.isStatic(unMangledInterMethod.getModifiers())) {
- body.append(InstructionFactory.createThis());
- pos++;
- }
- Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes());
- for (int i = 0, len = paramTypes.length; i < len; i++) {
- Type paramType = paramTypes[i];
- body.append(InstructionFactory.createLoad(paramType, pos));
- pos += paramType.getSize();
- }
- body.append(Utility.createInvoke(fact, classWeaver.getWorld(), interMethodBody));
- body.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(mangledInterMethod.getReturnType())));
-
- if (classWeaver.getWorld().isInJava5Mode()) { // Don't need bridge
- // methods if not in
- // 1.5 mode.
- createAnyBridgeMethodsForCovariance(classWeaver, munger, unMangledInterMethod, onType, classGen, paramTypes);
- }
-
- } else {
- // ??? this is okay
- // if (!(mg.getBody() == null)) throw new
- // RuntimeException("bas");
- }
-
- if (world.isInJava5Mode()) {
- String basicSignature = mangledInterMethod.getSignature();
- String genericSignature = ((ResolvedMemberImpl) mangledInterMethod).getSignatureForAttribute();
- if (!basicSignature.equals(genericSignature)) {
- // Add a signature attribute to it
- newMethod.addAttribute(createSignatureAttribute(classGen.getConstantPool(), genericSignature));
- }
- }
- // XXX make sure to check that we set exceptions properly on this
- // guy.
- classWeaver.addLazyMethodGen(newMethod);
- classWeaver.getLazyClassGen().warnOnAddedMethod(newMethod.getMethod(), getSignature().getSourceLocation());
-
- addNeededSuperCallMethods(classWeaver, onType, munger.getSuperMethodsCalled());
-
- return true;
-
- } else if (onInterface && !Modifier.isAbstract(unMangledInterMethod.getModifiers())) {
-
- // This means the 'gen' should be the top most implementor
- // - if it is *not* then something went wrong after we worked
- // out that it was the top most implementor (see pr49657)
- if (!classGen.getType().isTopmostImplementor(onType)) {
- ResolvedType rtx = classGen.getType().getTopmostImplementor(onType);
- if (rtx == null) {
- // pr302460
- // null means there is something wrong with what we are looking at
- ResolvedType rt = classGen.getType();
- if (rt.isInterface()) {
- ISourceLocation sloc = munger.getSourceLocation();
- classWeaver
- .getWorld()
- .getMessageHandler()
- .handleMessage(
- MessageUtil.error(
- "ITD target "
- + rt.getName()
- + " is an interface but has been incorrectly determined to be the topmost implementor of "
- + onType.getName() + ". ITD is " + this.getSignature(), sloc));
- }
- if (!onType.isAssignableFrom(rt)) {
- ISourceLocation sloc = munger.getSourceLocation();
- classWeaver
- .getWorld()
- .getMessageHandler()
- .handleMessage(
- MessageUtil.error(
- "ITD target " + rt.getName() + " doesn't appear to implement " + onType.getName()
- + " why did we consider it the top most implementor? ITD is "
- + this.getSignature(), sloc));
- }
- } else if (!rtx.isExposedToWeaver()) {
- ISourceLocation sLoc = munger.getSourceLocation();
- classWeaver
- .getWorld()
- .getMessageHandler()
- .handleMessage(
- MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_NON_EXPOSED_IMPLEMENTOR, rtx,
- getAspectType().getName()), (sLoc == null ? getAspectType().getSourceLocation() : sLoc)));
- } else {
- // XXX what does this state mean?
- // We have incorrectly identified what is the top most
- // implementor and its not because
- // a type wasn't exposed to the weaver
- }
- return false;
- } else {
-
- ResolvedMember mangledInterMethod = AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, false);
-
- LazyMethodGen mg = makeMethodGen(classGen, mangledInterMethod);
-
- // From 98901#29 - need to copy annotations across
- if (classWeaver.getWorld().isInJava5Mode()) {
- AnnotationAJ annotationsOnRealMember[] = null;
- ResolvedType toLookOn = aspectType;
- if (aspectType.isRawType()) {
- toLookOn = aspectType.getGenericType();
- }
- ResolvedMember realMember = getRealMemberForITDFromAspect(toLookOn, memberHoldingAnyAnnotations, false);
- if (realMember == null) {
- throw new BCException("Couldn't find ITD holder member '" + memberHoldingAnyAnnotations + "' on aspect "
- + aspectType);
- }
- annotationsOnRealMember = realMember.getAnnotations();
-
- if (annotationsOnRealMember != null) {
- for (AnnotationAJ annotationX : annotationsOnRealMember) {
- AnnotationGen a = ((BcelAnnotation) annotationX).getBcelAnnotation();
- AnnotationGen ag = new AnnotationGen(a, classWeaver.getLazyClassGen().getConstantPool(), true);
- mg.addAnnotation(new BcelAnnotation(ag, classWeaver.getWorld()));
- }
- }
-
- copyOverParameterAnnotations(mg, realMember);
- }
-
- if (mungingInterface) {
- // we want the modifiers of the ITD to be used for all
- // *implementors* of the
- // interface, but the method itself we add to the interface
- // must be public abstract
- mg.setAccessFlags(Modifier.PUBLIC | Modifier.ABSTRACT);
- }
-
- Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes());
- Type returnType = BcelWorld.makeBcelType(mangledInterMethod.getReturnType());
-
- InstructionList body = mg.getBody();
- InstructionFactory fact = classGen.getFactory();
- int pos = 0;
-
- if (!Modifier.isStatic(mangledInterMethod.getModifiers())) {
- body.append(InstructionFactory.createThis());
- pos++;
- }
- for (int i = 0, len = paramTypes.length; i < len; i++) {
- Type paramType = paramTypes[i];
- body.append(InstructionFactory.createLoad(paramType, pos));
- pos += paramType.getSize();
- }
-
- body.append(Utility.createInvoke(fact, classWeaver.getWorld(), interMethodBody));
- Type t = BcelWorld.makeBcelType(interMethodBody.getReturnType());
- if (!t.equals(returnType)) {
- body.append(fact.createCast(t, returnType));
- }
- body.append(InstructionFactory.createReturn(returnType));
- mg.definingType = onType;
-
- if (world.isInJava5Mode()) {
- String basicSignature = mangledInterMethod.getSignature();
- String genericSignature = ((ResolvedMemberImpl) mangledInterMethod).getSignatureForAttribute();
- if (!basicSignature.equals(genericSignature)) {
- // Add a signature attribute to it
- mg.addAttribute(createSignatureAttribute(classGen.getConstantPool(), genericSignature));
- }
- }
-
- classWeaver.addOrReplaceLazyMethodGen(mg);
-
- addNeededSuperCallMethods(classWeaver, onType, munger.getSuperMethodsCalled());
-
- // Work out if we need a bridge method for the new method added to the topmostimplementor.
-
- // Check if the munger being processed is a parameterized form of the original munger
- createBridgeIfNecessary(classWeaver, munger, unMangledInterMethod, classGen);
-
- return true;
- }
- } else {
- return false;
- }
- }
-
- private void createBridgeIfNecessary(BcelClassWeaver classWeaver, NewMethodTypeMunger munger,
- ResolvedMember unMangledInterMethod, LazyClassGen classGen) {
- if (munger.getDeclaredSignature() != null) {
- boolean needsbridging = false;
- ResolvedMember mungerSignature = munger.getSignature();
- ResolvedMember toBridgeTo = munger.getDeclaredSignature().parameterizedWith(null,
- mungerSignature.getDeclaringType().resolve(getWorld()), false, munger.getTypeVariableAliases());
- if (!toBridgeTo.getReturnType().getErasureSignature().equals(mungerSignature.getReturnType().getErasureSignature())) {
- needsbridging = true;
- }
- UnresolvedType[] originalParams = toBridgeTo.getParameterTypes();
- UnresolvedType[] newParams = mungerSignature.getParameterTypes();
- for (int ii = 0; ii < originalParams.length; ii++) {
- if (!originalParams[ii].getErasureSignature().equals(newParams[ii].getErasureSignature())) {
- needsbridging = true;
- }
- }
- if (needsbridging) {
- createBridge(classWeaver, unMangledInterMethod, classGen, toBridgeTo);
- }
- }
- }
-
- private void copyOverParameterAnnotations(LazyMethodGen receiverMethod, ResolvedMember donorMethod) {
- AnnotationAJ[][] pAnnos = donorMethod.getParameterAnnotations();
- if (pAnnos != null) {
- int offset = receiverMethod.isStatic() ? 0 : 1;
- int param = 0;
- for (int i = offset; i < pAnnos.length; i++) {
- AnnotationAJ[] annosOnParam = pAnnos[i];
- if (annosOnParam != null) {
- for (AnnotationAJ anno : annosOnParam) {
- receiverMethod.addParameterAnnotation(param, anno);
- }
- }
- param++;
- }
- }
- }
-
- private void createBridge(BcelClassWeaver weaver, ResolvedMember unMangledInterMethod, LazyClassGen classGen,
- ResolvedMember toBridgeTo) {
- Type[] paramTypes;
- Type returnType;
- InstructionList body;
- InstructionFactory fact;
- int pos;
- ResolvedMember bridgerMethod = AjcMemberMaker.bridgerToInterMethod(unMangledInterMethod, classGen.getType());
- ResolvedMember bridgingSetter = AjcMemberMaker.interMethodBridger(toBridgeTo, aspectType, false); // pr250493
-
- LazyMethodGen bridgeMethod = makeMethodGen(classGen, bridgingSetter);
- paramTypes = BcelWorld.makeBcelTypes(bridgingSetter.getParameterTypes());
- Type[] bridgingToParms = BcelWorld.makeBcelTypes(unMangledInterMethod.getParameterTypes());
- returnType = BcelWorld.makeBcelType(bridgingSetter.getReturnType());
- body = bridgeMethod.getBody();
- fact = classGen.getFactory();
- pos = 0;
- if (!Modifier.isStatic(bridgingSetter.getModifiers())) {
- body.append(InstructionFactory.createThis());
- pos++;
- }
- for (int i = 0, len = paramTypes.length; i < len; i++) {
- Type paramType = paramTypes[i];
- body.append(InstructionFactory.createLoad(paramType, pos));
- if (!bridgingSetter.getParameterTypes()[i].getErasureSignature().equals(
- unMangledInterMethod.getParameterTypes()[i].getErasureSignature())) {
- // System.err.println("Putting in cast from "+
- // paramType+" to "+bridgingToParms[i]);
- body.append(fact.createCast(paramType, bridgingToParms[i]));
- }
- pos += paramType.getSize();
- }
-
- body.append(Utility.createInvoke(fact, weaver.getWorld(), bridgerMethod));
- body.append(InstructionFactory.createReturn(returnType));
- classGen.addMethodGen(bridgeMethod);
- // mg.definingType = onType;
- }
-
- /**
- * Helper method to create a signature attribute based on a string signature: e.g. "Ljava/lang/Object;LI<Ljava/lang/Double;>;"
- */
- private Signature createSignatureAttribute(ConstantPool cp, String signature) {
- int nameIndex = cp.addUtf8("Signature");
- int sigIndex = cp.addUtf8(signature);
- return new Signature(nameIndex, 2, sigIndex, cp);
- }
-
- /**
- * Create any bridge method required because of covariant returns being used. This method is used in the case where an ITD is
- * applied to some type and it may be in an override relationship with a method from the supertype - but due to covariance there
- * is a mismatch in return values. Example of when required: Super defines: Object m(String s) Sub defines: String m(String s)
- * then we need a bridge method in Sub called 'Object m(String s)' that forwards to 'String m(String s)'
- */
- private void createAnyBridgeMethodsForCovariance(BcelClassWeaver weaver, NewMethodTypeMunger munger,
- ResolvedMember unMangledInterMethod, ResolvedType onType, LazyClassGen gen, Type[] paramTypes) {
- // PERFORMANCE BOTTLENECK? Might need investigating, method analysis
- // between types in a hierarchy just seems expensive...
- // COVARIANCE BRIDGING
- // Algorithm: Step1. Check in this type - has someone already created
- // the bridge method?
- // Step2. Look above us - do we 'override' a method and yet differ in
- // return type (i.e. covariance)
- // Step3. Create a forwarding bridge method
- // ResolvedType superclass = onType.getSuperclass();
- boolean quitRightNow = false;
-
- String localMethodName = unMangledInterMethod.getName();
- String erasedSig = unMangledInterMethod.getSignatureErased(); // will be something like (LSuperB;)LFoo;
- String localParameterSig = erasedSig.substring(0,erasedSig.lastIndexOf(')')+1);//unMangledInterMethod.getParameterSignature();
- // getParameterSignatureErased() does not include parens, which we do need.
- String localReturnTypeESig = unMangledInterMethod.getReturnType().getErasureSignature();
-
- // Step1
- boolean alreadyDone = false; // Compiler might have done it
- ResolvedMember[] localMethods = onType.getDeclaredMethods();
- for (int i = 0; i < localMethods.length; i++) {
- ResolvedMember member = localMethods[i];
- if (member.getName().equals(localMethodName)) {
- // Check the params
- if (member.getParameterSignature().equals(localParameterSig)) {
- alreadyDone = true;
- }
- }
- }
-
- // Step2
- if (!alreadyDone) {
- // Use the iterator form of 'getMethods()' so we do as little work as necessary
- ResolvedType supertype = onType.getSuperclass();
- if (supertype != null) {
- for (Iterator<ResolvedMember> iter = supertype.getMethods(true, true); iter.hasNext() && !quitRightNow;) {
- ResolvedMember aMethod = iter.next();
- if (aMethod.getName().equals(localMethodName) && aMethod.getParameterSignature().equals(localParameterSig)) {
- // check the return types, if they are different we need a
- // bridging method.
- if (!aMethod.getReturnType().getErasureSignature().equals(localReturnTypeESig)
- && !Modifier.isPrivate(aMethod.getModifiers())) {
- // Step3
- createBridgeMethod(weaver.getWorld(), munger, unMangledInterMethod, gen, paramTypes, aMethod);
- quitRightNow = true;
- }
- }
- }
- }
- }
- }
-
- /**
- * Create a bridge method for a particular munger.
- *
- * @param world
- * @param munger
- * @param unMangledInterMethod the method to bridge 'to' that we have already created in the 'subtype'
- * @param clazz the class in which to put the bridge method
- * @param paramTypes Parameter types for the bridge method, passed in as an optimization since the caller is likely to have
- * already created them.
- * @param theBridgeMethod
- */
- private void createBridgeMethod(BcelWorld world, NewMethodTypeMunger munger, ResolvedMember unMangledInterMethod,
- LazyClassGen clazz, Type[] paramTypes, ResolvedMember theBridgeMethod) {
- InstructionList body;
- InstructionFactory fact;
- int pos = 0;
-
- // The bridge method in this type will have the same signature as the one in the supertype
- LazyMethodGen bridgeMethod = makeMethodGen(clazz, theBridgeMethod);
- bridgeMethod.setAccessFlags(bridgeMethod.getAccessFlags() | 0x00000040 /* BRIDGE = 0x00000040 */);
- // UnresolvedType[] newParams = munger.getSignature().getParameterTypes();
- Type returnType = BcelWorld.makeBcelType(theBridgeMethod.getReturnType());
- body = bridgeMethod.getBody();
- fact = clazz.getFactory();
-
- if (!Modifier.isStatic(unMangledInterMethod.getModifiers())) {
- body.append(InstructionFactory.createThis());
- pos++;
- }
- for (int i = 0, len = paramTypes.length; i < len; i++) {
- Type paramType = paramTypes[i];
- body.append(InstructionFactory.createLoad(paramType, pos));
- // if (!bridgingSetter.getParameterTypes()[i].getErasureSignature().
- // equals
- // (unMangledInterMethod.getParameterTypes()[i].getErasureSignature
- // ())) {
- // System.err.println("Putting in cast from "+paramType+" to "+
- // bridgingToParms[i]);
- // body.append(fact.createCast(paramType,bridgingToParms[i]));
- // }
- pos += paramType.getSize();
- }
-
- body.append(Utility.createInvoke(fact, world, unMangledInterMethod));
- body.append(InstructionFactory.createReturn(returnType));
- 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) {
- World world = weaver.getWorld();
-
- LazyClassGen gen = weaver.getLazyClassGen();
- if (gen.getType().isAnnotation() || gen.getType().isEnum()) {
- // don't signal error as it could be a consequence of a wild type pattern
- return false;
- }
-
- ResolvedMember introduced = munger.getSignature();
-
- ResolvedType fromType = world.resolve(introduced.getDeclaringType(), munger.getSourceLocation());
- if (fromType.isRawType()) {
- fromType = fromType.getGenericType();
- }
-
- boolean shouldApply = munger.matches(weaver.getLazyClassGen().getType(), aspectType);
-
- if (shouldApply) {
- Type bcelReturnType = BcelWorld.makeBcelType(introduced.getReturnType());
-
- // 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 && !munger.specifiesDelegateFactoryMethod()) {
- boolean isOK = false;
- List<LazyMethodGen> existingMethods = gen.getMethodGens();
- for (LazyMethodGen m : existingMethods) {
- if (m.getName().equals(introduced.getName())
- && m.getParameterSignature().equals(introduced.getParameterSignature())
- && m.getReturnType().equals(bcelReturnType)) {
- 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, bcelReturnType,
- introduced.getName(), BcelWorld.makeBcelTypes(introduced.getParameterTypes()),
- BcelWorld.makeBcelTypesAsClassNames(introduced.getExceptions()), gen);
-
- // annotation copy from annotation on ITD interface
- if (weaver.getWorld().isInJava5Mode()) {
- AnnotationAJ annotationsOnRealMember[] = null;
- ResolvedType toLookOn = weaver.getWorld().lookupOrCreateName(introduced.getDeclaringType());
- if (fromType.isRawType()) {
- toLookOn = fromType.getGenericType();
- }
- // lookup the method
- ResolvedMember[] ms = toLookOn.getDeclaredJavaMethods();
- for (ResolvedMember m : ms) {
- if (introduced.getName().equals(m.getName()) && introduced.getSignature().equals(m.getSignature())) {
- annotationsOnRealMember = m.getAnnotations();
- break;
- }
- }
- if (annotationsOnRealMember != null) {
- for (AnnotationAJ anno : annotationsOnRealMember) {
- AnnotationGen a = ((BcelAnnotation) anno).getBcelAnnotation();
- AnnotationGen ag = new AnnotationGen(a, weaver.getLazyClassGen().getConstantPool(), true);
- mg.addAnnotation(new BcelAnnotation(ag, weaver.getWorld()));
- }
- }
- }
-
- InstructionList body = new InstructionList();
- InstructionFactory fact = gen.getFactory();
-
- // getfield
- body.append(InstructionConstants.ALOAD_0);
- body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
- InstructionBranch ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
- body.append(ifNonNull);
-
- // Create and store a new instance
- body.append(InstructionConstants.ALOAD_0); // 'this' is where we'll store the field value
-
- // TODO for non-static case, call aspectOf() then call the factory method on the retval
- // TODO decide whether the value can really be cached
-
- // locate the aspect and call the static method in it
- if (munger.specifiesDelegateFactoryMethod()) {
- ResolvedMember rm = munger.getDelegateFactoryMethod(weaver.getWorld());
-
- // Check the method parameter is compatible with the type of the instance to be passed
- if (rm.getArity() != 0) {
- ResolvedType parameterType = rm.getParameterTypes()[0].resolve(weaver.getWorld());
- if (!parameterType.isAssignableFrom(weaver.getLazyClassGen().getType())) {
- signalError("For mixin factory method '" + rm + "': Instance type '" + weaver.getLazyClassGen().getType()
- + "' is not compatible with factory parameter type '" + parameterType + "'", weaver);
- return false;
- }
- }
- if (Modifier.isStatic(rm.getModifiers())) {
- if (rm.getArity() != 0) {
- body.append(InstructionConstants.ALOAD_0);
- }
- body.append(fact.createInvoke(rm.getDeclaringType().getName(), rm.getName(), rm.getSignature(),
- Constants.INVOKESTATIC));
- body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
- } else {
- // Need to call aspectOf() to obtain the aspect instance then call the factory method upon that
- UnresolvedType theAspect = munger.getAspect();
- body.append(fact.createInvoke(theAspect.getName(), "aspectOf", "()" + theAspect.getSignature(),
- Constants.INVOKESTATIC));
- if (rm.getArity() != 0) {
- body.append(InstructionConstants.ALOAD_0);
- }
- body.append(fact.createInvoke(rm.getDeclaringType().getName(), rm.getName(), rm.getSignature(),
- Constants.INVOKEVIRTUAL));
- body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
- }
- } else {
- body.append(fact.createNew(munger.getImplClassName()));
- body.append(InstructionConstants.DUP);
- body.append(fact.createInvoke(munger.getImplClassName(), "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
- body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
- }
-
- // if not null use the instance we've got
- InstructionHandle ifNonNullElse = body.append(InstructionConstants.ALOAD_0);
- ifNonNull.setTarget(ifNonNullElse);
- body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
-
- // args
- int pos = 0;
- if (!Modifier.isStatic(introduced.getModifiers())) { // skip 'this' (?? can this really
- // happen)
- // body.append(InstructionFactory.createThis());
- pos++;
- }
- Type[] paramTypes = BcelWorld.makeBcelTypes(introduced.getParameterTypes());
- for (int i = 0, len = paramTypes.length; i < len; i++) {
- Type paramType = paramTypes[i];
- body.append(InstructionFactory.createLoad(paramType, pos));
- pos += paramType.getSize();
- }
- body.append(Utility.createInvoke(fact, Constants.INVOKEINTERFACE, introduced));
- body.append(InstructionFactory.createReturn(bcelReturnType));
-
- mg.getBody().append(body);
- weaver.addLazyMethodGen(mg);
- weaver.getLazyClassGen().warnOnAddedMethod(mg.getMethod(), getSignature().getSourceLocation());
- return true;
- }
- return false;
- }
-
- private boolean mungeFieldHost(BcelClassWeaver weaver, MethodDelegateTypeMunger.FieldHostTypeMunger munger) {
- LazyClassGen gen = weaver.getLazyClassGen();
- if (gen.getType().isAnnotation() || gen.getType().isEnum()) {
- // don't signal error as it could be a consequence of a wild type
- // pattern
- return false;
- }
- // boolean shouldApply =
- munger.matches(weaver.getLazyClassGen().getType(), aspectType); // why
- // do
- // this?
- ResolvedMember host = AjcMemberMaker.itdAtDeclareParentsField(weaver.getLazyClassGen().getType(), munger.getSignature()
- .getType(), aspectType);
- FieldGen field = makeFieldGen(weaver.getLazyClassGen(), host);
- field.setModifiers(field.getModifiers() | BcelField.AccSynthetic);
- weaver.getLazyClassGen().addField(field, null);
- return true;
- }
-
- private ResolvedMember getRealMemberForITDFromAspect(ResolvedType aspectType, ResolvedMember lookingFor, boolean isCtorRelated) {
- World world = aspectType.getWorld();
- boolean debug = false;
- if (debug) {
- System.err.println("Searching for a member on type: " + aspectType);
- System.err.println("Member we are looking for: " + lookingFor);
- }
-
- ResolvedMember aspectMethods[] = aspectType.getDeclaredMethods();
- UnresolvedType[] lookingForParams = lookingFor.getParameterTypes();
-
- ResolvedMember realMember = null;
- for (int i = 0; realMember == null && i < aspectMethods.length; i++) {
- ResolvedMember member = aspectMethods[i];
- if (member.getName().equals(lookingFor.getName())) {
- UnresolvedType[] memberParams = member.getGenericParameterTypes();
- if (memberParams.length == lookingForParams.length) {
- if (debug) {
- System.err.println("Reviewing potential candidates: " + member);
- }
- boolean matchOK = true;
- // If not related to a ctor ITD then the name is enough to
- // confirm we have the
- // right one. If it is ctor related we need to check the
- // params all match, although
- // only the erasure.
- if (isCtorRelated) {
- for (int j = 0; j < memberParams.length && matchOK; j++) {
- ResolvedType pMember = memberParams[j].resolve(world);
- ResolvedType pLookingFor = lookingForParams[j].resolve(world);
-
- if (pMember.isTypeVariableReference()) {
- pMember = ((TypeVariableReference) pMember).getTypeVariable().getFirstBound().resolve(world);
- }
- if (pMember.isParameterizedType() || pMember.isGenericType()) {
- pMember = pMember.getRawType().resolve(aspectType.getWorld());
- }
-
- if (pLookingFor.isTypeVariableReference()) {
- pLookingFor = ((TypeVariableReference) pLookingFor).getTypeVariable().getFirstBound()
- .resolve(world);
- }
- if (pLookingFor.isParameterizedType() || pLookingFor.isGenericType()) {
- pLookingFor = pLookingFor.getRawType().resolve(world);
- }
-
- if (debug) {
- System.err.println("Comparing parameter " + j + " member=" + pMember + " lookingFor="
- + pLookingFor);
- }
- if (!pMember.equals(pLookingFor)) {
- matchOK = false;
- }
- }
- }
- if (matchOK) {
- realMember = member;
- }
- }
- }
- }
- if (debug && realMember == null) {
- System.err.println("Didn't find a match");
- }
- return realMember;
- }
-
- private void addNeededSuperCallMethods(BcelClassWeaver weaver, ResolvedType onType, Set<ResolvedMember> neededSuperCalls) {
- LazyClassGen gen = weaver.getLazyClassGen();
- for (ResolvedMember superMethod: neededSuperCalls) {
- if (weaver.addDispatchTarget(superMethod)) {
- // System.err.println("super type: " + superMethod.getDeclaringType() + ", " + gen.getType());
- boolean isSuper = !superMethod.getDeclaringType().equals(gen.getType());
- String dispatchName;
- if (isSuper) {
- dispatchName = NameMangler.superDispatchMethod(onType, superMethod.getName());
- } else {
- dispatchName = NameMangler.protectedDispatchMethod(onType, superMethod.getName());
- }
- superMethod = superMethod.resolve(weaver.getWorld());
- LazyMethodGen dispatcher = makeDispatcher(gen, dispatchName, superMethod, weaver.getWorld(), isSuper);
- weaver.addLazyMethodGen(dispatcher);
- }
- }
- }
-
- private void signalError(String msgid, BcelClassWeaver weaver, UnresolvedType onType) {
- IMessage msg = MessageUtil.error(WeaverMessages.format(msgid, onType.getName()), getSourceLocation());
- weaver.getWorld().getMessageHandler().handleMessage(msg);
- }
-
- // private void signalWarning(String msgString, BcelClassWeaver weaver) {
- // IMessage msg = MessageUtil.warn(msgString, getSourceLocation());
- // weaver.getWorld().getMessageHandler().handleMessage(msg);
- // }
-
- private void signalError(String msgString, BcelClassWeaver weaver) {
- IMessage msg = MessageUtil.error(msgString, getSourceLocation());
- weaver.getWorld().getMessageHandler().handleMessage(msg);
- }
-
- private boolean mungeNewConstructor(BcelClassWeaver weaver, NewConstructorTypeMunger newConstructorTypeMunger) {
-
- final LazyClassGen currentClass = weaver.getLazyClassGen();
- final InstructionFactory fact = currentClass.getFactory();
-
- ResolvedMember newConstructorMember = newConstructorTypeMunger.getSyntheticConstructor();
- ResolvedType onType = newConstructorMember.getDeclaringType().resolve(weaver.getWorld());
- if (onType.isRawType()) {
- onType = onType.getGenericType();
- }
-
- if (onType.isAnnotation()) {
- signalError(WeaverMessages.ITDC_ON_ANNOTATION_NOT_ALLOWED, weaver, onType);
- return false;
- }
-
- if (onType.isEnum()) {
- signalError(WeaverMessages.ITDC_ON_ENUM_NOT_ALLOWED, weaver, onType);
- return false;
- }
-
- if (!onType.equals(currentClass.getType())) {
- return false;
- }
-
- ResolvedMember explicitConstructor = newConstructorTypeMunger.getExplicitConstructor();
- // int declaredParameterCount =
- // newConstructorTypeMunger.getDeclaredParameterCount();
- LazyMethodGen mg = makeMethodGen(currentClass, newConstructorMember);
- mg.setEffectiveSignature(newConstructorTypeMunger.getSignature(), Shadow.ConstructorExecution, true);
-
- // pr98901
- // For copying the annotations across, we have to discover the real
- // member in the aspect
- // which is holding them.
- if (weaver.getWorld().isInJava5Mode()) {
-
- ResolvedMember interMethodDispatcher = AjcMemberMaker.postIntroducedConstructor(aspectType, onType,
- newConstructorTypeMunger.getSignature().getParameterTypes());
- AnnotationAJ annotationsOnRealMember[] = null;
- ResolvedMember realMember = getRealMemberForITDFromAspect(aspectType, interMethodDispatcher, true);
- // 266602 - consider it missing to mean that the corresponding aspect had errors
- if (realMember == null) {
- // signalWarning("Unable to apply any annotations attached to " + munger.getSignature(), weaver);
- // throw new BCException("Couldn't find ITD init member '" + interMethodBody + "' on aspect " + aspectType);
- } else {
- annotationsOnRealMember = realMember.getAnnotations();
- }
- if (annotationsOnRealMember != null) {
- for (int i = 0; i < annotationsOnRealMember.length; i++) {
- AnnotationAJ annotationX = annotationsOnRealMember[i];
- AnnotationGen a = ((BcelAnnotation) annotationX).getBcelAnnotation();
- AnnotationGen ag = new AnnotationGen(a, weaver.getLazyClassGen().getConstantPool(), true);
- mg.addAnnotation(new BcelAnnotation(ag, weaver.getWorld()));
- }
- }
- // the below loop fixes the very special (and very stupid)
- // case where an aspect declares an annotation
- // on an ITD it declared on itself.
- List<DeclareAnnotation> allDecams = weaver.getWorld().getDeclareAnnotationOnMethods();
- for (Iterator<DeclareAnnotation> i = allDecams.iterator(); i.hasNext();) {
- DeclareAnnotation decaMC = i.next();
- if (decaMC.matches(explicitConstructor, weaver.getWorld()) && mg.getEnclosingClass().getType() == aspectType) {
- mg.addAnnotation(decaMC.getAnnotation());
- }
- }
- }
-
- // Might have to remove the default constructor - b275032
- // TODO could have tagged the type munger when the fact we needed to do this was detected earlier
- if (mg.getArgumentTypes().length == 0) {
- LazyMethodGen toRemove = null;
- for (LazyMethodGen object : currentClass.getMethodGens()) {
- if (object.getName().equals("<init>") && object.getArgumentTypes().length == 0) {
- toRemove = object;
- }
- }
- if (toRemove != null) {
- currentClass.removeMethodGen(toRemove);
- }
- }
-
- currentClass.addMethodGen(mg);
- // weaver.addLazyMethodGen(freshConstructor);
-
- InstructionList body = mg.getBody();
-
- // add to body: push arts for call to pre, from actual args starting at
- // 1 (skipping this), going to
- // declared argcount + 1
- UnresolvedType[] declaredParams = newConstructorTypeMunger.getSignature().getParameterTypes();
- Type[] paramTypes = mg.getArgumentTypes();
- int frameIndex = 1;
- for (int i = 0, len = declaredParams.length; i < len; i++) {
- body.append(InstructionFactory.createLoad(paramTypes[i], frameIndex));
- frameIndex += paramTypes[i].getSize();
- }
- // do call to pre
- Member preMethod = AjcMemberMaker.preIntroducedConstructor(aspectType, onType, declaredParams);
- body.append(Utility.createInvoke(fact, null, preMethod));
-
- // create a local, and store return pre stuff into it.
- int arraySlot = mg.allocateLocal(1);
- body.append(InstructionFactory.createStore(Type.OBJECT, arraySlot));
-
- // put this on the stack
- body.append(InstructionConstants.ALOAD_0);
-
- // unpack pre args onto stack
- UnresolvedType[] superParamTypes = explicitConstructor.getParameterTypes();
-
- for (int i = 0, len = superParamTypes.length; i < len; i++) {
- body.append(InstructionFactory.createLoad(Type.OBJECT, arraySlot));
- body.append(Utility.createConstant(fact, i));
- body.append(InstructionFactory.createArrayLoad(Type.OBJECT));
- body.append(Utility.createConversion(fact, Type.OBJECT, BcelWorld.makeBcelType(superParamTypes[i])));
- }
-
- // call super/this
-
- body.append(Utility.createInvoke(fact, null, explicitConstructor));
-
- // put this back on the stack
-
- body.append(InstructionConstants.ALOAD_0);
-
- // unpack params onto stack
- Member postMethod = AjcMemberMaker.postIntroducedConstructor(aspectType, onType, declaredParams);
- UnresolvedType[] postParamTypes = postMethod.getParameterTypes();
-
- for (int i = 1, len = postParamTypes.length; i < len; i++) {
- body.append(InstructionFactory.createLoad(Type.OBJECT, arraySlot));
- body.append(Utility.createConstant(fact, superParamTypes.length + i - 1));
- body.append(InstructionFactory.createArrayLoad(Type.OBJECT));
- body.append(Utility.createConversion(fact, Type.OBJECT, BcelWorld.makeBcelType(postParamTypes[i])));
- }
-
- // call post
- body.append(Utility.createInvoke(fact, null, postMethod));
-
- // don't forget to return!!
- body.append(InstructionConstants.RETURN);
-
- addNeededSuperCallMethods(weaver, onType, munger.getSuperMethodsCalled());
-
- return true;
- }
-
- private static LazyMethodGen makeDispatcher(LazyClassGen onGen, String dispatchName, ResolvedMember superMethod,
- BcelWorld world, boolean isSuper) {
- Type[] paramTypes = BcelWorld.makeBcelTypes(superMethod.getParameterTypes());
- Type returnType = BcelWorld.makeBcelType(superMethod.getReturnType());
-
- int modifiers = Modifier.PUBLIC;
- if (onGen.isInterface()) {
- modifiers |= Modifier.ABSTRACT;
- }
-
- LazyMethodGen mg = new LazyMethodGen(modifiers, returnType, dispatchName, paramTypes, UnresolvedType.getNames(superMethod
- .getExceptions()), onGen);
- InstructionList body = mg.getBody();
-
- if (onGen.isInterface()) {
- return mg;
- }
-
- // assert (!superMethod.isStatic())
- InstructionFactory fact = onGen.getFactory();
- int pos = 0;
-
- body.append(InstructionFactory.createThis());
- pos++;
- for (int i = 0, len = paramTypes.length; i < len; i++) {
- Type paramType = paramTypes[i];
- body.append(InstructionFactory.createLoad(paramType, pos));
- pos += paramType.getSize();
- }
- if (isSuper) {
- body.append(Utility.createSuperInvoke(fact, world, superMethod));
- } else {
- body.append(Utility.createInvoke(fact, world, superMethod));
- }
- body.append(InstructionFactory.createReturn(returnType));
-
- return mg;
- }
-
- private boolean mungeNewField(BcelClassWeaver weaver, NewFieldTypeMunger munger) {
- /* ResolvedMember initMethod = */munger.getInitMethod(aspectType);
- LazyClassGen gen = weaver.getLazyClassGen();
- ResolvedMember field = munger.getSignature();
-
- ResolvedType onType = weaver.getWorld().resolve(field.getDeclaringType(), munger.getSourceLocation());
- if (onType.isRawType()) {
- onType = onType.getGenericType();
- }
-
- boolean onInterface = onType.isInterface();
-
- if (onType.isAnnotation()) {
- signalError(WeaverMessages.ITDF_ON_ANNOTATION_NOT_ALLOWED, weaver, onType);
- return false;
- }
-
- if (onType.isEnum()) {
- signalError(WeaverMessages.ITDF_ON_ENUM_NOT_ALLOWED, weaver, onType);
- return false;
- }
-
- ResolvedMember interMethodBody = munger.getInitMethod(aspectType);
-
- AnnotationAJ annotationsOnRealMember[] = null;
- // pr98901
- // For copying the annotations across, we have to discover the real
- // member in the aspect
- // which is holding them.
- if (weaver.getWorld().isInJava5Mode()) {
- // the below line just gets the method with the same name in
- // aspectType.getDeclaredMethods();
- ResolvedType toLookOn = aspectType;
- if (aspectType.isRawType()) {
- toLookOn = aspectType.getGenericType();
- }
- ResolvedMember realMember = getRealMemberForITDFromAspect(toLookOn, interMethodBody, false);
- if (realMember == null) {
- // signalWarning("Unable to apply any annotations attached to " + munger.getSignature(), weaver);
- // throw new BCException("Couldn't find ITD init member '" + interMethodBody + "' on aspect " + aspectType);
- } else {
- annotationsOnRealMember = realMember.getAnnotations();
- }
- }
-
- if (onType.equals(gen.getType())) {
- if (onInterface) {
- ResolvedMember itdfieldGetter = AjcMemberMaker.interFieldInterfaceGetter(field, onType, aspectType);
- LazyMethodGen mg = makeMethodGen(gen, itdfieldGetter);
- gen.addMethodGen(mg);
-
- LazyMethodGen mg1 = makeMethodGen(gen, AjcMemberMaker.interFieldInterfaceSetter(field, onType, aspectType));
- gen.addMethodGen(mg1);
- } else {
- weaver.addInitializer(this);
- ResolvedMember newField = AjcMemberMaker.interFieldClassField(field, aspectType,
- munger.version == NewFieldTypeMunger.VersionTwo);
- FieldGen fg = makeFieldGen(gen, newField);
-
- if (annotationsOnRealMember != null) {
- for (int i = 0; i < annotationsOnRealMember.length; i++) {
- AnnotationAJ annotationX = annotationsOnRealMember[i];
- AnnotationGen a = ((BcelAnnotation) annotationX).getBcelAnnotation();
- AnnotationGen ag = new AnnotationGen(a, weaver.getLazyClassGen().getConstantPool(), true);
- fg.addAnnotation(ag);
- }
- }
-
- if (weaver.getWorld().isInJava5Mode()) {
- String basicSignature = field.getSignature();
- String genericSignature = field.getReturnType().resolve(weaver.getWorld()).getSignatureForAttribute();
- // String genericSignature =
- // ((ResolvedMemberImpl)field).getSignatureForAttribute();
- if (!basicSignature.equals(genericSignature)) {
- // Add a signature attribute to it
- fg.addAttribute(createSignatureAttribute(gen.getConstantPool(), genericSignature));
- }
- }
- gen.addField(fg, getSourceLocation());
-
- }
- return true;
- } else if (onInterface && gen.getType().isTopmostImplementor(onType)) {
- // we know that we can't be static since we don't allow statics on interfaces
- if (Modifier.isStatic(field.getModifiers())) {
- throw new RuntimeException("unimplemented");
- }
-
- boolean alreadyExists = false;
- // only need to check for version 2 style mungers
- if (munger.version==NewFieldTypeMunger.VersionTwo) {
- for (BcelField fieldgen: gen.getFieldGens()) {
- if (fieldgen.getName().equals(field.getName())) {
- alreadyExists=true;
- break;
- }
- }
- }
-
- // FieldGen fg = makeFieldGen(gen, AjcMemberMaker.interFieldInterfaceField(field, onType, aspectType));
- ResolvedMember newField = AjcMemberMaker.interFieldInterfaceField(field, onType, aspectType, munger.version == NewFieldTypeMunger.VersionTwo);
- String fieldName = newField.getName();
-
- Type fieldType = BcelWorld.makeBcelType(field.getType());
- if (!alreadyExists) {
- weaver.addInitializer(this);
- FieldGen fg = makeFieldGen(gen,newField);
- if (annotationsOnRealMember != null) {
- for (int i = 0; i < annotationsOnRealMember.length; i++) {
- AnnotationAJ annotationX = annotationsOnRealMember[i];
- AnnotationGen a = ((BcelAnnotation) annotationX).getBcelAnnotation();
- AnnotationGen ag = new AnnotationGen(a, weaver.getLazyClassGen().getConstantPool(), true);
- fg.addAnnotation(ag);
- }
- }
-
- if (weaver.getWorld().isInJava5Mode()) {
- String basicSignature = field.getSignature();
- String genericSignature = field.getReturnType().resolve(weaver.getWorld()).getSignatureForAttribute();
- // String genericSignature =
- // ((ResolvedMemberImpl)field).getSignatureForAttribute();
- if (!basicSignature.equals(genericSignature)) {
- // Add a signature attribute to it
- fg.addAttribute(createSignatureAttribute(gen.getConstantPool(), genericSignature));
- }
- }
- gen.addField(fg, getSourceLocation());
- }
- // this uses a shadow munger to add init method to constructors
- // weaver.getShadowMungers().add(makeInitCallShadowMunger(initMethod)
- // );
-
- ResolvedMember itdfieldGetter = AjcMemberMaker.interFieldInterfaceGetter(field, gen.getType()/* onType */, aspectType);
- LazyMethodGen mg = makeMethodGen(gen, itdfieldGetter);
- InstructionList il = new InstructionList();
- InstructionFactory fact = gen.getFactory();
- if (Modifier.isStatic(field.getModifiers())) {
- il.append(fact.createFieldAccess(gen.getClassName(), fieldName, fieldType, Constants.GETSTATIC));
- } else {
- il.append(InstructionConstants.ALOAD_0);
- il.append(fact.createFieldAccess(gen.getClassName(), fieldName, fieldType, Constants.GETFIELD));
- }
- il.append(InstructionFactory.createReturn(fieldType));
- mg.getBody().insert(il);
-
- gen.addMethodGen(mg);
-
- // Check if we need bridge methods for the field getter and setter
- if (munger.getDeclaredSignature() != null) { // is this munger a
- // parameterized
- // form of some
- // original munger?
- ResolvedMember toBridgeTo = munger.getDeclaredSignature().parameterizedWith(null,
- munger.getSignature().getDeclaringType().resolve(getWorld()), false, munger.getTypeVariableAliases());
- boolean needsbridging = false;
- if (!toBridgeTo.getReturnType().getErasureSignature()
- .equals(munger.getSignature().getReturnType().getErasureSignature())) {
- needsbridging = true;
- }
- if (needsbridging) {
- ResolvedMember bridgingGetter = AjcMemberMaker.interFieldInterfaceGetter(toBridgeTo, gen.getType(), aspectType);
- createBridgeMethodForITDF(weaver, gen, itdfieldGetter, bridgingGetter);
- }
- }
-
- ResolvedMember itdfieldSetter = AjcMemberMaker.interFieldInterfaceSetter(field, gen.getType(), aspectType);
- LazyMethodGen mg1 = makeMethodGen(gen, itdfieldSetter);
- InstructionList il1 = new InstructionList();
- if (Modifier.isStatic(field.getModifiers())) {
- il1.append(InstructionFactory.createLoad(fieldType, 0));
- il1.append(fact.createFieldAccess(gen.getClassName(), fieldName, fieldType, Constants.PUTSTATIC));
- } else {
- il1.append(InstructionConstants.ALOAD_0);
- il1.append(InstructionFactory.createLoad(fieldType, 1));
- il1.append(fact.createFieldAccess(gen.getClassName(), fieldName, fieldType, Constants.PUTFIELD));
- }
- il1.append(InstructionFactory.createReturn(Type.VOID));
- mg1.getBody().insert(il1);
-
- gen.addMethodGen(mg1);
-
- if (munger.getDeclaredSignature() != null) {
- ResolvedMember toBridgeTo = munger.getDeclaredSignature().parameterizedWith(null,
- munger.getSignature().getDeclaringType().resolve(getWorld()), false, munger.getTypeVariableAliases());
- boolean needsbridging = false;
- if (!toBridgeTo.getReturnType().getErasureSignature()
- .equals(munger.getSignature().getReturnType().getErasureSignature())) {
- needsbridging = true;
- }
- if (needsbridging) {
- ResolvedMember bridgingSetter = AjcMemberMaker.interFieldInterfaceSetter(toBridgeTo, gen.getType(), aspectType);
- createBridgeMethodForITDF(weaver, gen, itdfieldSetter, bridgingSetter);
- }
- }
-
- return true;
- } else {
- return false;
- }
- }
-
- // FIXME asc combine with other createBridge.. method in this class, avoid
- // the duplication...
- private void createBridgeMethodForITDF(BcelClassWeaver weaver, LazyClassGen gen, ResolvedMember itdfieldSetter,
- ResolvedMember bridgingSetter) {
- InstructionFactory fact;
- LazyMethodGen bridgeMethod = makeMethodGen(gen, bridgingSetter);
- bridgeMethod.setAccessFlags(bridgeMethod.getAccessFlags() | 0x00000040); // BRIDGE = 0x00000040
- Type[] paramTypes = BcelWorld.makeBcelTypes(bridgingSetter.getParameterTypes());
- Type[] bridgingToParms = BcelWorld.makeBcelTypes(itdfieldSetter.getParameterTypes());
- Type returnType = BcelWorld.makeBcelType(bridgingSetter.getReturnType());
- InstructionList body = bridgeMethod.getBody();
- fact = gen.getFactory();
- int pos = 0;
-
- if (!Modifier.isStatic(bridgingSetter.getModifiers())) {
- body.append(InstructionFactory.createThis());
- pos++;
- }
- for (int i = 0, len = paramTypes.length; i < len; i++) {
- Type paramType = paramTypes[i];
- body.append(InstructionFactory.createLoad(paramType, pos));
- if (!bridgingSetter.getParameterTypes()[i].getErasureSignature().equals(
- itdfieldSetter.getParameterTypes()[i].getErasureSignature())) {
- body.append(fact.createCast(paramType, bridgingToParms[i]));
- }
- pos += paramType.getSize();
- }
-
- body.append(Utility.createInvoke(fact, weaver.getWorld(), itdfieldSetter));
- body.append(InstructionFactory.createReturn(returnType));
- gen.addMethodGen(bridgeMethod);
- }
-
- @Override
- public ConcreteTypeMunger parameterizedFor(ResolvedType target) {
- return new BcelTypeMunger(munger.parameterizedFor(target), aspectType);
- }
-
- @Override
- public ConcreteTypeMunger parameterizeWith(Map<String, UnresolvedType> 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 the strings "A" and "B".
- */
- public List<String> getTypeVariableAliases() {
- return munger.getTypeVariableAliases();
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof BcelTypeMunger)) {
- return false;
- }
- BcelTypeMunger o = (BcelTypeMunger) other;
- return ((o.getMunger() == null) ? (getMunger() == null) : o.getMunger().equals(getMunger()))
- && ((o.getAspectType() == null) ? (getAspectType() == null) : o.getAspectType().equals(getAspectType()));
- // && (AsmManager.getDefault().getHandleProvider().dependsOnLocation() ? ((o.getSourceLocation() == null) ?
- // (getSourceLocation() == null)
- // : o.getSourceLocation().equals(getSourceLocation()))
- // : true); // pr134471 - remove when handles are improved
- // to be independent of location
-
- }
-
- private volatile int hashCode = 0;
-
- @Override
- public int hashCode() {
- if (hashCode == 0) {
- int result = 17;
- result = 37 * result + ((getMunger() == null) ? 0 : getMunger().hashCode());
- result = 37 * result + ((getAspectType() == null) ? 0 : getAspectType().hashCode());
- hashCode = result;
- }
- return hashCode;
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelVar.java b/weaver/src/org/aspectj/weaver/bcel/BcelVar.java
deleted file mode 100644
index ce45fdf12..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelVar.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/* *******************************************************************
- * 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 org.aspectj.apache.bcel.generic.Instruction;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.ast.Var;
-
-public class BcelVar extends Var {
-
- private int positionInAroundState = -1;
-
- private int slot;
-
- public BcelVar(ResolvedType type, int slot) {
- super(type);
- this.slot = slot;
- }
-
- public String toString() {
- return "BcelVar(" + getType() + " " + slot + ((positionInAroundState != -1) ? (" " + positionInAroundState) : "") +
-
- ")";
- }
-
- public int getSlot() {
- return slot;
- }
-
- // fact is used in the subtypes
- public Instruction createLoad(InstructionFactory fact) {
- return InstructionFactory.createLoad(BcelWorld.makeBcelType(getType()), slot);
- }
-
- public Instruction createStore(InstructionFactory fact) {
- return InstructionFactory.createStore(BcelWorld.makeBcelType(getType()), slot);
- }
-
- public void appendStore(InstructionList il, InstructionFactory fact) {
- il.append(createStore(fact));
- }
-
- public void appendLoad(InstructionList il, InstructionFactory fact) {
- il.append(createLoad(fact));
- }
-
- public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) {
- il.append(createLoad(fact));
- Utility.appendConversion(il, fact, getType(), toType);
- }
-
- public void insertLoad(InstructionList il, InstructionFactory fact) {
- il.insert(createLoad(fact));
- }
-
- public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) {
- InstructionList il = new InstructionList();
- il.append(InstructionFactory.createLoad(BcelWorld.makeBcelType(getType()), oldSlot));
- il.append(createStore(fact));
- return il;
- }
-
- // this is an array var
- void appendConvertableArrayLoad(InstructionList il, InstructionFactory fact, int index, ResolvedType convertTo) {
- ResolvedType convertFromType = getType().getResolvedComponentType();
- appendLoad(il, fact);
- il.append(Utility.createConstant(fact, index));
- il.append(InstructionFactory.createArrayLoad(BcelWorld.makeBcelType(convertFromType)));
- Utility.appendConversion(il, fact, convertFromType, convertTo);
- }
-
- void appendConvertableArrayStore(InstructionList il, InstructionFactory fact, int index, BcelVar storee) {
- ResolvedType convertToType = getType().getResolvedComponentType();
- appendLoad(il, fact);
- il.append(Utility.createConstant(fact, index));
- storee.appendLoad(il, fact);
- Utility.appendConversion(il, fact, storee.getType(), convertToType);
- il.append(InstructionFactory.createArrayStore(BcelWorld.makeBcelType(convertToType)));
- }
-
- InstructionList createConvertableArrayStore(InstructionFactory fact, int index, BcelVar storee) {
- InstructionList il = new InstructionList();
- appendConvertableArrayStore(il, fact, index, storee);
- return il;
- }
-
- InstructionList createConvertableArrayLoad(InstructionFactory fact, int index, ResolvedType convertTo) {
- InstructionList il = new InstructionList();
- appendConvertableArrayLoad(il, fact, index, convertTo);
- return il;
- }
-
- public int getPositionInAroundState() {
- return positionInAroundState;
- }
-
- public void setPositionInAroundState(int positionInAroundState) {
- this.positionInAroundState = positionInAroundState;
- }
-
- // random useful fields
-
- public static final BcelVar[] NONE = new BcelVar[] {};
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeakClassLoaderReference.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeakClassLoaderReference.java
deleted file mode 100644
index aac294fa4..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelWeakClassLoaderReference.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/* *******************************************************************
- * 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.bcel;
-
-import org.aspectj.apache.bcel.util.ClassLoaderReference;
-import org.aspectj.weaver.WeakClassLoaderReference;
-
-/**
- * Wraps a reference to a classloader inside a WeakReference. This should be used where we do not want the existence of a
- * classloader reference to prevent garbage collection of that classloader (and possibly an associated weaver instance in the case
- * of load time weaving).
- * <p>
- * In more detail:<br>
- * When load time weaving, the class Aj maintains a WeakHashMap from the classloader instance to a weaver instance. The aim is that
- * the weaver is around as long as the classloader is and should the classloader be dereferenced then the weaver can also be garbage
- * collected. The problem is that if there are many references to the classloader from within the weaver, these are considered hard
- * references and cause the classloader to be long lived - even if the user of the classloader has dereferenced it in their code.
- * The solution is that the weaver should use instances of WeakClassLoaderReference objects - so that when the users hard reference
- * to the classloader goes, nothing in the weaver will cause it to hang around. There is a big assertion here that the
- * WeakClassLoaderReference instances will not 'lose' their ClassLoader references until the top level ClassLoader reference is
- * null'd. This means there is no need to check for the null case on get() in this WeakReference logic below, because we shouldn't
- * be using this weaver if its associated ClassLoader has been collected. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=210470
- *
- *
- * @author Andy Clement
- */
-public class BcelWeakClassLoaderReference extends WeakClassLoaderReference implements ClassLoaderReference {
-
- public BcelWeakClassLoaderReference(ClassLoader loader) {
- super(loader);
- }
-
- public boolean equals(Object obj) {
- if (!(obj instanceof BcelWeakClassLoaderReference))
- return false;
- BcelWeakClassLoaderReference other = (BcelWeakClassLoaderReference) obj;
- return (other.hashcode == hashcode);
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
deleted file mode 100644
index f83a79379..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
+++ /dev/null
@@ -1,2043 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2002-2010 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
- * ******************************************************************/
-package org.aspectj.weaver.bcel;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Enumeration;
-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 java.util.jar.Attributes;
-import java.util.jar.Attributes.Name;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-import java.util.zip.ZipOutputStream;
-
-import org.aspectj.apache.bcel.classfile.ClassParser;
-import org.aspectj.apache.bcel.classfile.JavaClass;
-import org.aspectj.asm.AsmManager;
-import org.aspectj.asm.IProgramElement;
-import org.aspectj.asm.internal.AspectJElementHierarchy;
-import org.aspectj.bridge.IMessage;
-import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.bridge.Message;
-import org.aspectj.bridge.MessageUtil;
-import org.aspectj.bridge.SourceLocation;
-import org.aspectj.bridge.WeaveMessage;
-import org.aspectj.bridge.context.CompilationAndWeavingContext;
-import org.aspectj.bridge.context.ContextToken;
-import org.aspectj.util.FileUtil;
-import org.aspectj.util.FuzzyBoolean;
-import org.aspectj.weaver.Advice;
-import org.aspectj.weaver.AdviceKind;
-import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
-import org.aspectj.weaver.AnnotationAJ;
-import org.aspectj.weaver.AnnotationOnTypeMunger;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.CompressingDataOutputStream;
-import org.aspectj.weaver.ConcreteTypeMunger;
-import org.aspectj.weaver.CrosscuttingMembersSet;
-import org.aspectj.weaver.CustomMungerFactory;
-import org.aspectj.weaver.IClassFileProvider;
-import org.aspectj.weaver.IUnwovenClassFile;
-import org.aspectj.weaver.IWeaveRequestor;
-import org.aspectj.weaver.NewParentTypeMunger;
-import org.aspectj.weaver.ReferenceType;
-import org.aspectj.weaver.ReferenceTypeDelegate;
-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.WeaverStateInfo;
-import org.aspectj.weaver.World;
-import org.aspectj.weaver.model.AsmRelationshipProvider;
-import org.aspectj.weaver.patterns.AndPointcut;
-import org.aspectj.weaver.patterns.BindingPattern;
-import org.aspectj.weaver.patterns.BindingTypePattern;
-import org.aspectj.weaver.patterns.ConcreteCflowPointcut;
-import org.aspectj.weaver.patterns.DeclareAnnotation;
-import org.aspectj.weaver.patterns.DeclareParents;
-import org.aspectj.weaver.patterns.DeclareTypeErrorOrWarning;
-import org.aspectj.weaver.patterns.FastMatchInfo;
-import org.aspectj.weaver.patterns.IfPointcut;
-import org.aspectj.weaver.patterns.KindedPointcut;
-import org.aspectj.weaver.patterns.NameBindingPointcut;
-import org.aspectj.weaver.patterns.NotPointcut;
-import org.aspectj.weaver.patterns.OrPointcut;
-import org.aspectj.weaver.patterns.Pointcut;
-import org.aspectj.weaver.patterns.PointcutRewriter;
-import org.aspectj.weaver.patterns.WithinPointcut;
-import org.aspectj.weaver.tools.Trace;
-import org.aspectj.weaver.tools.TraceFactory;
-
-/**
- *
- * @author PARC
- * @author Andy Clement
- * @author Alexandre Vasseur
- */
-public class BcelWeaver {
-
- public static final String CLOSURE_CLASS_PREFIX = "$Ajc";
- public static final String SYNTHETIC_CLASS_POSTFIX = "$ajc";
-
- private static Trace trace = TraceFactory.getTraceFactory().getTrace(BcelWeaver.class);
-
- private transient final BcelWorld world;
- private final CrosscuttingMembersSet xcutSet;
-
- private boolean inReweavableMode = false;
-
- private transient List<UnwovenClassFile> addedClasses = new ArrayList<UnwovenClassFile>();
- private transient List<String> deletedTypenames = new ArrayList<String>();
-
- // These four are setup by prepareForWeave
- private transient List<ShadowMunger> shadowMungerList = null;
- private transient List<ConcreteTypeMunger> typeMungerList = null;
- private transient List<ConcreteTypeMunger> lateTypeMungerList = null;
- private transient List<DeclareParents> declareParentsList = null;
-
- private Manifest manifest = null;
- private boolean needToReweaveWorld = false;
-
- private boolean isBatchWeave = true;
-
- private ZipOutputStream zipOutputStream;
- private CustomMungerFactory customMungerFactory;
-
- public BcelWeaver(BcelWorld world) {
- super();
- if (trace.isTraceEnabled()) {
- trace.enter("<init>", this, world);
- }
- this.world = world;
- this.xcutSet = world.getCrosscuttingMembersSet();
- if (trace.isTraceEnabled()) {
- trace.exit("<init>");
- }
- }
-
- /**
- * Add the given aspect to the weaver. The type is resolved to support DOT for static inner classes as well as DOLLAR
- *
- * @param aspectName
- * @return aspect
- */
- public ResolvedType addLibraryAspect(String aspectName) {
- if (trace.isTraceEnabled()) {
- trace.enter("addLibraryAspect", this, aspectName);
- }
-
- // 1 - resolve as is
- UnresolvedType unresolvedT = UnresolvedType.forName(aspectName);
- unresolvedT.setNeedsModifiableDelegate(true);
- ResolvedType type = world.resolve(unresolvedT, true);
- if (type.isMissing()) {
- // fallback on inner class lookup mechanism
- String fixedName = aspectName;
- int hasDot = fixedName.lastIndexOf('.');
- while (hasDot > 0) {
- // System.out.println("BcelWeaver.addLibraryAspect " + fixedName);
- char[] fixedNameChars = fixedName.toCharArray();
- fixedNameChars[hasDot] = '$';
- fixedName = new String(fixedNameChars);
- hasDot = fixedName.lastIndexOf('.');
- UnresolvedType ut = UnresolvedType.forName(fixedName);
- ut.setNeedsModifiableDelegate(true);
- type = world.resolve(ut, true);
- if (!type.isMissing()) {
- break;
- }
- }
- }
-
- // System.out.println("type: " + type + " for " + aspectName);
- if (type.isAspect()) {
- // Bug 119657 ensure we use the unwoven aspect
- WeaverStateInfo wsi = type.getWeaverState();
- if (wsi != null && wsi.isReweavable()) {
- BcelObjectType classType = getClassType(type.getName());
- JavaClass wovenJavaClass = classType.getJavaClass();
- byte[] bytes = wsi.getUnwovenClassFileData(wovenJavaClass.getBytes());
- JavaClass unwovenJavaClass = Utility.makeJavaClass(wovenJavaClass.getFileName(), bytes);
- world.storeClass(unwovenJavaClass);
- classType.setJavaClass(unwovenJavaClass, true);
- // classType.setJavaClass(Utility.makeJavaClass(classType.
- // getJavaClass().getFileName(),
- // wsi.getUnwovenClassFileData(classType.getJavaClass().getBytes(
- // ))));
- }
-
- // TODO AV - happens to reach that a lot of time: for each type
- // flagged reweavable X for each aspect in the weaverstate
- // => 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 {
- if (type.isMissing()) {
- // May not be found if not visible to the classloader that can see the aop.xml during LTW
- IMessage message = new Message("The specified aspect '"+aspectName+"' cannot be found", null, true);
- world.getMessageHandler().handleMessage(message);
- } else {
- IMessage message = new Message("Cannot register '"+aspectName+"' because the type found with that name is not an aspect", null, true);
- world.getMessageHandler().handleMessage(message);
- }
- return null;
- }
- }
-
- /**
- *
- * @param inFile directory containing classes or zip/jar class archive
- */
- public void addLibraryJarFile(File inFile) throws IOException {
- List<ResolvedType> addedAspects = null;
- if (inFile.isDirectory()) {
- addedAspects = addAspectsFromDirectory(inFile);
- } else {
- addedAspects = addAspectsFromJarFile(inFile);
- }
- for (ResolvedType addedAspect : addedAspects) {
- xcutSet.addOrReplaceAspect(addedAspect);
- }
- }
-
- private List<ResolvedType> addAspectsFromJarFile(File inFile) throws FileNotFoundException, IOException {
- ZipInputStream inStream = new ZipInputStream(new FileInputStream(inFile)); // ??? buffered
- List<ResolvedType> addedAspects = new ArrayList<ResolvedType>();
- try {
- while (true) {
- ZipEntry entry = inStream.getNextEntry();
- if (entry == null) {
- break;
- }
-
- if (entry.isDirectory() || !entry.getName().endsWith(".class")) {
- continue;
- }
-
- // FIXME ASC performance? of this alternative soln.
- int size = (int) entry.getSize();
- ClassParser parser = new ClassParser(new ByteArrayInputStream(FileUtil.readAsByteArray(inStream)), entry.getName());
- JavaClass jc = parser.parse();
- inStream.closeEntry();
-
- ResolvedType type = world.addSourceObjectType(jc, false).getResolvedTypeX();
- type.setBinaryPath(inFile.getAbsolutePath());
- if (type.isAspect()) {
- addedAspects.add(type);
- } else {
- world.demote(type);
- }
-
- }
- } finally {
- inStream.close();
- }
- return addedAspects;
- }
-
- /**
- * Look for .class files that represent aspects in the supplied directory - return the list of accumulated aspects.
- *
- * @param directory the directory in which to look for Aspect .class files
- * @return the list of discovered aspects
- * @throws FileNotFoundException
- * @throws IOException
- */
- private List<ResolvedType> addAspectsFromDirectory(File directory) throws FileNotFoundException, IOException {
- List<ResolvedType> addedAspects = new ArrayList<ResolvedType>();
- File[] classFiles = FileUtil.listFiles(directory, new FileFilter() {
- public boolean accept(File pathname) {
- return pathname.getName().endsWith(".class");
- }
- });
- for (File classFile : classFiles) {
- FileInputStream fis = new FileInputStream(classFile);
- byte[] classBytes = FileUtil.readAsByteArray(fis);
- ResolvedType aspectType = isAspect(classBytes, classFile.getAbsolutePath(), directory);
- if (aspectType != null) {
- addedAspects.add(aspectType);
- }
- fis.close();
- }
- return addedAspects;
- }
-
- /**
- * Determine if the supplied bytes represent an aspect, if they do then create a ResolvedType instance for the aspect and return
- * it, otherwise return null
- *
- * @param classbytes the classbytes that might represent an aspect
- * @param name the name of the class
- * @param directory directory which contained the class file
- * @return a ResolvedType if the classbytes represent an aspect, otherwise null
- */
- private ResolvedType isAspect(byte[] classbytes, String name, File dir) throws IOException {
- ClassParser parser = new ClassParser(new ByteArrayInputStream(classbytes), name);
- JavaClass jc = parser.parse();
- ResolvedType type = world.addSourceObjectType(jc, false).getResolvedTypeX();
- String typeName = type.getName().replace('.', File.separatorChar);
- int end = name.lastIndexOf(typeName + ".class");
- String binaryPath = null;
- // if end is -1 then something weird happened, the class file is not in
- // the correct place, something like
- // bin/A.class when the declaration for A specifies it is in a package.
- if (end == -1) {
- binaryPath = dir.getAbsolutePath();
- } else {
- binaryPath = name.substring(0, end - 1);
- }
- type.setBinaryPath(binaryPath);
- if (type.isAspect()) {
- return type;
- } else {
- // immediately demote the type we just added since it will have
- // have been stuffed into the permanent map (assumed to be
- // an aspect)
- world.demote(type);
- return null;
- }
- }
-
- // // The ANT copy task should be used to copy resources across.
- // private final static boolean
- // CopyResourcesFromInpathDirectoriesToOutput=false;
-
- /**
- * Add any .class files in the directory to the outdir. Anything other than .class files in the directory (or its
- * subdirectories) are considered resources and are also copied.
- *
- */
- public List<UnwovenClassFile> addDirectoryContents(File inFile, File outDir) throws IOException {
- List<UnwovenClassFile> addedClassFiles = new ArrayList<UnwovenClassFile>();
-
- // Get a list of all files (i.e. everything that isnt a directory)
- File[] files = FileUtil.listFiles(inFile, new FileFilter() {
- public boolean accept(File f) {
- boolean accept = !f.isDirectory();
- return accept;
- }
- });
-
- // For each file, add it either as a real .class file or as a resource
- for (int i = 0; i < files.length; i++) {
- addedClassFiles.add(addClassFile(files[i], inFile, outDir));
- }
-
- return addedClassFiles;
- }
-
- /**
- * Adds all class files in the jar
- */
- public List<UnwovenClassFile> addJarFile(File inFile, File outDir, boolean canBeDirectory) {
- // System.err.println("? addJarFile(" + inFile + ", " + outDir + ")");
- List<UnwovenClassFile> addedClassFiles = new ArrayList<UnwovenClassFile>();
- needToReweaveWorld = true;
- JarFile inJar = null;
-
- try {
- // Is this a directory we are looking at?
- if (inFile.isDirectory() && canBeDirectory) {
- addedClassFiles.addAll(addDirectoryContents(inFile, outDir));
- } else {
-
- inJar = new JarFile(inFile);
- try {
- addManifest(inJar.getManifest());
- Enumeration entries = inJar.entries();
-
- while (entries.hasMoreElements()) {
- JarEntry entry = (JarEntry) entries.nextElement();
- InputStream inStream = inJar.getInputStream(entry);
-
- byte[] bytes = FileUtil.readAsByteArray(inStream);
- String filename = entry.getName();
- // System.out.println("? addJarFile() filename='" + filename
- // + "'");
- UnwovenClassFile classFile = new UnwovenClassFile(new File(outDir, filename).getAbsolutePath(), bytes);
-
- if (filename.endsWith(".class")) {
- ReferenceType type = this.addClassFile(classFile, false);
- StringBuffer sb = new StringBuffer();
- sb.append(inFile.getAbsolutePath());
- sb.append("!");
- sb.append(entry.getName());
- type.setBinaryPath(sb.toString());
- addedClassFiles.add(classFile);
- }
- // else if (!entry.isDirectory()) {
- //
- // /* bug-44190 Copy meta-data */
- // addResource(filename,classFile);
- // }
-
- inStream.close();
- }
- } finally {
- inJar.close();
- }
- inJar.close();
- }
- } catch (FileNotFoundException ex) {
- IMessage message = new Message("Could not find input jar file " + inFile.getPath() + ", ignoring", new SourceLocation(
- inFile, 0), false);
- world.getMessageHandler().handleMessage(message);
- } catch (IOException ex) {
- IMessage message = new Message("Could not read input jar file " + inFile.getPath() + "(" + ex.getMessage() + ")",
- new SourceLocation(inFile, 0), true);
- world.getMessageHandler().handleMessage(message);
- } finally {
- if (inJar != null) {
- try {
- inJar.close();
- } catch (IOException ex) {
- IMessage message = new Message("Could not close input jar file " + inFile.getPath() + "(" + ex.getMessage()
- + ")", new SourceLocation(inFile, 0), true);
- world.getMessageHandler().handleMessage(message);
- }
- }
- }
-
- return addedClassFiles;
- }
-
- public boolean needToReweaveWorld() {
- return needToReweaveWorld;
- }
-
- /**
- * Should be addOrReplace
- */
- public ReferenceType addClassFile(UnwovenClassFile classFile, boolean fromInpath) {
- addedClasses.add(classFile);
- ReferenceType type = world.addSourceObjectType(classFile.getJavaClass(), false).getResolvedTypeX();
- if (fromInpath) {
- type.setBinaryPath(classFile.getFilename());
- }
- return type;
- }
-
- public UnwovenClassFile addClassFile(File classFile, File inPathDir, File outDir) throws IOException {
- FileInputStream fis = new FileInputStream(classFile);
- byte[] bytes = FileUtil.readAsByteArray(fis);
- // String relativePath = files[i].getPath();
-
- // ASSERT:
- // files[i].getAbsolutePath().startsWith(inFile.getAbsolutePath()
- // or we are in trouble...
- String filename = classFile.getAbsolutePath().substring(inPathDir.getAbsolutePath().length() + 1);
- UnwovenClassFile ucf = new UnwovenClassFile(new File(outDir, filename).getAbsolutePath(), bytes);
- if (filename.endsWith(".class")) {
- // System.err.println(
- // "BCELWeaver: processing class from input directory "+classFile);
- StringBuffer sb = new StringBuffer();
- sb.append(inPathDir.getAbsolutePath());
- sb.append("!");
- sb.append(filename);
- ReferenceType type = this.addClassFile(ucf, false);
- type.setBinaryPath(sb.toString());
- }
- fis.close();
- return ucf;
- }
-
- public void deleteClassFile(String typename) {
- deletedTypenames.add(typename);
- world.deleteSourceObjectType(UnresolvedType.forName(typename));
- }
-
- // ---- weave preparation
-
- public void setIsBatchWeave(boolean b) {
- isBatchWeave = b;
- }
-
- public void prepareForWeave() {
- if (trace.isTraceEnabled()) {
- trace.enter("prepareForWeave", this);
- }
- needToReweaveWorld = xcutSet.hasChangedSinceLastReset();
-
- // update mungers
- for (Iterator<UnwovenClassFile> i = addedClasses.iterator(); i.hasNext();) {
- UnwovenClassFile jc = i.next();
- String name = jc.getClassName();
- ResolvedType type = world.resolve(name);
- // No overweaving guard. If you have one then when overweaving is on the
- // addOrReplaceAspect will not be called when the aspect delegate changes from
- // EclipseSourceType to BcelObjectType. This will mean the mungers
- // are not picked up.
- if (type.isAspect()) {
- needToReweaveWorld |= xcutSet.addOrReplaceAspect(type);
- }
- }
-
- for (Iterator<String> i = deletedTypenames.iterator(); i.hasNext();) {
- String name = i.next();
- if (xcutSet.deleteAspect(UnresolvedType.forName(name))) {
- needToReweaveWorld = true;
- }
- }
-
- shadowMungerList = xcutSet.getShadowMungers();
- // world.debug("shadow mungers=" + shadowMungerList);
- rewritePointcuts(shadowMungerList);
- // Sometimes an error occurs during rewriting pointcuts (for example, if
- // ambiguous bindings
- // are detected) - we ought to fail the prepare when this happens
- // because continuing with
- // inconsistent pointcuts could lead to problems
- 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
- // have changed the sorting to be based on source location in the file -
- // this is reliable, in
- // the case of source locations missing, we assume they are 'sorted' -
- // i.e. the order in
- // which they were added to the collection is correct, this enables the
- // @AJ stuff to work properly.
-
- // When @AJ processing starts filling in source locations for mungers,
- // this code may need
- // a bit of alteration...
-
- Collections.sort(shadowMungerList, new Comparator<ShadowMunger>() {
- public int compare(ShadowMunger sm1, ShadowMunger sm2) {
- if (sm1.getSourceLocation() == null) {
- return (sm2.getSourceLocation() == null ? 0 : 1);
- }
- if (sm2.getSourceLocation() == null) {
- return -1;
- }
-
- return (sm2.getSourceLocation().getOffset() - sm1.getSourceLocation().getOffset());
- }
- });
-
- if (inReweavableMode) {
- world.showMessage(IMessage.INFO, WeaverMessages.format(WeaverMessages.REWEAVABLE_MODE), null, null);
- }
-
- if (trace.isTraceEnabled()) {
- trace.exit("prepareForWeave");
- }
- }
-
- private void addCustomMungers() {
- if (customMungerFactory != null) {
- for (Iterator<UnwovenClassFile> i = addedClasses.iterator(); i.hasNext();) {
- UnwovenClassFile jc = 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) then pc1 == pc2 (for non-binding pcds) by making references all point to the same instance. Since pointcuts
- * remember their match decision on the last shadow, this makes matching faster when many pointcuts share common elements, or
- * even when one single pointcut has one common element (which can be a side-effect of DNF rewriting).
- */
- private void rewritePointcuts(List<ShadowMunger> shadowMungers) {
- PointcutRewriter rewriter = new PointcutRewriter();
- for (ShadowMunger munger : shadowMungers) {
- Pointcut p = munger.getPointcut();
- Pointcut newP = rewriter.rewrite(p);
- // validateBindings now whilst we still have around the pointcut
- // that resembles what the user actually wrote in their program
- // text.
- if (munger instanceof Advice) {
- Advice advice = (Advice) munger;
- if (advice.getSignature() != null) {
- final int numFormals;
- final String names[];
- // If the advice is being concretized in a @AJ aspect *and*
- // the advice was declared in
- // an @AJ aspect (it could have been inherited from a code
- // style aspect) then
- // evaluate the alternative set of formals. pr125699
- if ((advice.getConcreteAspect().isAnnotationStyleAspect() && advice.getDeclaringAspect() != null && advice
- .getDeclaringAspect().resolve(world).isAnnotationStyleAspect())
- || advice.isAnnotationStyle()) {
- numFormals = advice.getBaseParameterCount();
- int numArgs = advice.getSignature().getParameterTypes().length;
- if (numFormals > 0) {
- names = advice.getSignature().getParameterNames(world);
- validateBindings(newP, p, numArgs, names);
- }
- } else {
- numFormals = advice.getBaseParameterCount();
- if (numFormals > 0) {
- names = advice.getBaseParameterNames(world);
- validateBindings(newP, p, numFormals, names);
- }
- }
- }
- }
- newP.m_ignoreUnboundBindingForNames = p.m_ignoreUnboundBindingForNames;
- munger.setPointcut(newP);
- }
- // now that we have optimized individual pointcuts, optimize
- // across the set of pointcuts....
- // Use a map from key based on pc equality, to value based on
- // pc identity.
- Map<Pointcut, Pointcut> pcMap = new HashMap<Pointcut, Pointcut>();
- for (ShadowMunger munger: shadowMungers) {
- Pointcut p = munger.getPointcut();
- Pointcut newP = shareEntriesFromMap(p, pcMap);
- newP.m_ignoreUnboundBindingForNames = p.m_ignoreUnboundBindingForNames;
- munger.setPointcut(newP);
- }
- }
-
- private Pointcut shareEntriesFromMap(Pointcut p, Map<Pointcut, Pointcut> pcMap) {
- // some things cant be shared...
- if (p instanceof NameBindingPointcut) {
- return p;
- }
- if (p instanceof IfPointcut) {
- return p;
- }
- if (p instanceof ConcreteCflowPointcut) {
- return p;
- }
- if (p instanceof AndPointcut) {
- AndPointcut apc = (AndPointcut) p;
- Pointcut left = shareEntriesFromMap(apc.getLeft(), pcMap);
- Pointcut right = shareEntriesFromMap(apc.getRight(), pcMap);
- return new AndPointcut(left, right);
- } else if (p instanceof OrPointcut) {
- OrPointcut opc = (OrPointcut) p;
- Pointcut left = shareEntriesFromMap(opc.getLeft(), pcMap);
- Pointcut right = shareEntriesFromMap(opc.getRight(), pcMap);
- return new OrPointcut(left, right);
- } else if (p instanceof NotPointcut) {
- NotPointcut npc = (NotPointcut) p;
- Pointcut not = shareEntriesFromMap(npc.getNegatedPointcut(), pcMap);
- return new NotPointcut(not);
- } else {
- // primitive pcd
- if (pcMap.containsKey(p)) { // based on equality
- return pcMap.get(p); // same instance (identity)
- } else {
- pcMap.put(p, p);
- return p;
- }
- }
- }
-
- // userPointcut is the pointcut that the user wrote in the program text.
- // dnfPointcut is the same pointcut rewritten in DNF
- // numFormals is the number of formal parameters in the pointcut
- // if numFormals > 0 then every branch of a disjunction must bind each
- // formal once and only once.
- // in addition, the left and right branches of a disjunction must hold on
- // join point kinds in common.
- private void validateBindings(Pointcut dnfPointcut, Pointcut userPointcut, int numFormals, String[] names) {
- if (numFormals == 0) {
- return; // nothing to check
- }
- if (dnfPointcut.couldMatchKinds() == Shadow.NO_SHADOW_KINDS_BITS) {
- return; // cant have problems if you dont match!
- }
- if (dnfPointcut instanceof OrPointcut) {
- OrPointcut orBasedDNFPointcut = (OrPointcut) dnfPointcut;
- Pointcut[] leftBindings = new Pointcut[numFormals];
- Pointcut[] rightBindings = new Pointcut[numFormals];
- validateOrBranch(orBasedDNFPointcut, userPointcut, numFormals, names, leftBindings, rightBindings);
- } else {
- Pointcut[] bindings = new Pointcut[numFormals];
- validateSingleBranch(dnfPointcut, userPointcut, numFormals, names, bindings);
- }
- }
-
- private void validateOrBranch(OrPointcut pc, Pointcut userPointcut, int numFormals, String[] names, Pointcut[] leftBindings,
- Pointcut[] rightBindings) {
- Pointcut left = pc.getLeft();
- Pointcut right = pc.getRight();
- if (left instanceof OrPointcut) {
- Pointcut[] newRightBindings = new Pointcut[numFormals];
- validateOrBranch((OrPointcut) left, userPointcut, numFormals, names, leftBindings, newRightBindings);
- } else {
- if (left.couldMatchKinds() != Shadow.NO_SHADOW_KINDS_BITS) {
- validateSingleBranch(left, userPointcut, numFormals, names, leftBindings);
- }
- }
- if (right instanceof OrPointcut) {
- Pointcut[] newLeftBindings = new Pointcut[numFormals];
- validateOrBranch((OrPointcut) right, userPointcut, numFormals, names, newLeftBindings, rightBindings);
- } else {
- if (right.couldMatchKinds() != Shadow.NO_SHADOW_KINDS_BITS) {
- validateSingleBranch(right, userPointcut, numFormals, names, rightBindings);
- }
- }
- int kindsInCommon = left.couldMatchKinds() & right.couldMatchKinds();
- if (kindsInCommon != Shadow.NO_SHADOW_KINDS_BITS && couldEverMatchSameJoinPoints(left, right)) {
- // we know that every branch binds every formal, so there is no
- // ambiguity if each branch binds it in exactly the same way...
- List<String> ambiguousNames = new ArrayList<String>();
- for (int i = 0; i < numFormals; i++) {
- if (leftBindings[i] == null) {
- if (rightBindings[i] != null) {
- ambiguousNames.add(names[i]);
- }
- } else if (!leftBindings[i].equals(rightBindings[i])) {
- ambiguousNames.add(names[i]);
- }
- }
- if (!ambiguousNames.isEmpty()) {
- raiseAmbiguityInDisjunctionError(userPointcut, ambiguousNames);
- }
- }
- }
-
- // pc is a pointcut that does not contain any disjunctions
- // check that every formal is bound (negation doesn't count).
- // we know that numFormals > 0 or else we would not be called
- private void validateSingleBranch(Pointcut pc, Pointcut userPointcut, int numFormals, String[] names, Pointcut[] bindings) {
- boolean[] foundFormals = new boolean[numFormals];
- for (int i = 0; i < foundFormals.length; i++) {
- foundFormals[i] = false;
- }
- validateSingleBranchRecursion(pc, userPointcut, foundFormals, names, bindings);
- for (int i = 0; i < foundFormals.length; i++) {
- if (!foundFormals[i]) {
- boolean ignore = false;
- // ATAJ soften the unbound error for implicit bindings like
- // JoinPoint in @AJ style
- for (int j = 0; j < userPointcut.m_ignoreUnboundBindingForNames.length; j++) {
- if (names[i] != null && names[i].equals(userPointcut.m_ignoreUnboundBindingForNames[j])) {
- ignore = true;
- break;
- }
- }
- if (!ignore) {
- raiseUnboundFormalError(names[i], userPointcut);
- }
- }
- }
- }
-
- // each formal must appear exactly once
- private void validateSingleBranchRecursion(Pointcut pc, Pointcut userPointcut, boolean[] foundFormals, String[] names,
- Pointcut[] bindings) {
- if (pc instanceof NotPointcut) {
- // nots can only appear at leaves in DNF
- NotPointcut not = (NotPointcut) pc;
- if (not.getNegatedPointcut() instanceof NameBindingPointcut) {
- NameBindingPointcut nnbp = (NameBindingPointcut) not.getNegatedPointcut();
- if (!nnbp.getBindingAnnotationTypePatterns().isEmpty() && !nnbp.getBindingTypePatterns().isEmpty()) {
- raiseNegationBindingError(userPointcut);
- }
- }
- } else if (pc instanceof AndPointcut) {
- AndPointcut and = (AndPointcut) pc;
- validateSingleBranchRecursion(and.getLeft(), userPointcut, foundFormals, names, bindings);
- validateSingleBranchRecursion(and.getRight(), userPointcut, foundFormals, names, bindings);
- } else if (pc instanceof NameBindingPointcut) {
- List<BindingTypePattern> bindingTypePatterns = ((NameBindingPointcut) pc).getBindingTypePatterns();
- for (BindingTypePattern bindingTypePattern: bindingTypePatterns) {
- int index = bindingTypePattern.getFormalIndex();
- bindings[index] = pc;
- if (foundFormals[index]) {
- raiseAmbiguousBindingError(names[index], userPointcut);
- } else {
- foundFormals[index] = true;
- }
- }
- List<BindingPattern> bindingAnnotationTypePatterns = ((NameBindingPointcut) pc).getBindingAnnotationTypePatterns();
- for (BindingPattern bindingAnnotationTypePattern: bindingAnnotationTypePatterns) {
- int index = bindingAnnotationTypePattern.getFormalIndex();
- bindings[index] = pc;
- if (foundFormals[index]) {
- raiseAmbiguousBindingError(names[index], userPointcut);
- } else {
- foundFormals[index] = true;
- }
- }
- } else if (pc instanceof ConcreteCflowPointcut) {
- ConcreteCflowPointcut cfp = (ConcreteCflowPointcut) pc;
- int[] slots = cfp.getUsedFormalSlots();
- for (int i = 0; i < slots.length; i++) {
- bindings[slots[i]] = cfp;
- if (foundFormals[slots[i]]) {
- raiseAmbiguousBindingError(names[slots[i]], userPointcut);
- } else {
- foundFormals[slots[i]] = true;
- }
- }
- }
- }
-
- // By returning false from this method, we are allowing binding of the same
- // variable on either side of an or.
- // Be conservative :- have to consider overriding, varargs, autoboxing,
- // the effects of itds (on within for example), interfaces, the fact that
- // join points can have multiple signatures and so on.
- private boolean couldEverMatchSameJoinPoints(Pointcut left, Pointcut right) {
-
- if (left instanceof OrPointcut) {
- OrPointcut leftOrPointcut = (OrPointcut) left;
- if (couldEverMatchSameJoinPoints(leftOrPointcut.getLeft(), right)) {
- return true;
- }
- if (couldEverMatchSameJoinPoints(leftOrPointcut.getRight(), right)) {
- return true;
- }
- return false;
- }
-
- if (right instanceof OrPointcut) {
- OrPointcut rightOrPointcut = (OrPointcut) right;
- if (couldEverMatchSameJoinPoints(left, rightOrPointcut.getLeft())) {
- return true;
- }
- if (couldEverMatchSameJoinPoints(left, rightOrPointcut.getRight())) {
- return true;
- }
- return false;
- }
-
- // look for withins
- WithinPointcut leftWithin = (WithinPointcut) findFirstPointcutIn(left, WithinPointcut.class);
- WithinPointcut rightWithin = (WithinPointcut) findFirstPointcutIn(right, WithinPointcut.class);
- if ((leftWithin != null) && (rightWithin != null)) {
- if (!leftWithin.couldEverMatchSameJoinPointsAs(rightWithin)) {
- return false;
- }
- }
- // look for kinded
- KindedPointcut leftKind = (KindedPointcut) findFirstPointcutIn(left, KindedPointcut.class);
- KindedPointcut rightKind = (KindedPointcut) findFirstPointcutIn(right, KindedPointcut.class);
- if ((leftKind != null) && (rightKind != null)) {
- if (!leftKind.couldEverMatchSameJoinPointsAs(rightKind)) {
- return false;
- }
- }
- return true;
- }
-
- private Pointcut findFirstPointcutIn(Pointcut toSearch, Class toLookFor) {
- if (toSearch instanceof NotPointcut) {
- return null;
- }
- if (toLookFor.isInstance(toSearch)) {
- return toSearch;
- }
- if (toSearch instanceof AndPointcut) {
- AndPointcut apc = (AndPointcut) toSearch;
- Pointcut left = findFirstPointcutIn(apc.getLeft(), toLookFor);
- if (left != null) {
- return left;
- }
- return findFirstPointcutIn(apc.getRight(), toLookFor);
- }
- return null;
- }
-
- /**
- * @param userPointcut
- */
- private void raiseNegationBindingError(Pointcut userPointcut) {
- world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.NEGATION_DOESNT_ALLOW_BINDING), userPointcut
- .getSourceContext().makeSourceLocation(userPointcut), null);
- }
-
- private void raiseAmbiguousBindingError(String name, Pointcut pointcut) {
- world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.AMBIGUOUS_BINDING, name), pointcut
- .getSourceContext().makeSourceLocation(pointcut), null);
- }
-
- /**
- * @param userPointcut
- */
- private void raiseAmbiguityInDisjunctionError(Pointcut userPointcut, List<String> names) {
- StringBuffer formalNames = new StringBuffer(names.get(0).toString());
- for (int i = 1; i < names.size(); i++) {
- formalNames.append(", ");
- formalNames.append(names.get(i));
- }
- world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.AMBIGUOUS_BINDING_IN_OR, formalNames), userPointcut
- .getSourceContext().makeSourceLocation(userPointcut), null);
- }
-
- /**
- * @param name
- * @param userPointcut
- */
- private void raiseUnboundFormalError(String name, Pointcut userPointcut) {
- world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.UNBOUND_FORMAL, name),
- userPointcut.getSourceLocation(), null);
- }
-
- public void addManifest(Manifest newManifest) {
- // System.out.println("? addManifest() newManifest=" + newManifest);
- if (manifest == null) {
- manifest = newManifest;
- }
- }
-
- public Manifest getManifest(boolean shouldCreate) {
- if (manifest == null && shouldCreate) {
- String WEAVER_MANIFEST_VERSION = "1.0";
- Attributes.Name CREATED_BY = new Name("Created-By");
- String WEAVER_CREATED_BY = "AspectJ Compiler";
-
- manifest = new Manifest();
-
- Attributes attributes = manifest.getMainAttributes();
- attributes.put(Name.MANIFEST_VERSION, WEAVER_MANIFEST_VERSION);
- attributes.put(CREATED_BY, WEAVER_CREATED_BY);
- }
-
- return manifest;
- }
-
- // ---- weaving
-
- // FOR TESTING
- public Collection<String> weave(File file) throws IOException {
- OutputStream os = FileUtil.makeOutputStream(file);
- this.zipOutputStream = new ZipOutputStream(os);
- prepareForWeave();
- Collection<String> c = weave(new IClassFileProvider() {
-
- public boolean isApplyAtAspectJMungersOnly() {
- return false;
- }
-
- public Iterator<UnwovenClassFile> getClassFileIterator() {
- return addedClasses.iterator();
- }
-
- public IWeaveRequestor getRequestor() {
- return new IWeaveRequestor() {
- public void acceptResult(IUnwovenClassFile result) {
- try {
- writeZipEntry(result.getFilename(), result.getBytes());
- } catch (IOException ex) {
- }
- }
-
- public void processingReweavableState() {
- }
-
- public void addingTypeMungers() {
- }
-
- public void weavingAspects() {
- }
-
- public void weavingClasses() {
- }
-
- public void weaveCompleted() {
- }
- };
- }
- });
- // /* BUG 40943*/
- // dumpResourcesToOutJar();
- zipOutputStream.close(); // this flushes and closes the acutal file
- return c;
- }
-
- private Set<IProgramElement> candidatesForRemoval = null;
-
- // variation of "weave" that sources class files from an external source.
- public Collection<String> weave(IClassFileProvider input) throws IOException {
- if (trace.isTraceEnabled()) {
- trace.enter("weave", this, input);
- }
- ContextToken weaveToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING, "");
- Collection<String> wovenClassNames = new ArrayList<String>();
- IWeaveRequestor requestor = input.getRequestor();
-
- if (world.getModel() != null && world.isMinimalModel()) {
- candidatesForRemoval = new HashSet<IProgramElement>();
- }
- if (world.getModel() != null && !isBatchWeave) {
- AsmManager manager = world.getModelAsAsmManager();
- for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
- UnwovenClassFile classFile = i.next();
- // remove all relationships where this file being woven is
- // the target of the relationship
- manager.removeRelationshipsTargettingThisType(classFile.getClassName());
- }
- }
-
- // Go through the types and ensure any 'damaged' during compile time are
- // repaired prior to weaving
- for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
- UnwovenClassFile classFile = i.next();
- if (classFile.shouldBeWoven()) {
- String className = classFile.getClassName();
- ResolvedType theType = world.resolve(className);
- if (theType != null) {
- theType.ensureConsistent();
- }
- }
- }
-
- // special case for AtAspectJMungerOnly - see #113587
- if (input.isApplyAtAspectJMungersOnly()) {
- ContextToken atAspectJMungersOnly = CompilationAndWeavingContext.enteringPhase(
- CompilationAndWeavingContext.PROCESSING_ATASPECTJTYPE_MUNGERS_ONLY, "");
- requestor.weavingAspects();
- // ContextToken aspectToken =
- CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_ASPECTS, "");
- for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
- UnwovenClassFile classFile = i.next();
- if (classFile.shouldBeWoven()) {
- String className = classFile.getClassName();
- ResolvedType theType = world.resolve(className);
- if (theType.isAnnotationStyleAspect()) {
- BcelObjectType classType = BcelWorld.getBcelObjectType(theType);
- if (classType == null) {
- throw new BCException("Can't find bcel delegate for " + className + " type=" + theType.getClass());
- }
- LazyClassGen clazz = classType.getLazyClassGen();
- BcelPerClauseAspectAdder selfMunger = new BcelPerClauseAspectAdder(theType, theType.getPerClause().getKind());
- selfMunger.forceMunge(clazz, true);
- classType.finishedWith();
- UnwovenClassFile[] newClasses = getClassFilesFor(clazz);
- for (int news = 0; news < newClasses.length; news++) {
- requestor.acceptResult(newClasses[news]);
- }
- wovenClassNames.add(classFile.getClassName());
- }
- }
- }
- requestor.weaveCompleted();
- CompilationAndWeavingContext.leavingPhase(atAspectJMungersOnly);
- return wovenClassNames;
- }
-
- requestor.processingReweavableState();
- ContextToken reweaveToken = CompilationAndWeavingContext.enteringPhase(
- CompilationAndWeavingContext.PROCESSING_REWEAVABLE_STATE, "");
- prepareToProcessReweavableState();
- // clear all state from files we'll be reweaving
- for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
- UnwovenClassFile classFile = i.next();
- if (classFile.shouldBeWoven()) {
- String className = classFile.getClassName();
- BcelObjectType classType = getClassType(className);
-
- // null return from getClassType() means the delegate is an eclipse
- // source type - so
- // there *cant* be any reweavable state... (he bravely claimed...)
- if (classType != null) {
- ContextToken tok = CompilationAndWeavingContext.enteringPhase(
- CompilationAndWeavingContext.PROCESSING_REWEAVABLE_STATE, className);
- processReweavableStateIfPresent(className, classType);
- CompilationAndWeavingContext.leavingPhase(tok);
- }
- }
- }
-
- CompilationAndWeavingContext.leavingPhase(reweaveToken);
-
- ContextToken typeMungingToken = CompilationAndWeavingContext.enteringPhase(
- CompilationAndWeavingContext.PROCESSING_TYPE_MUNGERS, "");
- requestor.addingTypeMungers();
-
- // We process type mungers in two groups, first mungers that change the
- // type
- // hierarchy, then 'normal' ITD type mungers.
-
- // Process the types in a predictable order (rather than the order
- // encountered).
- // For class A, the order is superclasses of A then superinterfaces of A
- // (and this mechanism is applied recursively)
- List<String> typesToProcess = new ArrayList<String>();
- for (Iterator<UnwovenClassFile> iter = input.getClassFileIterator(); iter.hasNext();) {
- UnwovenClassFile clf = iter.next();
- if (clf.shouldBeWoven()) {
- typesToProcess.add(clf.getClassName());
- }
- }
- while (typesToProcess.size() > 0) {
- weaveParentsFor(typesToProcess, typesToProcess.get(0), null);
- }
-
- for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
- UnwovenClassFile classFile = i.next();
- if (classFile.shouldBeWoven()) {
- String className = classFile.getClassName();
- addNormalTypeMungers(className);
- }
- }
-
- CompilationAndWeavingContext.leavingPhase(typeMungingToken);
-
- requestor.weavingAspects();
- ContextToken aspectToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_ASPECTS, "");
- // first weave into aspects
- for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
- UnwovenClassFile classFile = i.next();
- if (classFile.shouldBeWoven()) {
- String className = classFile.getClassName();
- ResolvedType theType = world.resolve(className);
- if (theType.isAspect()) {
- BcelObjectType classType = BcelWorld.getBcelObjectType(theType);
- if (classType == null) {
-
- // Sometimes.. if the Bcel Delegate couldn't be found then a
- // problem occurred at compile time - on
- // a previous compiler run. In this case I assert the
- // delegate will still be an EclipseSourceType
- // and we can ignore the problem here (the original compile
- // error will be reported again from
- // the eclipse source type) - pr113531
- ReferenceTypeDelegate theDelegate = ((ReferenceType) theType).getDelegate();
- if (theDelegate.getClass().getName().endsWith("EclipseSourceType")) {
- continue;
- }
-
- throw new BCException("Can't find bcel delegate for " + className + " type=" + theType.getClass());
- }
- weaveAndNotify(classFile, classType, requestor);
- wovenClassNames.add(className);
- }
- }
- }
-
- CompilationAndWeavingContext.leavingPhase(aspectToken);
-
- requestor.weavingClasses();
- ContextToken classToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_CLASSES, "");
- // then weave into non-aspects
- for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
- UnwovenClassFile classFile = i.next();
- if (classFile.shouldBeWoven()) {
- String className = classFile.getClassName();
- ResolvedType theType = world.resolve(className);
- if (!theType.isAspect()) {
- BcelObjectType classType = BcelWorld.getBcelObjectType(theType);
- if (classType == null) {
-
- // bug 119882 - see above comment for bug 113531
- ReferenceTypeDelegate theDelegate = ((ReferenceType) theType).getDelegate();
-
- // TODO urgh - put a method on the interface to check this,
- // string compare is hideous
- if (theDelegate.getClass().getName().endsWith("EclipseSourceType")) {
- continue;
- }
-
- throw new BCException("Can't find bcel delegate for " + className + " type=" + theType.getClass());
- }
- weaveAndNotify(classFile, classType, requestor);
- wovenClassNames.add(className);
- }
- }
- }
- CompilationAndWeavingContext.leavingPhase(classToken);
-
- addedClasses.clear();
- deletedTypenames.clear();
-
- requestor.weaveCompleted();
- CompilationAndWeavingContext.leavingPhase(weaveToken);
- if (trace.isTraceEnabled()) {
- trace.exit("weave", wovenClassNames);
- }
- if (world.getModel() != null && world.isMinimalModel()) {
- candidatesForRemoval.clear();
- }
- return wovenClassNames;
- }
-
- public void allWeavingComplete() {
- warnOnUnmatchedAdvice();
- }
-
- /**
- * In 1.5 mode and with XLint:adviceDidNotMatch enabled, put out messages for any mungers that did not match anything.
- */
- private void warnOnUnmatchedAdvice() {
-
- class AdviceLocation {
- private final int lineNo;
- private final UnresolvedType inAspect;
-
- public AdviceLocation(BcelAdvice advice) {
- this.lineNo = advice.getSourceLocation().getLine();
- this.inAspect = advice.getDeclaringAspect();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof AdviceLocation)) {
- return false;
- }
- AdviceLocation other = (AdviceLocation) obj;
- if (this.lineNo != other.lineNo) {
- return false;
- }
- if (!this.inAspect.equals(other.inAspect)) {
- return false;
- }
- return true;
- }
-
- @Override
- public int hashCode() {
- return 37 + 17 * lineNo + 17 * inAspect.hashCode();
- }
- }
-
- // FIXME asc Should be factored out into Xlint code and done
- // automatically for all xlint messages, ideally.
- // if a piece of advice hasn't matched anywhere and we are in -1.5 mode,
- // put out a warning
- if (world.isInJava5Mode() && world.getLint().adviceDidNotMatch.isEnabled()) {
- List l = world.getCrosscuttingMembersSet().getShadowMungers();
- Set<AdviceLocation> alreadyWarnedLocations = new HashSet<AdviceLocation>();
-
- for (Iterator iter = l.iterator(); iter.hasNext();) {
- ShadowMunger element = (ShadowMunger) iter.next();
- // This will stop us incorrectly reporting deow checkers:
- if (element instanceof BcelAdvice) {
- BcelAdvice ba = (BcelAdvice) element;
- if (ba.getKind() == AdviceKind.CflowEntry || ba.getKind() == AdviceKind.CflowBelowEntry) {
- continue;
- }
- if (!ba.hasMatchedSomething()) {
- // Because we implement some features of AJ itself by
- // creating our own kind of mungers, you sometimes
- // find that ba.getSignature() is not a BcelMethod - for
- // example it might be a cflow entry munger.
- if (ba.getSignature() != null) {
- // check we haven't already warned on this advice and line
- // (cflow creates multiple mungers for the same advice)
- AdviceLocation loc = new AdviceLocation(ba);
- if (alreadyWarnedLocations.contains(loc)) {
- continue;
- } else {
- alreadyWarnedLocations.add(loc);
- }
-
- if (!(ba.getSignature() instanceof BcelMethod)
- || !Utility.isSuppressing(ba.getSignature(), "adviceDidNotMatch")) {
- world.getLint().adviceDidNotMatch.signal(ba.getDeclaringAspect().toString(), new SourceLocation(
- element.getSourceLocation().getSourceFile(), element.getSourceLocation().getLine()));
- }
- }
- }
- }
- }
- }
- }
-
- /**
- * 'typeToWeave' is one from the 'typesForWeaving' list. This routine ensures we process supertypes (classes/interfaces) of
- * 'typeToWeave' that are in the 'typesForWeaving' list before 'typeToWeave' itself. 'typesToWeave' is then removed from the
- * 'typesForWeaving' list.
- *
- * Note: Future gotcha in here ... when supplying partial hierarchies, this algorithm may break down. If you have a hierarchy
- * A>B>C and only give A and C to the weaver, it may choose to weave them in either order - but you'll probably have other
- * problems if you are supplying partial hierarchies like that !
- */
- private void weaveParentsFor(List<String> typesForWeaving, String typeToWeave, ResolvedType resolvedTypeToWeave) {
- if (resolvedTypeToWeave == null) {
- // resolve it if the caller could not pass in the resolved type
- resolvedTypeToWeave = world.resolve(typeToWeave);
- }
- ResolvedType superclassType = resolvedTypeToWeave.getSuperclass();
- String superclassTypename = (superclassType == null ? null : superclassType.getName());
-
- // PR336654 added the 'typesForWeaving.contains(superclassTypename)' clause.
- // Without it we can delete all type mungers on the parents and yet we only
- // add back in the declare parents related ones, not the regular ITDs.
- if (superclassType != null && !superclassType.isTypeHierarchyComplete() && superclassType.isExposedToWeaver()
- && typesForWeaving.contains(superclassTypename)) {
- weaveParentsFor(typesForWeaving, superclassTypename, superclassType);
- }
-
- ResolvedType[] interfaceTypes = resolvedTypeToWeave.getDeclaredInterfaces();
- for (ResolvedType resolvedSuperInterface : interfaceTypes) {
- if (!resolvedSuperInterface.isTypeHierarchyComplete()) {
- String interfaceTypename = resolvedSuperInterface.getName();
- if (resolvedSuperInterface.isExposedToWeaver()) { // typesForWeaving.contains(interfaceTypename)) {
- weaveParentsFor(typesForWeaving, interfaceTypename, resolvedSuperInterface);
- }
- }
- }
- ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_DECLARE_PARENTS,
- resolvedTypeToWeave.getName());
- // If A was processed before B (and was declared 'class A implements B') then there is no need to complete B again, it
- // will have been done whilst processing A.
- if (!resolvedTypeToWeave.isTypeHierarchyComplete()) {
- weaveParentTypeMungers(resolvedTypeToWeave);
- }
- CompilationAndWeavingContext.leavingPhase(tok);
- typesForWeaving.remove(typeToWeave);
- resolvedTypeToWeave.tagAsTypeHierarchyComplete();
- }
-
- public void prepareToProcessReweavableState() {
- }
-
- public void processReweavableStateIfPresent(String className, BcelObjectType classType) {
- // If the class is marked reweavable, check any aspects around when it
- // was built are in this world
- WeaverStateInfo wsi = classType.getWeaverState();
- // System.out.println(">> processReweavableStateIfPresent " + className + " wsi=" + wsi);
- if (wsi != null && wsi.isReweavable()) { // Check all necessary types
- // are around!
- world.showMessage(IMessage.INFO, WeaverMessages.format(WeaverMessages.PROCESSING_REWEAVABLE, className, classType
- .getSourceLocation().getSourceFile()), null, null);
- Set<String> aspectsPreviouslyInWorld = wsi.getAspectsAffectingType();
- // keep track of them just to ensure unique missing aspect error
- // reporting
- Set<String> alreadyConfirmedReweavableState = new HashSet<String>();
- for (String requiredTypeSignature : aspectsPreviouslyInWorld) {
- // for (Iterator iter = aspectsPreviouslyInWorld.iterator(); iter.hasNext();) {
- // String requiredTypeName = (String) iter.next();
- if (!alreadyConfirmedReweavableState.contains(requiredTypeSignature)) {
- ResolvedType rtx = world.resolve(UnresolvedType.forSignature(requiredTypeSignature), true);
- boolean exists = !rtx.isMissing();
- if (!world.isOverWeaving()) {
- if (!exists) {
- world.getLint().missingAspectForReweaving.signal(new String[] { rtx.getName(), className },
- classType.getSourceLocation(), null);
- // world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.MISSING_REWEAVABLE_TYPE,
- // requiredTypeName, className), classType.getSourceLocation(), null);
- } else {
- // weaved in aspect that are not declared in aop.xml
- // trigger an error for now
- // may cause headhache for LTW and packaged lib
- // without aop.xml in
- // see #104218
- if (!xcutSet.containsAspect(rtx)) {
- world.showMessage(IMessage.ERROR, WeaverMessages.format(
- WeaverMessages.REWEAVABLE_ASPECT_NOT_REGISTERED, rtx.getName(), className), null, null);
- } else if (!world.getMessageHandler().isIgnoring(IMessage.INFO)) {
- world.showMessage(IMessage.INFO, WeaverMessages.format(WeaverMessages.VERIFIED_REWEAVABLE_TYPE,
- rtx.getName(), rtx.getSourceLocation().getSourceFile()), null, null);
- }
- alreadyConfirmedReweavableState.add(requiredTypeSignature);
- }
- }
- }
- }
- // old:
- // classType.setJavaClass(Utility.makeJavaClass(classType.getJavaClass
- // ().getFileName(), wsi.getUnwovenClassFileData()));
- // new: reweavable default with clever diff
- if (!world.isOverWeaving()) {
- byte[] ucfd = wsi.getUnwovenClassFileData();
- if (ucfd.length == 0) {
- // Size 0 indicates the class was previously overwoven, so you need to be overweaving now!
- world.getMessageHandler().handleMessage(
- MessageUtil.error(
- WeaverMessages.format(WeaverMessages.MUST_KEEP_OVERWEAVING_ONCE_START,
- className)));
-// onType.getName(), annoX.getTypeName(), annoX.getValidTargets()),
-// decA.getSourceLocation()));
- } else {
- byte[] bytes = wsi.getUnwovenClassFileData(classType.getJavaClass().getBytes());
- JavaClass newJavaClass = Utility.makeJavaClass(classType.getJavaClass().getFileName(), bytes);
- classType.setJavaClass(newJavaClass, true);
- classType.getResolvedTypeX().ensureConsistent();
- }
- }
- // } else {
- // classType.resetState();
- }
- }
-
- private void weaveAndNotify(UnwovenClassFile classFile, BcelObjectType classType, IWeaveRequestor requestor) throws IOException {
- trace.enter("weaveAndNotify", this, new Object[] { classFile, classType, requestor });
-
- ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_TYPE, classType
- .getResolvedTypeX().getName());
- LazyClassGen clazz = weaveWithoutDump(classFile, classType);
- classType.finishedWith();
- // clazz is null if the classfile was unchanged by weaving...
- if (clazz != null) {
- UnwovenClassFile[] newClasses = getClassFilesFor(clazz);
- // OPTIMIZE can we avoid using the string name at all in
- // UnwovenClassFile instances?
- // 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]);
- }
- } else {
- requestor.acceptResult(classFile);
- }
- classType.weavingCompleted();
- CompilationAndWeavingContext.leavingPhase(tok);
-
- trace.exit("weaveAndNotify");
- }
-
- /**
- * helper method - will return NULL if the underlying delegate is an EclipseSourceType and not a BcelObjectType
- */
- public BcelObjectType getClassType(String forClass) {
- return BcelWorld.getBcelObjectType(world.resolve(forClass));
- }
-
- public void addParentTypeMungers(String typeName) {
- weaveParentTypeMungers(world.resolve(typeName));
- }
-
- public void addNormalTypeMungers(String typeName) {
- weaveNormalTypeMungers(world.resolve(typeName));
- }
-
- public UnwovenClassFile[] getClassFilesFor(LazyClassGen clazz) {
- List<UnwovenClassFile.ChildClass> childClasses = clazz.getChildClasses(world);
- UnwovenClassFile[] ret = new UnwovenClassFile[1 + childClasses.size()];
- ret[0] = new UnwovenClassFile(clazz.getFileName(), clazz.getClassName(), clazz.getJavaClassBytesIncludingReweavable(world));
- int index = 1;
- for (Iterator<UnwovenClassFile.ChildClass> iter = childClasses.iterator(); iter.hasNext();) {
- UnwovenClassFile.ChildClass element = iter.next();
- UnwovenClassFile childClass = new UnwovenClassFile(clazz.getFileName() + "$" + element.name, element.bytes);
- ret[index++] = childClass;
- }
- return ret;
- }
-
- /**
- * Weaves new parents and annotations onto a type ("declare parents" and "declare @type")
- *
- * Algorithm: 1. First pass, do parents then do annotations. During this pass record: - any parent mungers that don't match but
- * have a non-wild annotation type pattern - any annotation mungers that don't match 2. Multiple subsequent passes which go over
- * the munger lists constructed in the first pass, repeatedly applying them until nothing changes. FIXME asc confirm that
- * algorithm is optimal ??
- */
- public void weaveParentTypeMungers(ResolvedType onType) {
- if (onType.isRawType() || onType.isParameterizedType()) {
- onType = onType.getGenericType();
- }
- onType.clearInterTypeMungers();
-
- List<DeclareParents> decpToRepeat = new ArrayList<DeclareParents>();
-
- boolean aParentChangeOccurred = false;
- boolean anAnnotationChangeOccurred = false;
- // First pass - apply all decp mungers
- for (DeclareParents decp : declareParentsList) {
- boolean typeChanged = applyDeclareParents(decp, onType);
- if (typeChanged) {
- aParentChangeOccurred = true;
- } else {
- decpToRepeat.add(decp);
- }
- }
-
- // Still first pass - apply all dec @type mungers
- for (DeclareAnnotation decA : xcutSet.getDeclareAnnotationOnTypes()) {
- boolean typeChanged = applyDeclareAtType(decA, onType, true);
- if (typeChanged) {
- anAnnotationChangeOccurred = true;
- }
- }
-
- while ((aParentChangeOccurred || anAnnotationChangeOccurred) && !decpToRepeat.isEmpty()) {
- anAnnotationChangeOccurred = aParentChangeOccurred = false;
- List<DeclareParents> decpToRepeatNextTime = new ArrayList<DeclareParents>();
- for (Iterator<DeclareParents> iter = decpToRepeat.iterator(); iter.hasNext();) {
- DeclareParents decp = iter.next();
- boolean typeChanged = applyDeclareParents(decp, onType);
- if (typeChanged) {
- aParentChangeOccurred = true;
- } else {
- decpToRepeatNextTime.add(decp);
- }
- }
-
- for (DeclareAnnotation decA : xcutSet.getDeclareAnnotationOnTypes()) {
- boolean typeChanged = applyDeclareAtType(decA, onType, false);
- if (typeChanged) {
- anAnnotationChangeOccurred = true;
- }
- }
- decpToRepeat = decpToRepeatNextTime;
- }
- }
-
- /**
- * Apply a declare @type - return true if we change the type
- */
- private boolean applyDeclareAtType(DeclareAnnotation decA, ResolvedType onType, boolean reportProblems) {
- boolean didSomething = false;
- if (decA.matches(onType)) {
- AnnotationAJ theAnnotation = decA.getAnnotation();
- // can be null for broken code!
- if (theAnnotation == null) {
- return false;
- }
- if (onType.hasAnnotation(theAnnotation.getType())) {
- // Could put out a lint here for an already annotated type ...
- // if (reportProblems) {
- // world.getLint().elementAlreadyAnnotated.signal(
- // new
- // String[]{onType.toString(),decA.getAnnotationTypeX().toString
- // ()},
- // onType.getSourceLocation(),new
- // ISourceLocation[]{decA.getSourceLocation()});
- // }
- return false;
- }
-
- AnnotationAJ annoX = decA.getAnnotation();
-
- // check the annotation is suitable for the target
- boolean problemReported = verifyTargetIsOK(decA, onType, annoX, reportProblems);
-
- if (!problemReported) {
- AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(), decA.getSourceLocation(),
- onType.getSourceLocation(), false);
- // TAG: WeavingMessage
- if (!getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
- getWorld().getMessageHandler().handleMessage(
- WeaveMessage.constructWeavingMessage(
- WeaveMessage.WEAVEMESSAGE_ANNOTATES,
- new String[] { onType.toString(), Utility.beautifyLocation(onType.getSourceLocation()),
- decA.getAnnotationString(), "type", decA.getAspect().toString(),
- Utility.beautifyLocation(decA.getSourceLocation()) }));
- }
- didSomething = true;
- ResolvedTypeMunger newAnnotationTM = new AnnotationOnTypeMunger(annoX);
- newAnnotationTM.setSourceLocation(decA.getSourceLocation());
- onType.addInterTypeMunger(new BcelTypeMunger(newAnnotationTM, decA.getAspect().resolve(world)), false);
- decA.copyAnnotationTo(onType);
- }
- }
- return didSomething;
- }
-
- /**
- * Checks for an @target() on the annotation and if found ensures it allows the annotation to be attached to the target type
- * that matched.
- */
- private boolean verifyTargetIsOK(DeclareAnnotation decA, ResolvedType onType, AnnotationAJ annoX, boolean outputProblems) {
- boolean problemReported = false;
- if (annoX.specifiesTarget()) {
- if ((onType.isAnnotation() && !annoX.allowedOnAnnotationType()) || (!annoX.allowedOnRegularType())) {
- if (outputProblems) {
- if (decA.isExactPattern()) {
- world.getMessageHandler().handleMessage(
- MessageUtil.error(
- WeaverMessages.format(WeaverMessages.INCORRECT_TARGET_FOR_DECLARE_ANNOTATION,
- onType.getName(), annoX.getTypeName(), annoX.getValidTargets()),
- decA.getSourceLocation()));
- } else {
- if (world.getLint().invalidTargetForAnnotation.isEnabled()) {
- world.getLint().invalidTargetForAnnotation.signal(new String[] { onType.getName(), annoX.getTypeName(),
- annoX.getValidTargets() }, decA.getSourceLocation(),
- new ISourceLocation[] { onType.getSourceLocation() });
- }
- }
- }
- problemReported = true;
- }
- }
- return problemReported;
- }
-
- /**
- * Apply a single declare parents - return true if we change the type
- */
- private boolean applyDeclareParents(DeclareParents p, ResolvedType onType) {
- boolean didSomething = false;
- List<ResolvedType> newParents = p.findMatchingNewParents(onType, true);
- if (!newParents.isEmpty()) {
- didSomething = true;
- BcelWorld.getBcelObjectType(onType);
- // System.err.println("need to do declare parents for: " + onType);
- for (ResolvedType newParent : newParents) {
- // We set it here so that the imminent matching for ITDs can
- // succeed - we still haven't done the necessary changes to the class file
- // itself (like transform super calls) - that is done in
- // BcelTypeMunger.mungeNewParent()
- // classType.addParent(newParent);
- onType.addParent(newParent);
- NewParentTypeMunger newParentMunger = new NewParentTypeMunger(newParent, p.getDeclaringType());
- if (p.isMixin()) {
- newParentMunger.setIsMixin(true);
- }
- newParentMunger.setSourceLocation(p.getSourceLocation());
- onType.addInterTypeMunger(new BcelTypeMunger(newParentMunger, xcutSet.findAspectDeclaringParents(p)), false);
- }
- }
- return didSomething;
- }
-
- public void weaveNormalTypeMungers(ResolvedType onType) {
- ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_TYPE_MUNGERS,
- onType.getName());
- if (onType.isRawType() || onType.isParameterizedType()) {
- onType = onType.getGenericType();
- }
- for (ConcreteTypeMunger m : typeMungerList) {
- if (!m.isLateMunger() && m.matches(onType)) {
- onType.addInterTypeMunger(m, false);
- }
- }
- CompilationAndWeavingContext.leavingPhase(tok);
- }
-
- // exposed for ClassLoader dynamic weaving
- public LazyClassGen weaveWithoutDump(UnwovenClassFile classFile, BcelObjectType classType) throws IOException {
- return weave(classFile, classType, false);
- }
-
- // FOR TESTING
- LazyClassGen weave(UnwovenClassFile classFile, BcelObjectType classType) throws IOException {
- LazyClassGen ret = weave(classFile, classType, true);
- return ret;
- }
-
- private LazyClassGen weave(UnwovenClassFile classFile, BcelObjectType classType, boolean dump) throws IOException {
-
- try {
- if (classType.isSynthetic()) { // Don't touch synthetic classes
- if (dump) {
- dumpUnchanged(classFile);
- }
- return null;
- }
- ReferenceType resolvedClassType = classType.getResolvedTypeX();
-
- if (world.isXmlConfigured() && world.getXmlConfiguration().excludesType(resolvedClassType)) {
- if (!world.getMessageHandler().isIgnoring(IMessage.INFO)) {
- world.getMessageHandler().handleMessage(
- MessageUtil.info("Type '" + resolvedClassType.getName()
- + "' not woven due to exclusion via XML weaver exclude section"));
-
- }
- if (dump) {
- dumpUnchanged(classFile);
- }
- return null;
- }
-
- List<ShadowMunger> shadowMungers = fastMatch(shadowMungerList, resolvedClassType);
- List<ConcreteTypeMunger> typeMungers = classType.getResolvedTypeX().getInterTypeMungers();
-
- resolvedClassType.checkInterTypeMungers();
-
- // Decide if we need to do actual weaving for this class
- boolean mightNeedToWeave = shadowMungers.size() > 0 || typeMungers.size() > 0 || classType.isAspect()
- || world.getDeclareAnnotationOnMethods().size() > 0 || world.getDeclareAnnotationOnFields().size() > 0;
-
- // May need bridge methods if on 1.5 and something in our hierarchy is
- // affected by ITDs
- boolean mightNeedBridgeMethods = world.isInJava5Mode() && !classType.isInterface()
- && resolvedClassType.getInterTypeMungersIncludingSupers().size() > 0;
-
- LazyClassGen clazz = null;
- if (mightNeedToWeave || mightNeedBridgeMethods) {
- clazz = classType.getLazyClassGen();
- // System.err.println("got lazy gen: " + clazz + ", " +
- // clazz.getWeaverState());
- try {
- boolean isChanged = false;
-
- if (mightNeedToWeave) {
- isChanged = BcelClassWeaver.weave(world, clazz, shadowMungers, typeMungers, lateTypeMungerList,
- inReweavableMode);
- }
-
- checkDeclareTypeErrorOrWarning(world, classType);
-
- if (mightNeedBridgeMethods) {
- isChanged = BcelClassWeaver.calculateAnyRequiredBridgeMethods(world, clazz) || isChanged;
- }
-
- if (isChanged) {
- if (dump) {
- dump(classFile, clazz);
- }
- return clazz;
- }
- } catch (RuntimeException re) {
- String classDebugInfo = null;
- try {
- classDebugInfo = clazz.toLongString();
- } catch (Throwable e) {
- new RuntimeException("Crashed whilst crashing with this exception: " + e, e).printStackTrace();
- // recover from crash whilst producing debug string
- classDebugInfo = clazz.getClassName();
- }
- String messageText = "trouble in: \n" + classDebugInfo;
- getWorld().getMessageHandler().handleMessage(new Message(messageText, IMessage.ABORT, re, null));
- } catch (Error re) {
- String classDebugInfo = null;
- try {
- classDebugInfo = clazz.toLongString();
- } catch (OutOfMemoryError oome) {
- System.err.println("Ran out of memory creating debug info for an error");
- re.printStackTrace(System.err);
- // recover from crash whilst producing debug string
- classDebugInfo = clazz.getClassName();
- } catch (Throwable e) {
- // recover from crash whilst producing debug string
- classDebugInfo = clazz.getClassName();
- }
- String messageText = "trouble in: \n" + classDebugInfo;
- getWorld().getMessageHandler().handleMessage(new Message(messageText, IMessage.ABORT, re, null));
- }
- } else {
- checkDeclareTypeErrorOrWarning(world, classType);
- }
- // this is very odd return behavior trying to keep everyone happy
-
- // can we remove it from the model now? we know it contains no relationship endpoints...
- AsmManager model = world.getModelAsAsmManager();
- if (world.isMinimalModel() && model != null && !classType.isAspect()) {
- AspectJElementHierarchy hierarchy = (AspectJElementHierarchy) model.getHierarchy();
- String pkgname = classType.getResolvedTypeX().getPackageName();
- String tname = classType.getResolvedTypeX().getSimpleBaseName();
- IProgramElement typeElement = hierarchy.findElementForType(pkgname, tname);
- if (typeElement != null && hasInnerType(typeElement)) {
- // Cannot remove it right now (has inner type), schedule it
- // for possible deletion later if all inner types are
- // removed
- candidatesForRemoval.add(typeElement);
- }
- if (typeElement != null && !hasInnerType(typeElement)) {
- IProgramElement parent = typeElement.getParent();
- // parent may have children: PACKAGE DECL, IMPORT-REFERENCE, TYPE_DECL
- if (parent != null) {
- // if it was the only type we should probably remove
- // the others too.
- parent.removeChild(typeElement);
- if (parent.getKind().isSourceFile()) {
- removeSourceFileIfNoMoreTypeDeclarationsInside(hierarchy, typeElement, parent);
- } else {
- hierarchy.forget(null, typeElement);
- // At this point, the child has been removed. We
- // should now check if the parent is in our
- // 'candidatesForRemoval' set. If it is then that
- // means we were going to remove it but it had a
- // child. Now we can check if it still has a child -
- // if it doesn't it can also be removed!
-
- walkUpRemovingEmptyTypesAndPossiblyEmptySourceFile(hierarchy, tname, parent);
- }
-
- }
- }
- }
-
- if (dump) {
- dumpUnchanged(classFile);
- return clazz;
- } else {
- // ATAJ: the class was not weaved, but since it gets there early it
- // may have new generated inner classes
- // attached to it to support LTW perX aspectOf support (see
- // BcelPerClauseAspectAdder)
- // that aggressively defines the inner <aspect>$mayHaveAspect
- // interface.
- if (clazz != null && !clazz.getChildClasses(world).isEmpty()) {
- return clazz;
- }
- return null;
- }
- } finally {
- world.demote();
- }
- }
-
- private void walkUpRemovingEmptyTypesAndPossiblyEmptySourceFile(AspectJElementHierarchy hierarchy, String tname,
- IProgramElement typeThatHasChildRemoved) {
- // typeThatHasChildRemoved might be a source file, type or a method/ctor
- // - for a method/ctor find the type/sourcefile
- while (typeThatHasChildRemoved != null
- && !(typeThatHasChildRemoved.getKind().isType() || typeThatHasChildRemoved.getKind().isSourceFile())) {
- // this will take us 'up' through methods that contain anonymous
- // inner classes
- typeThatHasChildRemoved = typeThatHasChildRemoved.getParent();
- }
- // now typeThatHasChildRemoved points to the type or sourcefile that has
- // had something removed
- if (candidatesForRemoval.contains(typeThatHasChildRemoved) && !hasInnerType(typeThatHasChildRemoved)) {
- // now we can get rid of it
- IProgramElement parent = typeThatHasChildRemoved.getParent();
- if (parent != null) {
- parent.removeChild(typeThatHasChildRemoved);
- candidatesForRemoval.remove(typeThatHasChildRemoved);
- if (parent.getKind().isSourceFile()) {
- removeSourceFileIfNoMoreTypeDeclarationsInside(hierarchy, typeThatHasChildRemoved, parent);
- // System.out.println("Removed on second pass: " +
- // typeThatHasChildRemoved.getName());
- } else {
- // System.out.println("On later pass, parent of type " +
- // typeThatHasChildRemoved.getName()
- // + " was found not to be a sourcefile, recursing up...");
- walkUpRemovingEmptyTypesAndPossiblyEmptySourceFile(hierarchy, tname, parent);
- }
- }
- }
- }
-
- private void removeSourceFileIfNoMoreTypeDeclarationsInside(AspectJElementHierarchy hierarchy, IProgramElement typeElement,
- IProgramElement sourceFileNode) {
- IProgramElement compilationUnit = sourceFileNode;
- boolean anyOtherTypeDeclarations = false;
- for (IProgramElement child : compilationUnit.getChildren()) {
- IProgramElement.Kind k = child.getKind();
- if (k.isType()) {
- anyOtherTypeDeclarations = true;
- break;
- }
- }
- // If the compilation unit node contained no
- // other types, there is no need to keep it
- if (!anyOtherTypeDeclarations) {
- IProgramElement cuParent = compilationUnit.getParent();
- if (cuParent != null) {
- compilationUnit.setParent(null);
- cuParent.removeChild(compilationUnit);
- }
- // need to update some caches and structures too?
- hierarchy.forget(sourceFileNode, typeElement);
- } else {
- hierarchy.forget(null, typeElement);
- }
- }
-
- // ---- writing
-
- // TODO could be smarter - really only matters if inner type has been woven, but there is a chance we haven't woven it *yet*
- private boolean hasInnerType(IProgramElement typeNode) {
- for (IProgramElement child : typeNode.getChildren()) {
- IProgramElement.Kind kind = child.getKind();
- if (kind.isType()) {
- return true;
- }
- // if (kind == IProgramElement.Kind.ASPECT) {
- // return true;
- // }
- if (kind.isType() || kind == IProgramElement.Kind.METHOD || kind == IProgramElement.Kind.CONSTRUCTOR) {
- boolean b = hasInnerType(child);
- if (b) {
- return b;
- }
- }
- }
- return false;
- }
-
- private void checkDeclareTypeErrorOrWarning(BcelWorld world2, BcelObjectType classType) {
- List<DeclareTypeErrorOrWarning> dteows = world.getDeclareTypeEows();
- for (DeclareTypeErrorOrWarning dteow : dteows) {
- if (dteow.getTypePattern().matchesStatically(classType.getResolvedTypeX())) {
- if (dteow.isError()) {
- world.getMessageHandler().handleMessage(
- MessageUtil.error(dteow.getMessage(), classType.getResolvedTypeX().getSourceLocation()));
- } else {
- world.getMessageHandler().handleMessage(
- MessageUtil.warn(dteow.getMessage(), classType.getResolvedTypeX().getSourceLocation()));
- }
- }
- }
- }
-
- private void dumpUnchanged(UnwovenClassFile classFile) throws IOException {
- if (zipOutputStream != null) {
- writeZipEntry(getEntryName(classFile.getJavaClass().getClassName()), classFile.getBytes());
- } else {
- classFile.writeUnchangedBytes();
- }
- }
-
- private String getEntryName(String className) {
- // XXX what does bcel's getClassName do for inner names
- return className.replace('.', '/') + ".class";
- }
-
- private void dump(UnwovenClassFile classFile, LazyClassGen clazz) throws IOException {
- if (zipOutputStream != null) {
- String mainClassName = classFile.getJavaClass().getClassName();
- writeZipEntry(getEntryName(mainClassName), clazz.getJavaClass(world).getBytes());
- List<UnwovenClassFile.ChildClass> childClasses = clazz.getChildClasses(world);
- if (!childClasses.isEmpty()) {
- for (Iterator<UnwovenClassFile.ChildClass> i = childClasses.iterator(); i.hasNext();) {
- UnwovenClassFile.ChildClass c = i.next();
- writeZipEntry(getEntryName(mainClassName + "$" + c.name), c.bytes);
- }
- }
- } else {
- classFile.writeWovenBytes(clazz.getJavaClass(world).getBytes(), clazz.getChildClasses(world));
- }
- }
-
- private void writeZipEntry(String name, byte[] bytes) throws IOException {
- ZipEntry newEntry = new ZipEntry(name); // ??? get compression scheme
- // right
-
- zipOutputStream.putNextEntry(newEntry);
- zipOutputStream.write(bytes);
- zipOutputStream.closeEntry();
- }
-
- /**
- * Perform a fast match of the specified list of shadowmungers against the specified type. A subset of those that might match is
- * returned.
- *
- * @param list list of all shadow mungers that might match
- * @param type the target type
- * @return a list of shadow mungers that might match with those that cannot (according to fast match rules) removed
- */
- private List<ShadowMunger> fastMatch(List<ShadowMunger> list, ResolvedType type) {
- if (list == null) {
- return Collections.emptyList();
- }
- boolean isOverweaving = world.isOverWeaving();
- WeaverStateInfo typeWeaverState = (isOverweaving ? type.getWeaverState() : null);
-
- // here we do the coarsest grained fast match with no kind constraints
- // this will remove all obvious non-matches and see if we need to do any
- // weaving
- FastMatchInfo info = new FastMatchInfo(type, null, world);
-
- List<ShadowMunger> result = new ArrayList<ShadowMunger>();
-
- if (world.areInfoMessagesEnabled() && world.isTimingEnabled()) {
- for (ShadowMunger munger : list) {
- if (typeWeaverState != null) { // will only be null if overweaving is ON and there is weaverstate
- ResolvedType declaringAspect = munger.getDeclaringType();
- if (typeWeaverState.isAspectAlreadyApplied(declaringAspect)) {
- continue;
- }
- }
- Pointcut pointcut = munger.getPointcut();
- long starttime = System.nanoTime();
- FuzzyBoolean fb = pointcut.fastMatch(info);
- long endtime = System.nanoTime();
- world.recordFastMatch(pointcut, endtime - starttime);
- if (fb.maybeTrue()) {
- result.add(munger);
- }
- }
- } else {
- for (ShadowMunger munger : list) {
- if (typeWeaverState != null) { // will only be null if overweaving is ON and there is weaverstate
- ResolvedType declaringAspect = munger.getConcreteAspect();// getDeclaringType();
- if (typeWeaverState.isAspectAlreadyApplied(declaringAspect)) {
- continue;
- }
- }
- Pointcut pointcut = munger.getPointcut();
- FuzzyBoolean fb = pointcut.fastMatch(info);
- if (fb.maybeTrue()) {
- result.add(munger);
- }
- }
- }
- return result;
- }
-
- public void setReweavableMode(boolean xNotReweavable) {
- inReweavableMode = !xNotReweavable;
- WeaverStateInfo.setReweavableModeDefaults(!xNotReweavable, false, true);
- }
-
- public boolean isReweavable() {
- return inReweavableMode;
- }
-
- public World getWorld() {
- return world;
- }
-
- public void tidyUp() {
- if (trace.isTraceEnabled()) {
- trace.enter("tidyUp", this);
- }
- shadowMungerList = null; // setup by prepareForWeave
- typeMungerList = null; // setup by prepareForWeave
- lateTypeMungerList = null; // setup by prepareForWeave
- declareParentsList = null; // setup by prepareForWeave
- if (trace.isTraceEnabled()) {
- trace.exit("tidyUp");
- }
- }
-
- public void write(CompressingDataOutputStream dos) throws IOException {
- xcutSet.write(dos);
- }
-
- // only called for testing
- public void setShadowMungers(List<ShadowMunger> shadowMungers) {
- shadowMungerList = shadowMungers;
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeavingSupport.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeavingSupport.java
deleted file mode 100644
index 120df80c2..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelWeavingSupport.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/* *******************************************************************
- * 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.bcel;
-
-import org.aspectj.weaver.Advice;
-import org.aspectj.weaver.AjAttribute;
-import org.aspectj.weaver.ConcreteTypeMunger;
-import org.aspectj.weaver.IWeavingSupport;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.ResolvedTypeMunger;
-import org.aspectj.weaver.ast.Var;
-import org.aspectj.weaver.patterns.PerClause;
-import org.aspectj.weaver.patterns.Pointcut;
-
-/**
- * Bcel implementation of the weaving support required in a BcelWorld which will actually modify bytecode.
- *
- * @author Andy Clement
- */
-public class BcelWeavingSupport implements IWeavingSupport {
-
- public Advice createAdviceMunger(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member signature,
- ResolvedType concreteAspect) {
- // System.err.println("concrete advice: " + signature + " context " +
- // sourceContext);
- return new BcelAdvice(attribute, pointcut, signature, concreteAspect);
- }
-
- public ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField) {
- return new BcelCflowStackFieldAdder(cflowField);
- }
-
- public ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField) {
- return new BcelCflowCounterFieldAdder(cflowField);
- }
-
- /**
- * Register a munger for perclause @AJ aspect so that we add aspectOf(..) to them as needed
- *
- * @param aspect
- * @param kind
- * @return munger
- */
- public ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, PerClause.Kind kind) {
- return new BcelPerClauseAspectAdder(aspect, kind);
- }
-
- public Var makeCflowAccessVar(ResolvedType formalType, Member cflowField, int arrayIndex) {
- return new BcelCflowAccessVar(formalType, cflowField, arrayIndex);
- }
-
- public ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) {
- return new BcelTypeMunger(munger, aspectType);
- }
-
- public ConcreteTypeMunger createAccessForInlineMunger(ResolvedType aspect) {
- return new BcelAccessForInlineMunger(aspect);
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java b/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java
deleted file mode 100644
index 4ade1e125..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java
+++ /dev/null
@@ -1,1329 +0,0 @@
-/* *******************************************************************
- * 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
- * Alexandre Vasseur perClause support for @AJ aspects
- * ******************************************************************/
-
-package org.aspectj.weaver.bcel;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Modifier;
-import java.net.MalformedURLException;
-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.StringTokenizer;
-
-import org.aspectj.apache.bcel.Constants;
-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.generic.FieldInstruction;
-import org.aspectj.apache.bcel.generic.INVOKEINTERFACE;
-import org.aspectj.apache.bcel.generic.Instruction;
-import org.aspectj.apache.bcel.generic.InstructionHandle;
-import org.aspectj.apache.bcel.generic.InvokeInstruction;
-import org.aspectj.apache.bcel.generic.MULTIANEWARRAY;
-import org.aspectj.apache.bcel.generic.ObjectType;
-import org.aspectj.apache.bcel.generic.Type;
-import org.aspectj.apache.bcel.util.ClassLoaderReference;
-import org.aspectj.apache.bcel.util.ClassLoaderRepository;
-import org.aspectj.apache.bcel.util.ClassPath;
-import org.aspectj.apache.bcel.util.NonCachingClassLoaderRepository;
-import org.aspectj.apache.bcel.util.Repository;
-import org.aspectj.asm.AsmManager;
-import org.aspectj.asm.IRelationship;
-import org.aspectj.asm.internal.CharOperation;
-import org.aspectj.bridge.IMessage;
-import org.aspectj.bridge.IMessageHandler;
-import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.bridge.Message;
-import org.aspectj.bridge.MessageUtil;
-import org.aspectj.bridge.WeaveMessage;
-import org.aspectj.weaver.Advice;
-import org.aspectj.weaver.AdviceKind;
-import org.aspectj.weaver.AnnotationAJ;
-import org.aspectj.weaver.AnnotationOnTypeMunger;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.Checker;
-import org.aspectj.weaver.ICrossReferenceHandler;
-import org.aspectj.weaver.IWeavingSupport;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.MemberImpl;
-import org.aspectj.weaver.MemberKind;
-import org.aspectj.weaver.NewParentTypeMunger;
-import org.aspectj.weaver.ReferenceType;
-import org.aspectj.weaver.ReferenceTypeDelegate;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedMemberImpl;
-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.World;
-import org.aspectj.weaver.loadtime.definition.Definition;
-import org.aspectj.weaver.loadtime.definition.DocumentParser;
-import org.aspectj.weaver.model.AsmRelationshipProvider;
-import org.aspectj.weaver.patterns.DeclareAnnotation;
-import org.aspectj.weaver.patterns.DeclareParents;
-import org.aspectj.weaver.patterns.ParserException;
-import org.aspectj.weaver.patterns.PatternParser;
-import org.aspectj.weaver.patterns.TypePattern;
-import org.aspectj.weaver.tools.Trace;
-import org.aspectj.weaver.tools.TraceFactory;
-
-public class BcelWorld extends World implements Repository {
-
- private final ClassPathManager classPath;
- protected Repository delegate;
- private BcelWeakClassLoaderReference loaderRef;
- private final BcelWeavingSupport bcelWeavingSupport = new BcelWeavingSupport();
- private boolean isXmlConfiguredWorld = false;
- private WeavingXmlConfig xmlConfiguration;
- private List<TypeDelegateResolver> typeDelegateResolvers;
-
- private static Trace trace = TraceFactory.getTraceFactory().getTrace(BcelWorld.class);
-
- public BcelWorld() {
- this("");
- }
-
- public BcelWorld(String cp) {
- this(makeDefaultClasspath(cp), IMessageHandler.THROW, null);
- }
-
- public IRelationship.Kind determineRelKind(ShadowMunger munger) {
- AdviceKind ak = ((Advice) munger).getKind();
- if (ak.getKey() == AdviceKind.Before.getKey()) {
- return IRelationship.Kind.ADVICE_BEFORE;
- } else if (ak.getKey() == AdviceKind.After.getKey()) {
- return IRelationship.Kind.ADVICE_AFTER;
- } else if (ak.getKey() == AdviceKind.AfterThrowing.getKey()) {
- return IRelationship.Kind.ADVICE_AFTERTHROWING;
- } else if (ak.getKey() == AdviceKind.AfterReturning.getKey()) {
- return IRelationship.Kind.ADVICE_AFTERRETURNING;
- } else if (ak.getKey() == AdviceKind.Around.getKey()) {
- return IRelationship.Kind.ADVICE_AROUND;
- } else if (ak.getKey() == AdviceKind.CflowEntry.getKey() || ak.getKey() == AdviceKind.CflowBelowEntry.getKey()
- || ak.getKey() == AdviceKind.InterInitializer.getKey() || ak.getKey() == AdviceKind.PerCflowEntry.getKey()
- || ak.getKey() == AdviceKind.PerCflowBelowEntry.getKey() || ak.getKey() == AdviceKind.PerThisEntry.getKey()
- || ak.getKey() == AdviceKind.PerTargetEntry.getKey() || ak.getKey() == AdviceKind.Softener.getKey()
- || ak.getKey() == AdviceKind.PerTypeWithinEntry.getKey()) {
- // System.err.println("Dont want a message about this: "+ak);
- return null;
- }
- throw new RuntimeException("Shadow.determineRelKind: What the hell is it? " + ak);
- }
-
- @Override
- public void reportMatch(ShadowMunger munger, Shadow shadow) {
- if (getCrossReferenceHandler() != null) {
- getCrossReferenceHandler().addCrossReference(munger.getSourceLocation(), // What is being applied
- shadow.getSourceLocation(), // Where is it being applied
- determineRelKind(munger).getName(), // What kind of advice?
- ((Advice) munger).hasDynamicTests() // Is a runtime test being stuffed in the code?
- );
- }
-
- if (!getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
- reportWeavingMessage(munger, shadow);
- }
-
- if (getModel() != null) {
- AsmRelationshipProvider.addAdvisedRelationship(getModelAsAsmManager(), shadow, munger);
- }
- }
-
- /*
- * Report a message about the advice weave that has occurred. Some messing about to make it pretty ! This code is just asking
- * for an NPE to occur ...
- */
- private void reportWeavingMessage(ShadowMunger munger, Shadow shadow) {
- Advice advice = (Advice) munger;
- AdviceKind aKind = advice.getKind();
- // Only report on interesting advice kinds ...
- if (aKind == null || advice.getConcreteAspect() == null) {
- // We suspect someone is programmatically driving the weaver
- // (e.g. IdWeaveTestCase in the weaver testcases)
- return;
- }
- if (!(aKind.equals(AdviceKind.Before) || aKind.equals(AdviceKind.After) || aKind.equals(AdviceKind.AfterReturning)
- || aKind.equals(AdviceKind.AfterThrowing) || aKind.equals(AdviceKind.Around) || aKind.equals(AdviceKind.Softener))) {
- return;
- }
-
- // synchronized blocks are implemented with multiple monitor_exit instructions in the bytecode
- // (one for normal exit from the method, one for abnormal exit), we only want to tell the user
- // once we have advised the end of the sync block, even though under the covers we will have
- // woven both exit points
- if (shadow.getKind() == Shadow.SynchronizationUnlock) {
- if (advice.lastReportedMonitorExitJoinpointLocation == null) {
- // this is the first time through, let's continue...
- advice.lastReportedMonitorExitJoinpointLocation = shadow.getSourceLocation();
- } else {
- if (areTheSame(shadow.getSourceLocation(), advice.lastReportedMonitorExitJoinpointLocation)) {
- // Don't report it again!
- advice.lastReportedMonitorExitJoinpointLocation = null;
- return;
- }
- // hmmm, this means some kind of nesting is going on, urgh
- advice.lastReportedMonitorExitJoinpointLocation = shadow.getSourceLocation();
- }
- }
-
- String description = advice.getKind().toString();
- String advisedType = shadow.getEnclosingType().getName();
- String advisingType = advice.getConcreteAspect().getName();
- Message msg = null;
- if (advice.getKind().equals(AdviceKind.Softener)) {
- msg = WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_SOFTENS, new String[] { advisedType,
- beautifyLocation(shadow.getSourceLocation()), advisingType, beautifyLocation(munger.getSourceLocation()) },
- advisedType, advisingType);
- } else {
- boolean runtimeTest = advice.hasDynamicTests();
- String joinPointDescription = shadow.toString();
- msg = WeaveMessage
- .constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ADVISES,
- new String[] { joinPointDescription, advisedType, beautifyLocation(shadow.getSourceLocation()),
- description, advisingType, beautifyLocation(munger.getSourceLocation()),
- (runtimeTest ? " [with runtime test]" : "") }, advisedType, advisingType);
- // Boolean.toString(runtimeTest)});
- }
- getMessageHandler().handleMessage(msg);
- }
-
- private boolean areTheSame(ISourceLocation locA, ISourceLocation locB) {
- if (locA == null) {
- return locB == null;
- }
- if (locB == null) {
- return false;
- }
- if (locA.getLine() != locB.getLine()) {
- return false;
- }
- File fA = locA.getSourceFile();
- File fB = locA.getSourceFile();
- if (fA == null) {
- return fB == null;
- }
- if (fB == null) {
- return false;
- }
- return fA.getName().equals(fB.getName());
- }
-
- /*
- * Ensure we report a nice source location - particular in the case where the source info is missing (binary weave).
- */
- private String beautifyLocation(ISourceLocation isl) {
- StringBuffer nice = new StringBuffer();
- if (isl == null || isl.getSourceFile() == null || isl.getSourceFile().getName().indexOf("no debug info available") != -1) {
- nice.append("no debug info available");
- } else {
- // can't use File.getName() as this fails when a Linux box encounters a path created on Windows and vice-versa
- int takeFrom = isl.getSourceFile().getPath().lastIndexOf('/');
- if (takeFrom == -1) {
- takeFrom = isl.getSourceFile().getPath().lastIndexOf('\\');
- }
- int binary = isl.getSourceFile().getPath().lastIndexOf('!');
- if (binary != -1 && binary < takeFrom) {
- // we have been woven by a binary aspect
- String pathToBinaryLoc = isl.getSourceFile().getPath().substring(0, binary + 1);
- if (pathToBinaryLoc.indexOf(".jar") != -1) {
- // only want to add the extra info if we're from a jar file
- int lastSlash = pathToBinaryLoc.lastIndexOf('/');
- if (lastSlash == -1) {
- lastSlash = pathToBinaryLoc.lastIndexOf('\\');
- }
- nice.append(pathToBinaryLoc.substring(lastSlash + 1));
- }
- }
- nice.append(isl.getSourceFile().getPath().substring(takeFrom + 1));
- if (isl.getLine() != 0) {
- nice.append(":").append(isl.getLine());
- }
- // if it's a binary file then also want to give the file name
- if (isl.getSourceFileName() != null) {
- nice.append("(from " + isl.getSourceFileName() + ")");
- }
- }
- return nice.toString();
- }
-
- private static List<String> makeDefaultClasspath(String cp) {
- List<String> classPath = new ArrayList<String>();
- classPath.addAll(getPathEntries(cp));
- classPath.addAll(getPathEntries(ClassPath.getClassPath()));
- return classPath;
-
- }
-
- private static List<String> getPathEntries(String s) {
- List<String> ret = new ArrayList<String>();
- StringTokenizer tok = new StringTokenizer(s, File.pathSeparator);
- while (tok.hasMoreTokens()) {
- ret.add(tok.nextToken());
- }
- return ret;
- }
-
- public BcelWorld(List classPath, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
- // this.aspectPath = new ClassPathManager(aspectPath, handler);
- this.classPath = new ClassPathManager(classPath, handler);
- setMessageHandler(handler);
- setCrossReferenceHandler(xrefHandler);
- // Tell BCEL to use us for resolving any classes
- delegate = this;
- }
-
- public BcelWorld(ClassPathManager cpm, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
- classPath = cpm;
- setMessageHandler(handler);
- setCrossReferenceHandler(xrefHandler);
- // Tell BCEL to use us for resolving any classes
- delegate = this;
- }
-
- /**
- * Build a World from a ClassLoader, for LTW support
- *
- * @param loader
- * @param handler
- * @param xrefHandler
- */
- public BcelWorld(ClassLoader loader, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
- classPath = null;
- loaderRef = new BcelWeakClassLoaderReference(loader);
- setMessageHandler(handler);
- setCrossReferenceHandler(xrefHandler);
- // Tell BCEL to use us for resolving any classes
- // delegate = getClassLoaderRepositoryFor(loader);
- }
-
- public void ensureRepositorySetup() {
- if (delegate == null) {
- delegate = getClassLoaderRepositoryFor(loaderRef);
- }
- }
-
- public Repository getClassLoaderRepositoryFor(ClassLoaderReference loader) {
- if (bcelRepositoryCaching) {
- return new ClassLoaderRepository(loader);
- } else {
- return new NonCachingClassLoaderRepository(loader);
- }
- }
-
- public void addPath(String name) {
- classPath.addPath(name, this.getMessageHandler());
- }
-
- // ---- various interactions with bcel
-
- public static Type makeBcelType(UnresolvedType type) {
- return Type.getType(type.getErasureSignature());
- }
-
- static Type[] makeBcelTypes(UnresolvedType[] types) {
- Type[] ret = new Type[types.length];
- for (int i = 0, len = types.length; i < len; i++) {
- ret[i] = makeBcelType(types[i]);
- }
- return ret;
- }
-
- public static Type[] makeBcelTypes(String[] types) {
- if (types == null || types.length==0 ) {
- return null;
- }
- Type[] ret = new Type[types.length];
- for (int i=0, len=types.length; i<len; i++) {
- ret[i] = makeBcelType(types[i]);
- }
- return ret;
- }
-
- public static Type makeBcelType(String type) {
- return Type.getType(type);
- }
-
-
- static String[] makeBcelTypesAsClassNames(UnresolvedType[] types) {
- String[] ret = new String[types.length];
- for (int i = 0, len = types.length; i < len; i++) {
- ret[i] = types[i].getName();
- }
- return ret;
- }
-
- public static UnresolvedType fromBcel(Type t) {
- return UnresolvedType.forSignature(t.getSignature());
- }
-
- static UnresolvedType[] fromBcel(Type[] ts) {
- UnresolvedType[] ret = new UnresolvedType[ts.length];
- for (int i = 0, len = ts.length; i < len; i++) {
- ret[i] = fromBcel(ts[i]);
- }
- return ret;
- }
-
- public ResolvedType resolve(Type t) {
- return resolve(fromBcel(t));
- }
-
- @Override
- protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) {
- String name = ty.getName();
- ensureAdvancedConfigurationProcessed();
- JavaClass jc = lookupJavaClass(classPath, name);
- if (jc == null) {
- // Anyone else to ask?
- if (typeDelegateResolvers != null) {
- for (TypeDelegateResolver tdr : typeDelegateResolvers) {
- ReferenceTypeDelegate delegate = tdr.getDelegate(ty);
- if (delegate != null) {
- return delegate;
- }
- }
- }
- return null;
- } else {
- return buildBcelDelegate(ty, jc, false, false);
- }
- }
-
- public BcelObjectType buildBcelDelegate(ReferenceType type, JavaClass jc, boolean artificial, boolean exposedToWeaver) {
- BcelObjectType ret = new BcelObjectType(type, jc, artificial, exposedToWeaver);
- return ret;
- }
-
- private JavaClass lookupJavaClass(ClassPathManager classPath, String name) {
- if (classPath == null) {
- try {
- ensureRepositorySetup();
- JavaClass jc = delegate.loadClass(name);
- if (trace.isTraceEnabled()) {
- trace.event("lookupJavaClass", this, new Object[] { name, jc });
- }
- return jc;
- } catch (ClassNotFoundException e) {
- if (trace.isTraceEnabled()) {
- trace.error("Unable to find class '" + name + "' in repository", e);
- }
- return null;
- }
- }
-
- ClassPathManager.ClassFile file = null;
- try {
- file = classPath.find(UnresolvedType.forName(name));
- if (file == null) {
- return null;
- }
- ClassParser parser = new ClassParser(file.getInputStream(), file.getPath());
- JavaClass jc = parser.parse();
- return jc;
- } catch (IOException ioe) {
- if (trace.isTraceEnabled()) {
- trace.error("IOException whilst processing class",ioe);
- }
- return null;
- } finally {
- if (file != null) {
- file.close();
- }
- }
- }
-
- public BcelObjectType addSourceObjectType(JavaClass jc, boolean artificial) {
- return addSourceObjectType(jc.getClassName(), jc, artificial);
- }
-
- public BcelObjectType addSourceObjectType(String classname, JavaClass jc, boolean artificial) {
- BcelObjectType ret = null;
- if (!jc.getClassName().equals(classname)) {
- throw new RuntimeException(jc.getClassName() + "!=" + classname);
- }
- String signature = UnresolvedType.forName(jc.getClassName()).getSignature();
-
- ResolvedType resolvedTypeFromTypeMap = typeMap.get(signature);
-
- if (resolvedTypeFromTypeMap != null && !(resolvedTypeFromTypeMap instanceof ReferenceType)) {
- // what on earth is it then? See pr 112243
- StringBuffer exceptionText = new StringBuffer();
- exceptionText.append("Found invalid (not a ReferenceType) entry in the type map. ");
- exceptionText.append("Signature=[" + signature + "] Found=[" + resolvedTypeFromTypeMap + "] Class=[" + resolvedTypeFromTypeMap.getClass() + "]");
- throw new BCException(exceptionText.toString());
- }
-
- ReferenceType referenceTypeFromTypeMap = (ReferenceType) resolvedTypeFromTypeMap;
-
- if (referenceTypeFromTypeMap == null) {
- if (jc.isGeneric() && isInJava5Mode()) {
- ReferenceType rawType = ReferenceType.fromTypeX(UnresolvedType.forRawTypeName(jc.getClassName()), this);
- ret = buildBcelDelegate(rawType, jc, artificial, true);
- ReferenceType genericRefType = new ReferenceType(UnresolvedType.forGenericTypeSignature(signature,
- ret.getDeclaredGenericSignature()), this);
- rawType.setDelegate(ret);
- genericRefType.setDelegate(ret);
- rawType.setGenericType(genericRefType);
- typeMap.put(signature, rawType);
- } else {
- referenceTypeFromTypeMap = new ReferenceType(signature, this);
- ret = buildBcelDelegate(referenceTypeFromTypeMap, jc, artificial, true);
- typeMap.put(signature, referenceTypeFromTypeMap);
- }
- } else {
- ret = buildBcelDelegate(referenceTypeFromTypeMap, jc, artificial, true);
- }
- return ret;
- }
-
- public BcelObjectType addSourceObjectType(String classname, byte[] bytes, boolean artificial) {
- BcelObjectType retval = null;
- String signature = UnresolvedType.forName(classname).getSignature();
- ResolvedType resolvedTypeFromTypeMap = typeMap.get(signature);
-
- if (resolvedTypeFromTypeMap != null && !(resolvedTypeFromTypeMap instanceof ReferenceType)) {
- // what on earth is it then? See pr 112243
- StringBuffer exceptionText = new StringBuffer();
- exceptionText.append("Found invalid (not a ReferenceType) entry in the type map. ");
- exceptionText.append("Signature=[" + signature + "] Found=[" + resolvedTypeFromTypeMap + "] Class=[" + resolvedTypeFromTypeMap.getClass() + "]");
- throw new BCException(exceptionText.toString());
- }
-
- ReferenceType referenceTypeFromTypeMap = (ReferenceType) resolvedTypeFromTypeMap;
-
- if (referenceTypeFromTypeMap == null) {
- JavaClass jc = Utility.makeJavaClass(classname, bytes);
- if (jc.isGeneric() && isInJava5Mode()) {
- referenceTypeFromTypeMap = ReferenceType.fromTypeX(UnresolvedType.forRawTypeName(jc.getClassName()), this);
- retval = buildBcelDelegate(referenceTypeFromTypeMap, jc, artificial, true);
- ReferenceType genericRefType = new ReferenceType(UnresolvedType.forGenericTypeSignature(signature,
- retval.getDeclaredGenericSignature()), this);
- referenceTypeFromTypeMap.setDelegate(retval);
- genericRefType.setDelegate(retval);
- referenceTypeFromTypeMap.setGenericType(genericRefType);
- typeMap.put(signature, referenceTypeFromTypeMap);
- } else {
- referenceTypeFromTypeMap = new ReferenceType(signature, this);
- retval = buildBcelDelegate(referenceTypeFromTypeMap, jc, artificial, true);
- typeMap.put(signature, referenceTypeFromTypeMap);
- }
- } else {
- ReferenceTypeDelegate existingDelegate = referenceTypeFromTypeMap.getDelegate();
- if (!(existingDelegate instanceof BcelObjectType)) {
- throw new IllegalStateException("For " + classname + " should be BcelObjectType, but is " + existingDelegate.getClass());
- }
- retval = (BcelObjectType) existingDelegate;
- // Note1: If the type is already exposed to the weaver (retval.isExposedToWeaver()) then this is likely
- // to be a hotswap reweave so build a new delegate, don't accidentally use the old data.
- // Note2: Also seen when LTW and another agent precedes the AspectJ agent. Earlier in LTW
- // a type is resolved (and ends up in the typemap but not exposed to the weaver at that time)
- // then later LTW actually is attempted on this type. We end up here with different
- // bytes to the current delegate if the earlier agent has modified them. See PR488216
-// if (retval.isArtificial() || retval.isExposedToWeaver()) {
- retval = buildBcelDelegate(referenceTypeFromTypeMap, Utility.makeJavaClass(classname, bytes), artificial, true);
-// }
- }
- return retval;
- }
-
- void deleteSourceObjectType(UnresolvedType ty) {
- typeMap.remove(ty.getSignature());
- }
-
- public static Member makeFieldJoinPointSignature(LazyClassGen cg, FieldInstruction fi) {
- ConstantPool cpg = cg.getConstantPool();
- return MemberImpl.field(fi.getClassName(cpg),
- (fi.opcode == Constants.GETSTATIC || fi.opcode == Constants.PUTSTATIC) ? Modifier.STATIC : 0, fi.getName(cpg),
- fi.getSignature(cpg));
- }
-
- public Member makeJoinPointSignatureFromMethod(LazyMethodGen mg, MemberKind kind) {
- Member ret = mg.getMemberView();
- if (ret == null) {
- int mods = mg.getAccessFlags();
- if (mg.getEnclosingClass().isInterface()) {
- mods |= Modifier.INTERFACE;
- }
- return new ResolvedMemberImpl(kind, UnresolvedType.forName(mg.getClassName()), mods, fromBcel(mg.getReturnType()),
- mg.getName(), fromBcel(mg.getArgumentTypes()));
- } else {
- return ret;
- }
-
- }
-
- public Member makeJoinPointSignatureForMonitorEnter(LazyClassGen cg, InstructionHandle h) {
- return MemberImpl.monitorEnter();
- }
-
- public Member makeJoinPointSignatureForMonitorExit(LazyClassGen cg, InstructionHandle h) {
- return MemberImpl.monitorExit();
- }
-
- public Member makeJoinPointSignatureForArrayConstruction(LazyClassGen cg, InstructionHandle handle) {
- Instruction i = handle.getInstruction();
- ConstantPool cpg = cg.getConstantPool();
- Member retval = null;
-
- if (i.opcode == Constants.ANEWARRAY) {
- // ANEWARRAY arrayInstruction = (ANEWARRAY)i;
- Type ot = i.getType(cpg);
- UnresolvedType ut = fromBcel(ot);
- ut = UnresolvedType.makeArray(ut, 1);
- retval = MemberImpl.method(ut, Modifier.PUBLIC, UnresolvedType.VOID, "<init>", new ResolvedType[] { INT });
- } else if (i instanceof MULTIANEWARRAY) {
- MULTIANEWARRAY arrayInstruction = (MULTIANEWARRAY) i;
- UnresolvedType ut = null;
- short dimensions = arrayInstruction.getDimensions();
- ObjectType ot = arrayInstruction.getLoadClassType(cpg);
- if (ot != null) {
- ut = fromBcel(ot);
- ut = UnresolvedType.makeArray(ut, dimensions);
- } else {
- Type t = arrayInstruction.getType(cpg);
- ut = fromBcel(t);
- }
- ResolvedType[] parms = new ResolvedType[dimensions];
- for (int ii = 0; ii < dimensions; ii++) {
- parms[ii] = INT;
- }
- retval = MemberImpl.method(ut, Modifier.PUBLIC, UnresolvedType.VOID, "<init>", parms);
-
- } else if (i.opcode == Constants.NEWARRAY) {
- // NEWARRAY arrayInstruction = (NEWARRAY)i;
- Type ot = i.getType();
- UnresolvedType ut = fromBcel(ot);
- retval = MemberImpl.method(ut, Modifier.PUBLIC, UnresolvedType.VOID, "<init>", new ResolvedType[] { INT });
- } else {
- throw new BCException("Cannot create array construction signature for this non-array instruction:" + i);
- }
- return retval;
- }
-
- public Member makeJoinPointSignatureForMethodInvocation(LazyClassGen cg, InvokeInstruction ii) {
- ConstantPool cpg = cg.getConstantPool();
- String name = ii.getName(cpg);
- String declaring = ii.getClassName(cpg);
- UnresolvedType declaringType = null;
-
- String signature = ii.getSignature(cpg);
-
- // 307147
- if (name.startsWith("ajc$privMethod$")) {
- // The invoke is on a privileged accessor. These may be created for different
- // kinds of target, not necessarily just private methods. In bug 307147 it is
- // for a private method. This code is identifying the particular case in 307147
- try {
- declaringType = UnresolvedType.forName(declaring);
- String typeNameAsFoundInAccessorName = declaringType.getName().replace('.', '_');
- int indexInAccessorName = name.lastIndexOf(typeNameAsFoundInAccessorName);
- if (indexInAccessorName != -1) {
- String methodName = name.substring(indexInAccessorName+typeNameAsFoundInAccessorName.length()+1);
- ResolvedType resolvedDeclaringType = declaringType.resolve(this);
- ResolvedMember[] methods = resolvedDeclaringType.getDeclaredMethods();
- for (ResolvedMember method: methods) {
- if (method.getName().equals(methodName) && method.getSignature().equals(signature) && Modifier.isPrivate(method.getModifiers())) {
- return method;
- }
- }
- }
- } catch (Exception e) {
- // Remove this once confident above code isn't having unexpected side effects
- // Added 1.8.7
- e.printStackTrace();
- }
- }
-
- int modifier = (ii instanceof INVOKEINTERFACE) ? Modifier.INTERFACE
- : (ii.opcode == Constants.INVOKESTATIC) ? Modifier.STATIC : (ii.opcode == Constants.INVOKESPECIAL && !name
- .equals("<init>")) ? Modifier.PRIVATE : 0;
-
- // in Java 1.4 and after, static method call of super class within
- // subclass method appears
- // as declared by the subclass in the bytecode - but they are not
- // see #104212
- if (ii.opcode == Constants.INVOKESTATIC) {
- ResolvedType appearsDeclaredBy = resolve(declaring);
- // look for the method there
- for (Iterator<ResolvedMember> iterator = appearsDeclaredBy.getMethods(true, true); iterator.hasNext();) {
- ResolvedMember method = iterator.next();
- if (Modifier.isStatic(method.getModifiers())) {
- if (name.equals(method.getName()) && signature.equals(method.getSignature())) {
- // we found it
- declaringType = method.getDeclaringType();
- break;
- }
- }
- }
- }
-
- if (declaringType == null) {
- if (declaring.charAt(0) == '[') {
- declaringType = UnresolvedType.forSignature(declaring);
- } else {
- declaringType = UnresolvedType.forName(declaring);
- }
- }
- return MemberImpl.method(declaringType, modifier, name, signature);
- }
-
- @Override
- public String toString() {
- StringBuffer buf = new StringBuffer();
- buf.append("BcelWorld(");
- // buf.append(shadowMungerMap);
- buf.append(")");
- return buf.toString();
- }
-
- /**
- * Retrieve a bcel delegate for an aspect - this will return NULL if the delegate is an EclipseSourceType and not a
- * BcelObjectType - this happens quite often when incrementally compiling.
- */
- public static BcelObjectType getBcelObjectType(ResolvedType concreteAspect) {
- if (concreteAspect == null) {
- return null;
- }
- if (!(concreteAspect instanceof ReferenceType)) { // Might be Missing
- return null;
- }
- ReferenceTypeDelegate rtDelegate = ((ReferenceType) concreteAspect).getDelegate();
- if (rtDelegate instanceof BcelObjectType) {
- return (BcelObjectType) rtDelegate;
- } else {
- return null;
- }
- }
-
- public void tidyUp() {
- // At end of compile, close any open files so deletion of those archives
- // is possible
- classPath.closeArchives();
- typeMap.report();
- typeMap.demote(true);
- // ResolvedType.resetPrimitives();
- }
-
- // / The repository interface methods
-
- @Override
- public JavaClass findClass(String className) {
- return lookupJavaClass(classPath, className);
- }
-
- @Override
- public JavaClass loadClass(String className) throws ClassNotFoundException {
- return lookupJavaClass(classPath, className);
- }
-
- @Override
- public void storeClass(JavaClass clazz) {
- // doesn't need to do anything
- }
-
- @Override
- public void removeClass(JavaClass clazz) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public JavaClass loadClass(Class clazz) throws ClassNotFoundException {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void clear() {
- delegate.clear();
- // throw new RuntimeException("Not implemented");
- }
-
- /**
- * The aim of this method is to make sure a particular type is 'ok'. Some operations on the delegate for a type modify it and
- * this method is intended to undo that... see pr85132
- */
- @Override
- public void validateType(UnresolvedType type) {
- ResolvedType result = typeMap.get(type.getSignature());
- if (result == null) {
- return; // We haven't heard of it yet
- }
- if (!result.isExposedToWeaver()) {
- return; // cant need resetting
- }
- result.ensureConsistent();
- // If we want to rebuild it 'from scratch' then:
- // ClassParser cp = new ClassParser(new
- // ByteArrayInputStream(newbytes),new String(cs));
- // try {
- // rt.setDelegate(makeBcelObjectType(rt,cp.parse(),true));
- // } catch (ClassFormatException e) {
- // e.printStackTrace();
- // } catch (IOException e) {
- // e.printStackTrace();
- // }
- }
-
- /**
- * Apply a single declare parents - return true if we change the type
- */
- private boolean applyDeclareParents(DeclareParents p, ResolvedType onType) {
- boolean didSomething = false;
- List<ResolvedType> newParents = p.findMatchingNewParents(onType, true);
- if (!newParents.isEmpty()) {
- didSomething = true;
- BcelObjectType classType = BcelWorld.getBcelObjectType(onType);
- // System.err.println("need to do declare parents for: " + onType);
- for (ResolvedType newParent : newParents) {
- // We set it here so that the imminent matching for ITDs can
- // succeed - we still haven't done the necessary changes to the class file
- // itself (like transform super calls) - that is done in
- // BcelTypeMunger.mungeNewParent()
- // classType.addParent(newParent);
- onType.addParent(newParent);
- ResolvedTypeMunger newParentMunger = new NewParentTypeMunger(newParent, p.getDeclaringType());
- newParentMunger.setSourceLocation(p.getSourceLocation());
- onType.addInterTypeMunger(new BcelTypeMunger(newParentMunger, getCrosscuttingMembersSet()
- .findAspectDeclaringParents(p)), false);
- }
- }
- return didSomething;
- }
-
- /**
- * Apply a declare @type - return true if we change the type
- */
- private boolean applyDeclareAtType(DeclareAnnotation decA, ResolvedType onType, boolean reportProblems) {
- boolean didSomething = false;
- if (decA.matches(onType)) {
-
- if (onType.hasAnnotation(decA.getAnnotation().getType())) {
- // already has it
- return false;
- }
-
- AnnotationAJ annoX = decA.getAnnotation();
-
- // check the annotation is suitable for the target
- boolean isOK = checkTargetOK(decA, onType, annoX);
-
- if (isOK) {
- didSomething = true;
- ResolvedTypeMunger newAnnotationTM = new AnnotationOnTypeMunger(annoX);
- newAnnotationTM.setSourceLocation(decA.getSourceLocation());
- onType.addInterTypeMunger(new BcelTypeMunger(newAnnotationTM, decA.getAspect().resolve(this)), false);
- decA.copyAnnotationTo(onType);
- }
- }
- return didSomething;
- }
-
- /**
- * Apply the specified declare @field construct to any matching fields in the specified type.
- * @param deca the declare annotation targeting fields
- * @param type the type to check for members matching the declare annotation
- * @return true if something matched and the type was modified
- */
- private boolean applyDeclareAtField(DeclareAnnotation deca, ResolvedType type) {
- boolean changedType = false;
- ResolvedMember[] fields = type.getDeclaredFields();
- for (ResolvedMember field: fields) {
- if (deca.matches(field, this)) {
- AnnotationAJ anno = deca.getAnnotation();
- if (!field.hasAnnotation(anno.getType())) {
- field.addAnnotation(anno);
- changedType=true;
- }
- }
- }
- return changedType;
- }
-
- /**
- * Checks for an @target() on the annotation and if found ensures it allows the annotation to be attached to the target type
- * that matched.
- */
- private boolean checkTargetOK(DeclareAnnotation decA, ResolvedType onType, AnnotationAJ annoX) {
- if (annoX.specifiesTarget()) {
- if ((onType.isAnnotation() && !annoX.allowedOnAnnotationType()) || (!annoX.allowedOnRegularType())) {
- return false;
- }
- }
- return true;
- }
-
- // Hmmm - very similar to the code in BcelWeaver.weaveParentTypeMungers -
- // this code
- // doesn't need to produce errors/warnings though as it won't really be
- // weaving.
- protected void weaveInterTypeDeclarations(ResolvedType onType) {
-
- List<DeclareParents> declareParentsList = getCrosscuttingMembersSet().getDeclareParents();
- if (onType.isRawType()) {
- onType = onType.getGenericType();
- }
- onType.clearInterTypeMungers();
-
- List<DeclareParents> decpToRepeat = new ArrayList<DeclareParents>();
-
- boolean aParentChangeOccurred = false;
- boolean anAnnotationChangeOccurred = false;
- // First pass - apply all decp mungers
- for (Iterator<DeclareParents> i = declareParentsList.iterator(); i.hasNext();) {
- DeclareParents decp = i.next();
- 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);
- }
- }
- }
-
- // Still first pass - apply all dec @type mungers
- for (DeclareAnnotation decA : getCrosscuttingMembersSet().getDeclareAnnotationOnTypes()) {
- boolean typeChanged = applyDeclareAtType(decA, onType, true);
- if (typeChanged) {
- anAnnotationChangeOccurred = true;
- }
- }
-
- // apply declare @field
- for (DeclareAnnotation deca: getCrosscuttingMembersSet().getDeclareAnnotationOnFields()) {
- if (applyDeclareAtField(deca,onType)) {
- anAnnotationChangeOccurred = true;
- }
- }
-
- while ((aParentChangeOccurred || anAnnotationChangeOccurred) && !decpToRepeat.isEmpty()) {
- anAnnotationChangeOccurred = aParentChangeOccurred = false;
- List<DeclareParents> decpToRepeatNextTime = new ArrayList<DeclareParents>();
- for (DeclareParents decp: decpToRepeat) {
- if (applyDeclareParents(decp, onType)) {
- aParentChangeOccurred = true;
- } else {
- decpToRepeatNextTime.add(decp);
- }
- }
-
- for (DeclareAnnotation deca: getCrosscuttingMembersSet().getDeclareAnnotationOnTypes()) {
- if (applyDeclareAtType(deca, onType, false)) {
- anAnnotationChangeOccurred = true;
- }
- }
-
- for (DeclareAnnotation deca: getCrosscuttingMembersSet().getDeclareAnnotationOnFields()) {
- if (applyDeclareAtField(deca, onType)) {
- anAnnotationChangeOccurred = true;
- }
- }
- decpToRepeat = decpToRepeatNextTime;
- }
-
- }
-
- @Override
- public IWeavingSupport getWeavingSupport() {
- return bcelWeavingSupport;
- }
-
- @Override
- public void reportCheckerMatch(Checker checker, Shadow shadow) {
- IMessage iMessage = new Message(checker.getMessage(shadow), shadow.toString(), checker.isError() ? IMessage.ERROR
- : IMessage.WARNING, shadow.getSourceLocation(), null, new ISourceLocation[] { checker.getSourceLocation() }, true,
- 0, -1, -1);
-
- getMessageHandler().handleMessage(iMessage);
-
- if (getCrossReferenceHandler() != null) {
- getCrossReferenceHandler()
- .addCrossReference(
- checker.getSourceLocation(),
- shadow.getSourceLocation(),
- (checker.isError() ? IRelationship.Kind.DECLARE_ERROR.getName() : IRelationship.Kind.DECLARE_WARNING
- .getName()), false);
-
- }
-
- if (getModel() != null) {
- AsmRelationshipProvider.addDeclareErrorOrWarningRelationship(getModelAsAsmManager(), shadow, checker);
- }
-
- }
-
- public AsmManager getModelAsAsmManager() {
- return (AsmManager) getModel(); // For now... always an AsmManager in a bcel environment
- }
-
- void raiseError(String message) {
- getMessageHandler().handleMessage(MessageUtil.error(message));
- }
-
- /**
- * These are aop.xml files that can be used to alter the aspects that actually apply from those passed in - and also their scope
- * of application to other files in the system.
- *
- * @param xmlFiles list of File objects representing any aop.xml files passed in to configure the build process
- */
- public void setXmlFiles(List<File> xmlFiles) {
- if (!isXmlConfiguredWorld && !xmlFiles.isEmpty()) {
- raiseError("xml configuration files only supported by the compiler when -xmlConfigured option specified");
- return;
- }
- if (!xmlFiles.isEmpty()) {
- xmlConfiguration = new WeavingXmlConfig(this, WeavingXmlConfig.MODE_COMPILE);
- }
- for (File xmlfile : xmlFiles) {
- try {
- Definition d = DocumentParser.parse(xmlfile.toURI().toURL());
- xmlConfiguration.add(d);
- } catch (MalformedURLException e) {
- raiseError("Unexpected problem processing XML config file '" + xmlfile.getName() + "' :" + e.getMessage());
- } catch (Exception e) {
- raiseError("Unexpected problem processing XML config file '" + xmlfile.getName() + "' :" + e.getMessage());
- }
- }
- }
-
- /**
- * Add a scoped aspects where the scoping was defined in an aop.xml file and this world is being used in a LTW configuration
- */
- public void addScopedAspect(String name, String scope) {
- this.isXmlConfiguredWorld = true;
- if (xmlConfiguration == null) {
- xmlConfiguration = new WeavingXmlConfig(this, WeavingXmlConfig.MODE_LTW);
- }
- xmlConfiguration.addScopedAspect(name, scope);
- }
-
- public void setXmlConfigured(boolean b) {
- this.isXmlConfiguredWorld = b;
- }
-
- @Override
- public boolean isXmlConfigured() {
- return isXmlConfiguredWorld && xmlConfiguration != null;
- }
-
- public WeavingXmlConfig getXmlConfiguration() {
- return xmlConfiguration;
- }
-
- @Override
- public boolean isAspectIncluded(ResolvedType aspectType) {
- if (!isXmlConfigured()) {
- return true;
- }
- return xmlConfiguration.specifiesInclusionOfAspect(aspectType.getName());
- }
-
- @Override
- public TypePattern getAspectScope(ResolvedType declaringType) {
- return xmlConfiguration.getScopeFor(declaringType.getName());
- }
-
- @Override
- public boolean hasUnsatisfiedDependency(ResolvedType aspectType) {
- String aspectName = aspectType.getName();
-
- if (aspectType.hasAnnotations()) {
- AnnotationAJ[] annos = aspectType.getAnnotations();
- for (AnnotationAJ anno: annos) {
- if (anno.getTypeName().equals("org.aspectj.lang.annotation.RequiredTypes")) {
- String values = anno.getStringFormOfValue("value"); // Example: "[A,org.foo.Bar]"
- if (values != null && values.length() > 2) {
- values = values.substring(1,values.length()-1);
- StringTokenizer tokenizer = new StringTokenizer(values,",");
- boolean anythingMissing = false;
- while (tokenizer.hasMoreElements()) {
- String requiredTypeName = tokenizer.nextToken();
- ResolvedType rt = resolve(UnresolvedType.forName(requiredTypeName));
- if (rt.isMissing()) {
- if (!getMessageHandler().isIgnoring(IMessage.INFO)) {
- getMessageHandler().handleMessage(
- MessageUtil.info("deactivating aspect '" + aspectName + "' as it requires type '"
- + requiredTypeName + "' which cannot be found on the classpath"));
- }
- anythingMissing = true;
- if (aspectRequiredTypes == null) {
- aspectRequiredTypes = new HashMap<String,String>();
- }
- // Record that it has an invalid type reference
- aspectRequiredTypes.put(aspectName,requiredTypeName);
- }
- }
- if (anythingMissing) {
- return true;
- }
- else {
- return false;
- }
- }
- else {
- // no value specified for annotation
- return false;
- }
- }
- }
- }
- if (aspectRequiredTypes == null) {
- // no aspects require anything, so there can be no unsatisfied dependencies
- return false;
- }
- if (!aspectRequiredTypesProcessed.contains(aspectName)) {
- String requiredTypeName = aspectRequiredTypes.get(aspectName);
- if (requiredTypeName==null) {
- aspectRequiredTypesProcessed.add(aspectName);
- return false;
- } else {
- ResolvedType rt = resolve(UnresolvedType.forName(requiredTypeName));
- if (!rt.isMissing()) {
- aspectRequiredTypesProcessed.add(aspectName);
- aspectRequiredTypes.remove(aspectName);
- return false;
- } else {
- if (!getMessageHandler().isIgnoring(IMessage.INFO)) {
- getMessageHandler().handleMessage(
- MessageUtil.info("deactivating aspect '" + aspectName + "' as it requires type '"
- + requiredTypeName + "' which cannot be found on the classpath"));
- }
- aspectRequiredTypesProcessed.add(aspectName);
- return true;
- }
- }
- }
- return aspectRequiredTypes.containsKey(aspectName);
- }
-
- private List<String> aspectRequiredTypesProcessed = new ArrayList<String>();
- private Map<String, String> aspectRequiredTypes = null;
-
- public void addAspectRequires(String aspectClassName, String requiredType) {
- if (aspectRequiredTypes == null) {
- aspectRequiredTypes = new HashMap<String, String>();
- }
- aspectRequiredTypes.put(aspectClassName,requiredType);
- }
-
- /**
- * A WeavingXmlConfig is initially a collection of definitions from XML files - once the world is ready and weaving is running
- * it will initialize and transform those definitions into an optimized set of values (eg. resolve type patterns and string
- * names to real entities). It can then answer questions quickly: (1) is this aspect included in the weaving? (2) Is there a
- * scope specified for this aspect and does it include type X?
- *
- */
- static class WeavingXmlConfig {
-
- final static int MODE_COMPILE = 1;
- final static int MODE_LTW = 2;
-
- private int mode;
-
- private boolean initialized = false; // Lazily done
- private List<Definition> definitions = new ArrayList<Definition>();
-
- private List<String> resolvedIncludedAspects = new ArrayList<String>();
- private Map<String, TypePattern> scopes = new HashMap<String, TypePattern>();
-
- // these are not set for LTW mode (exclusion of these fast match patterns is handled before the weaver/world are used)
- private List<String> includedFastMatchPatterns = Collections.emptyList();
- private List<TypePattern> includedPatterns = Collections.emptyList();
- private List<String> excludedFastMatchPatterns = Collections.emptyList();
- private List<TypePattern> excludedPatterns = Collections.emptyList();
-
- private BcelWorld world;
-
- public WeavingXmlConfig(BcelWorld bcelWorld, int mode) {
- this.world = bcelWorld;
- this.mode = mode;
- }
-
- public void add(Definition d) {
- definitions.add(d);
- }
-
- public void addScopedAspect(String aspectName, String scope) {
- ensureInitialized();
- resolvedIncludedAspects.add(aspectName);
- try {
- TypePattern scopePattern = new PatternParser(scope).parseTypePattern();
- scopePattern.resolve(world);
- scopes.put(aspectName, scopePattern);
- if (!world.getMessageHandler().isIgnoring(IMessage.INFO)) {
- world.getMessageHandler().handleMessage(
- MessageUtil.info("Aspect '" + aspectName + "' is scoped to apply against types matching pattern '"
- + scopePattern.toString() + "'"));
- }
- } catch (Exception e) {
- world.getMessageHandler().handleMessage(
- MessageUtil.error("Unable to parse scope as type pattern. Scope was '" + scope + "': " + e.getMessage()));
- }
- }
-
- public void ensureInitialized() {
- if (!initialized) {
- try {
- resolvedIncludedAspects = new ArrayList<String>();
- // Process the definitions into something more optimal
- for (Definition definition : definitions) {
- List<String> aspectNames = definition.getAspectClassNames();
- for (String name : aspectNames) {
- resolvedIncludedAspects.add(name);
- // TODO check for existence?
- // ResolvedType resolvedAspect = resolve(UnresolvedType.forName(name));
- // if (resolvedAspect.isMissing()) {
- // // ERROR
- // } else {
- // resolvedIncludedAspects.add(resolvedAspect);
- // }
- String scope = definition.getScopeForAspect(name);
- if (scope != null) {
- // Resolve the type pattern
- try {
- TypePattern scopePattern = new PatternParser(scope).parseTypePattern();
- scopePattern.resolve(world);
- scopes.put(name, scopePattern);
- if (!world.getMessageHandler().isIgnoring(IMessage.INFO)) {
- world.getMessageHandler().handleMessage(
- MessageUtil.info("Aspect '" + name
- + "' is scoped to apply against types matching pattern '"
- + scopePattern.toString() + "'"));
- }
- } catch (Exception e) {
- // TODO definitions should remember which file they came from, for inclusion in this message
- world.getMessageHandler().handleMessage(
- MessageUtil.error("Unable to parse scope as type pattern. Scope was '" + scope + "': "
- + e.getMessage()));
- }
- }
- }
- try {
- List<String> includePatterns = definition.getIncludePatterns();
- if (includePatterns.size() > 0) {
- includedPatterns = new ArrayList<TypePattern>();
- includedFastMatchPatterns = new ArrayList<String>();
- }
- for (String includePattern : includePatterns) {
- if (includePattern.endsWith("..*")) {
- // from 'blah.blah.blah..*' leave the 'blah.blah.blah.'
- includedFastMatchPatterns.add(includePattern.substring(0, includePattern.length() - 2));
- } else {
- TypePattern includedPattern = new PatternParser(includePattern).parseTypePattern();
- includedPatterns.add(includedPattern);
- }
- }
- List<String> excludePatterns = definition.getExcludePatterns();
- if (excludePatterns.size() > 0) {
- excludedPatterns = new ArrayList<TypePattern>();
- excludedFastMatchPatterns = new ArrayList<String>();
- }
- for (String excludePattern : excludePatterns) {
- if (excludePattern.endsWith("..*")) {
- // from 'blah.blah.blah..*' leave the 'blah.blah.blah.'
- excludedFastMatchPatterns.add(excludePattern.substring(0, excludePattern.length() - 2));
- } else {
- TypePattern excludedPattern = new PatternParser(excludePattern).parseTypePattern();
- excludedPatterns.add(excludedPattern);
- }
- }
- } catch (ParserException pe) {
- // TODO definitions should remember which file they came from, for inclusion in this message
- world.getMessageHandler().handleMessage(
- MessageUtil.error("Unable to parse type pattern: " + pe.getMessage()));
-
- }
- }
- } finally {
- initialized = true;
- }
- }
- }
-
- public boolean specifiesInclusionOfAspect(String name) {
- ensureInitialized();
- return resolvedIncludedAspects.contains(name);
- }
-
- public TypePattern getScopeFor(String name) {
- return scopes.get(name);
- }
-
- // Can't quite follow the same rules for exclusion as used for loadtime weaving:
- // "The set of types to be woven are those types matched by at least one weaver include element and not matched by any
- // weaver
- // exclude element. If there are no weaver include statements then all non-excluded types are included."
- // Since if the weaver is seeing it during this kind of build, the type is implicitly included. So all we should check
- // for is exclusion
- public boolean excludesType(ResolvedType type) {
- if (mode == MODE_LTW) {
- return false;
- }
- String typename = type.getName();
- boolean excluded = false;
- for (String excludedPattern : excludedFastMatchPatterns) {
- if (typename.startsWith(excludedPattern)) {
- excluded = true;
- break;
- }
- }
- if (!excluded) {
- for (TypePattern excludedPattern : excludedPatterns) {
- if (excludedPattern.matchesStatically(type)) {
- excluded = true;
- break;
- }
- }
- }
- return excluded;
- }
-
- }
-
- @Override
- public TypeMap getTypeMap() {
- return typeMap;
- }
-
- @Override
- public boolean isLoadtimeWeaving() {
- return false;
- }
-
- public void addTypeDelegateResolver(TypeDelegateResolver typeDelegateResolver) {
- if (typeDelegateResolvers == null) {
- typeDelegateResolvers = new ArrayList<TypeDelegateResolver>();
- }
- typeDelegateResolvers.add(typeDelegateResolver);
- }
-
- @Override
- public void classWriteEvent(char[][] compoundName) {
- typeMap.classWriteEvent(new String(CharOperation.concatWith(compoundName, '.')));
- }
-
- /**
- * Force demote a type.
- */
- public void demote(ResolvedType type) {
- typeMap.demote(type);
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java b/weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java
deleted file mode 100644
index f8a36ba98..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java
+++ /dev/null
@@ -1,579 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2002, 2017 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:
- * Palo Alto Research Center, Incorporated (PARC).
- * ******************************************************************/
-package org.aspectj.weaver.bcel;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import org.aspectj.bridge.IMessageHandler;
-import org.aspectj.bridge.MessageUtil;
-import org.aspectj.util.LangUtil;
-import org.aspectj.util.SoftHashMap;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.WeaverMessages;
-import org.aspectj.weaver.tools.Trace;
-import org.aspectj.weaver.tools.TraceFactory;
-
-/**
- * @author Andy Clement
- * @author Mario Ivankovits
- */
-public class ClassPathManager {
-
- private static Trace trace = TraceFactory.getTraceFactory().getTrace(ClassPathManager.class);
-
- private static int maxOpenArchives = -1;
-
- private static URI JRT_URI = URI.create("jrt:/"); //$NON-NLS-1$
-
- private static final int MAXOPEN_DEFAULT = 1000;
-
- private List<Entry> entries;
-
- // In order to control how many open files we have, we maintain a list.
- // The max number is configured through the property:
- // org.aspectj.weaver.openarchives
- // and it defaults to 1000
- private List<ZipFile> openArchives = new ArrayList<ZipFile>();
-
- static {
- String openzipsString = getSystemPropertyWithoutSecurityException("org.aspectj.weaver.openarchives",
- Integer.toString(MAXOPEN_DEFAULT));
- maxOpenArchives = Integer.parseInt(openzipsString);
- if (maxOpenArchives < 20) {
- maxOpenArchives = 1000;
- }
- }
-
- public ClassPathManager(List<String> classpath, IMessageHandler handler) {
- if (trace.isTraceEnabled()) {
- trace.enter("<init>", this, new Object[] { classpath==null?"null":classpath.toString(), handler });
- }
- entries = new ArrayList<Entry>();
- for (String classpathEntry: classpath) {
- addPath(classpathEntry,handler);
- }
- if (trace.isTraceEnabled()) {
- trace.exit("<init>");
- }
- }
-
- protected ClassPathManager() {
- }
-
- public void addPath(String name, IMessageHandler handler) {
- File f = new File(name);
- String lc = name.toLowerCase();
- if (!f.isDirectory()) {
- if (!f.isFile()) {
- if (!lc.endsWith(".jar") || lc.endsWith(".zip")) {
- // heuristic-only: ending with .jar or .zip means probably a
- // zip file
- MessageUtil.info(handler, WeaverMessages.format(WeaverMessages.ZIPFILE_ENTRY_MISSING, name));
- } else {
- MessageUtil.info(handler, WeaverMessages.format(WeaverMessages.DIRECTORY_ENTRY_MISSING, name));
- }
- return;
- }
- try {
- if (lc.endsWith(LangUtil.JRT_FS)) { // Java9
- entries.add(new JImageEntry());
- } else {
- entries.add(new ZipFileEntry(f));
- }
- } catch (IOException ioe) {
- MessageUtil.warn(handler,
- WeaverMessages.format(WeaverMessages.ZIPFILE_ENTRY_INVALID, name, ioe.getMessage()));
- return;
- }
- } else {
- entries.add(new DirEntry(f));
- }
- }
-
- public ClassFile find(UnresolvedType type) {
- if (trace.isTraceEnabled()) {
- trace.enter("find", this, type);
- }
- String name = type.getName();
- for (Iterator<Entry> i = entries.iterator(); i.hasNext();) {
- Entry entry = i.next();
- try {
- ClassFile ret = entry.find(name);
- if (trace.isTraceEnabled()) {
- trace.event("searching for "+type+" in "+entry.toString());
- }
- if (ret != null) {
- if (trace.isTraceEnabled()) {
- trace.exit("find", ret);
- }
- return ret;
- }
- } catch (IOException ioe) {
- // this is NOT an error: it's valid to have missing classpath entries
- if (trace.isTraceEnabled()) {
- trace.error("Removing classpath entry for "+entry,ioe);
- }
- i.remove();
- }
- }
- if (trace.isTraceEnabled()) {
- trace.exit("find", null);
- }
- return null;
- }
-
- @Override
- public String toString() {
- StringBuffer buf = new StringBuffer();
- boolean start = true;
- for (Iterator<Entry> i = entries.iterator(); i.hasNext();) {
- if (start) {
- start = false;
- } else {
- buf.append(File.pathSeparator);
- }
- buf.append(i.next());
- }
- return buf.toString();
- }
-
- public abstract static class ClassFile {
- public abstract InputStream getInputStream() throws IOException;
- public abstract String getPath();
- public abstract void close();
- }
-
- abstract static class Entry {
- public abstract ClassFile find(String name) throws IOException;
- }
-
- static class ByteBasedClassFile extends ClassFile {
-
- private byte[] bytes;
- private ByteArrayInputStream bais;
- private String path;
-
- public ByteBasedClassFile(byte[] bytes, String path) {
- this.bytes = bytes;
- this.path = path;
- }
-
- @Override
- public InputStream getInputStream() throws IOException {
- this.bais = new ByteArrayInputStream(bytes);
- return this.bais;
- }
-
- @Override
- public String getPath() {
- return this.path;
- }
-
- @Override
- public void close() {
- if (this.bais!=null) {
- try {
- this.bais.close();
- } catch (IOException e) {
- }
- this.bais = null;
- }
- }
-
- }
-
- static class FileClassFile extends ClassFile {
- private File file;
- private FileInputStream fis;
-
- public FileClassFile(File file) {
- this.file = file;
- }
-
- @Override
- public InputStream getInputStream() throws IOException {
- fis = new FileInputStream(file);
- return fis;
- }
-
- @Override
- public void close() {
- try {
- if (fis != null)
- fis.close();
- } catch (IOException ioe) {
- throw new BCException("Can't close class file : " + file.getName(), ioe);
- } finally {
- fis = null;
- }
- }
-
- @Override
- public String getPath() {
- return file.getPath();
- }
- }
-
- class DirEntry extends Entry {
- private String dirPath;
-
- public DirEntry(File dir) {
- this.dirPath = dir.getPath();
- }
-
- public DirEntry(String dirPath) {
- this.dirPath = dirPath;
- }
-
- @Override
- public ClassFile find(String name) {
- File f = new File(dirPath + File.separator + name.replace('.', File.separatorChar) + ".class");
- if (f.isFile())
- return new FileClassFile(f);
- else
- return null;
- }
-
- @Override
- public String toString() {
- return dirPath;
- }
- }
-
- static class ZipEntryClassFile extends ClassFile {
- private ZipEntry entry;
- private ZipFileEntry zipFile;
- private InputStream is;
-
- public ZipEntryClassFile(ZipFileEntry zipFile, ZipEntry entry) {
- this.zipFile = zipFile;
- this.entry = entry;
- }
-
- @Override
- public InputStream getInputStream() throws IOException {
- is = zipFile.getZipFile().getInputStream(entry);
- return is;
- }
-
- @Override
- public void close() {
- try {
- if (is != null)
- is.close();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- is = null;
- }
- }
-
- @Override
- public String getPath() {
- return entry.getName();
- }
-
- }
-
- /**
- * Maintains a shared package cache for java runtime image. This maps packages (for example:
- * java/lang) to a starting root position in the filesystem (for example: /modules/java.base/java/lang).
- * When searching for a type we work out the package name, use it to find where in the filesystem
- * to start looking then run from there. Once found we do cache what we learn to make subsequent
- * lookups of that type even faster. Maintaining just a package cache rather than complete type cache
- * helps reduce memory usage but still gives reasonably fast lookup performance.
- */
- static class JImageEntry extends Entry {
-
- private static FileSystem fs = null;
-
- private final static Map<String, Path> fileCache = new SoftHashMap<String, Path>();
-
- private final static Map<String, Path> packageCache = new HashMap<String, Path>();
-
- private static boolean packageCacheInitialized = false;
-
- public JImageEntry() {
- if (fs == null) {
- try {
- fs = FileSystems.getFileSystem(JRT_URI);
- } catch (Throwable t) {
- throw new IllegalStateException("Unexpectedly unable to initialize a JRT filesystem", t);
- }
- }
- buildPackageMap();
- }
-
- class PackageCacheBuilderVisitor extends SimpleFileVisitor<Path> {
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
- if (file.getNameCount() > 3 && file.toString().endsWith(".class")) {
- int fnc = file.getNameCount();
- if (fnc > 3) { // There is a package name - e.g. /modules/java.base/java/lang/Object.class
- Path packagePath = file.subpath(2, fnc-1); // e.g. java/lang
- String packagePathString = packagePath.toString();
- packageCache.put(packagePathString, file.subpath(0, fnc-1)); // java/lang -> /modules/java.base/java/lang
- }
- }
- return FileVisitResult.CONTINUE;
- }
- }
-
- /**
- * Create a map from package names to the specific directory of the package members in the filesystem.
- */
- private synchronized void buildPackageMap() {
- if (!packageCacheInitialized) {
- packageCacheInitialized = true;
- Iterable<java.nio.file.Path> roots = fs.getRootDirectories();
- PackageCacheBuilderVisitor visitor = new PackageCacheBuilderVisitor();
- try {
- for (java.nio.file.Path path : roots) {
- Files.walkFileTree(path, visitor);
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }
-
- class TypeIdentifier extends SimpleFileVisitor<Path> {
-
- // What are we looking for?
- private String name;
-
- // If set, where did we find it?
- public Path found;
-
- // Basic metric count of how many files we checked before finding it
- public int filesSearchedCount;
-
- public TypeIdentifier(String name) {
- this.name = name;
- }
-
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
- filesSearchedCount++;
- if (file.getNameCount() > 2 && file.toString().endsWith(".class")) {
- int fnc = file.getNameCount();
- Path filePath = file.subpath(2, fnc);
- String filePathString = filePath.toString();
- if (filePathString.equals(name)) {
- fileCache.put(filePathString, file);
- found = file;
- return FileVisitResult.TERMINATE;
- }
- }
- return FileVisitResult.CONTINUE;
- }
- }
-
- private Path searchForFileAndCache(final Path startPath, final String name) {
- TypeIdentifier locator = new TypeIdentifier(name);
- try {
- Files.walkFileTree(startPath, locator);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- return locator.found;
- }
-
- @Override
- public ClassFile find(String name) throws IOException {
- String fileName = name.replace('.', '/') + ".class";
- Path file = fileCache.get(fileName);
- if (file == null) {
- // Check the packages map to see if we know about this package
- int idx = fileName.lastIndexOf('/');
- if (idx == -1) {
- // Package not here
- return null;
- }
- Path packageStart = null;
- String packageName = null;
- if (idx !=-1 ) {
- packageName = fileName.substring(0, idx);
- packageStart = packageCache.get(packageName);
- if (packageStart != null) {
- file = searchForFileAndCache(packageStart, fileName);
- }
- }
- }
- if (file == null) {
- return null;
- }
- byte[] bs = Files.readAllBytes(file);
- ClassFile cf = new ByteBasedClassFile(bs, fileName);
- return cf;
- }
-
- static Map<String, Path> getPackageCache() {
- return packageCache;
- }
-
- static Map<String, Path> getFileCache() {
- return fileCache;
- }
-
- }
-
- class ZipFileEntry extends Entry {
- private File file;
- private ZipFile zipFile;
-
- public ZipFileEntry(File file) throws IOException {
- this.file = file;
- }
-
- public ZipFileEntry(ZipFile zipFile) {
- this.zipFile = zipFile;
- }
-
- public ZipFile getZipFile() {
- return zipFile;
- }
-
- @Override
- public ClassFile find(String name) throws IOException {
- ensureOpen();
- String key = name.replace('.', '/') + ".class";
- ZipEntry entry = zipFile.getEntry(key);
- if (entry != null)
- return new ZipEntryClassFile(this, entry);
- else
- return null; // This zip will be closed when necessary...
- }
-
- public List<ZipEntryClassFile> getAllClassFiles() throws IOException {
- ensureOpen();
- List<ZipEntryClassFile> ret = new ArrayList<ZipEntryClassFile>();
- for (Enumeration<? extends ZipEntry> e = zipFile.entries(); e.hasMoreElements();) {
- ZipEntry entry = e.nextElement();
- String name = entry.getName();
- if (hasClassExtension(name))
- ret.add(new ZipEntryClassFile(this, entry));
- }
- // if (ret.isEmpty()) close();
- return ret;
- }
-
- private void ensureOpen() throws IOException {
- if (zipFile != null && openArchives.contains(zipFile)) {
- if (isReallyOpen())
- return;
- }
- if (openArchives.size() >= maxOpenArchives) {
- closeSomeArchives(openArchives.size() / 10); // Close 10% of
- // those open
- }
- zipFile = new ZipFile(file);
- if (!isReallyOpen()) {
- throw new FileNotFoundException("Can't open archive: " + file.getName() + " (size() check failed)");
- }
- openArchives.add(zipFile);
- }
-
- private boolean isReallyOpen() {
- try {
- zipFile.size(); // this will fail if the file has been closed
- // for
- // some reason;
- return true;
- } catch (IllegalStateException ex) {
- // this means the zip file is closed...
- return false;
- }
-
- }
-
- public void closeSomeArchives(int n) {
- for (int i = n - 1; i >= 0; i--) {
- ZipFile zf = openArchives.get(i);
- try {
- zf.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- openArchives.remove(i);
- }
- }
-
- public void close() {
- if (zipFile == null)
- return;
- try {
- openArchives.remove(zipFile);
- zipFile.close();
- } catch (IOException ioe) {
- throw new BCException("Can't close archive: " + file.getName(), ioe);
- } finally {
- zipFile = null;
- }
- }
-
- @Override
- public String toString() {
- return file.getName();
- }
- }
-
- /* private */static boolean hasClassExtension(String name) {
- return name.toLowerCase().endsWith((".class"));
- }
-
- public void closeArchives() {
- for (Entry entry : entries) {
- if (entry instanceof ZipFileEntry) {
- ((ZipFileEntry) entry).close();
- }
- openArchives.clear();
- }
- }
-
- // Copes with the security manager
- private static String getSystemPropertyWithoutSecurityException(String aPropertyName, String aDefaultValue) {
- try {
- return System.getProperty(aPropertyName, aDefaultValue);
- } catch (SecurityException ex) {
- return aDefaultValue;
- }
- }
-
- // Mainly exposed for testing
- public List<Entry> getEntries() {
- return entries;
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/ExceptionRange.java b/weaver/src/org/aspectj/weaver/bcel/ExceptionRange.java
deleted file mode 100644
index 5e74627c3..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/ExceptionRange.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/* *******************************************************************
- * 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 org.aspectj.apache.bcel.generic.InstructionHandle;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.weaver.UnresolvedType;
-
-/**
- * exceptionRanges are set initially to be low priority. The various setPriority methods should be used accordingly. The priority is
- * used when we pack the exception table into a method... the exception table should be sorted from high to low priority. Exceptions
- * we generate for advice is either high priority (higher than anything coming from the original method... most kinds of
- * non-execution advice) or low priority (lower than anything coming from the original method, for execution advice).
- *
- * <p>
- * ??? This does not account for handler, or any other "statement-level" advice. When such statement level advice happens, we may
- * want to go to a float level, so we can set the priority of advice to be lower than anything it encloses, and higher than anything
- * enclosing it.
- */
-
-/*
- * we're actually using the fact that we're an instruction targeter, for the handler
- */
-public final class ExceptionRange extends Range {
-
- private InstructionHandle handler;
- private final UnresolvedType exceptionType;
- private final int priority;
-
- // ---- initialization
-
- /**
- * After this constructor is called, this range is not well situated unless {@link #associateWithTargets} is called
- *
- * XXX priority should be fixed
- */
- public ExceptionRange(InstructionList body, UnresolvedType exceptionType, int priority) {
- super(body);
- this.exceptionType = exceptionType;
- this.priority = priority;
- }
-
- /**
- * @param insideExisting
- */
- public ExceptionRange(InstructionList body, UnresolvedType exceptionType, boolean insideExisting) {
- this(body, exceptionType, insideExisting ? Integer.MAX_VALUE : -1);
- }
-
- public void associateWithTargets(InstructionHandle start, InstructionHandle end, InstructionHandle handler) {
- // assert body.contains(start) && body.contains(end) && body.contains(handler)
- this.start = start;
- this.end = end;
- this.handler = handler;
- start.addTargeter(this);
- end.addTargeter(this);
- handler.addTargeter(this);
- }
-
- // ----
-
- public InstructionHandle getHandler() {
- return handler;
- }
-
- public UnresolvedType getCatchType() {
- return exceptionType;
- }
-
- public int getPriority() {
- return priority;
- }
-
- // ---- from object
-
- public String toString() {
- String str;
- if (exceptionType == null) {
- str = "finally";
- } else {
- str = "catch " + exceptionType;
- }
- // if (priority >= 0 && priority < Integer.MAX_VALUE) {
- // str += " (priority " + priority + ")";
- // }
- return str;
- }
-
- public boolean equals(Object other) {
- if (!(other instanceof ExceptionRange))
- return false;
- ExceptionRange o = (ExceptionRange) other;
- return o.getStart() == getStart() && o.getEnd() == getEnd() && o.handler == handler
- && ((o.exceptionType == null) ? (exceptionType == null) : o.exceptionType.equals(exceptionType))
- && o.priority == priority;
- }
-
- private volatile int hashCode = 0;
-
- public int hashCode() {
- if (hashCode == 0) {
- int ret = 17;
- ret = 37 * ret + getStart().hashCode();
- ret = 37 * ret + getEnd().hashCode();
- ret = 37 * ret + handler.hashCode();
- ret = 37 * ret + ((exceptionType == null) ? 0 : exceptionType.hashCode());
- ret = 37 * ret + priority;
- hashCode = ret;
- }
- return hashCode;
- }
-
- public void updateTarget(InstructionHandle oldIh, InstructionHandle newIh, InstructionList newBody) {
- super.updateTarget(oldIh, newIh, newBody);
- // we're guaranteed that start, end, and handler are distinct instruction handles.
- if (oldIh == handler) {
- handler = newIh;
- }
- }
-
- public static boolean isExceptionStart(InstructionHandle ih) {
- if (!isRangeHandle(ih))
- return false;
- Range r = getRange(ih);
- if (!(r instanceof ExceptionRange))
- return false;
- ExceptionRange er = (ExceptionRange) r;
- return er.getStart() == ih;
- }
-
- public static boolean isExceptionEnd(InstructionHandle ih) {
- if (!isRangeHandle(ih))
- return false;
- Range r = getRange(ih);
- if (!(r instanceof ExceptionRange))
- return false;
- ExceptionRange er = (ExceptionRange) r;
- return er.getEnd() == ih;
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/ExtensibleURLClassLoader.java b/weaver/src/org/aspectj/weaver/bcel/ExtensibleURLClassLoader.java
deleted file mode 100644
index 3480b8172..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/ExtensibleURLClassLoader.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2004 IBM Corporation
- * 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:
- * Matthew Webster, Adrian Colyer,
- * Martin Lippert initial implementation
- * Andy Clement
- * Roy Varghese - Bug 473555
- * ******************************************************************/
-
-package org.aspectj.weaver.bcel;
-
-import java.io.IOException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.security.CodeSource;
-
-import org.aspectj.util.FileUtil;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.UnresolvedType;
-
-public abstract class ExtensibleURLClassLoader extends URLClassLoader {
-
- private ClassPathManager classPath;
-
- public ExtensibleURLClassLoader(URL[] urls, ClassLoader parent) {
- super(urls, parent);
-
- // System.err.println("? ExtensibleURLClassLoader.<init>() path=" + WeavingAdaptor.makeClasspath(urls));
- try {
- classPath = new ClassPathManager(FileUtil.makeClasspath(urls), null);
- } catch (ExceptionInInitializerError ex) {
- ex.printStackTrace(System.out);
- throw ex;
- }
- }
-
- protected void addURL(URL url) {
- super.addURL(url); // amc - this call was missing and is needed in
- // WeavingURLClassLoader chains
- classPath.addPath(url.getPath(), null);
- }
-
- protected Class findClass(String name) throws ClassNotFoundException {
- // System.err.println("? ExtensibleURLClassLoader.findClass(" + name + ")");
- try {
- byte[] bytes = getBytes(name);
- if (bytes != null) {
- return defineClass(name, bytes);
- } else {
- throw new ClassNotFoundException(name);
- }
- } catch (IOException ex) {
- throw new ClassNotFoundException(name);
- }
- }
-
- protected Class defineClass(String name, byte[] b, CodeSource cs) throws IOException {
- // System.err.println("? ExtensibleURLClassLoader.defineClass(" + name + ",[" + b.length + "])");
- return defineClass(name, b, 0, b.length, cs);
- }
-
- protected byte[] getBytes(String name) throws IOException {
- byte[] b = null;
- UnresolvedType unresolvedType = null;
- try {
- unresolvedType = UnresolvedType.forName(name);
- } catch (BCException bce) {
- if (bce.getMessage().indexOf("nameToSignature") == -1) {
- bce.printStackTrace(System.err);
- }
- return null;
- }
- ClassPathManager.ClassFile classFile = classPath.find(unresolvedType);
- if (classFile != null) {
- try {
- b = FileUtil.readAsByteArray(classFile.getInputStream());
- } finally {
- classFile.close();
- }
- }
- return b;
- }
-
- private Class defineClass(String name, byte[] bytes /* ClassPathManager.ClassFile classFile */) throws IOException {
- String packageName = getPackageName(name);
- if (packageName != null) {
- Package pakkage = getPackage(packageName);
- if (pakkage == null) {
- definePackage(packageName, null, null, null, null, null, null, null);
- }
- }
-
- return defineClass(name, bytes, null);
- }
-
- private String getPackageName(String className) {
- int offset = className.lastIndexOf('.');
- return (offset == -1) ? null : className.substring(0, offset);
- }
-
- @Override
- public void close() throws IOException {
- super.close();
- classPath.closeArchives();
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/FakeAnnotation.java b/weaver/src/org/aspectj/weaver/bcel/FakeAnnotation.java
deleted file mode 100644
index 4194e66e9..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/FakeAnnotation.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*******************************************************************************
- * 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:
- * initial implementation Andy Clement
- *******************************************************************************/
-package org.aspectj.weaver.bcel;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.List;
-
-import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
-import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
-
-/**
- * For implementing declare @type interacting with declare @parents during compilation - we need to be able to add an annotation to
- * 'binary type binding' (this is how types are seen during incremental compilation). Unlike a SourceTypeBinding - a
- * BinaryTypeBinding does not allow easy interaction with its annotations - so what we do is take the eclipse annotation, suck out
- * the name/signature and visibility and put that information in a 'FakeAnnotation'. The FakeAnnotation is attached to the BCEL
- * delegate for the binary type binding - this will allow type resolution to succeed correctly. The FakeAnnotation never makes it to
- * disk, since the weaver does the job properly, attaching a real annotation.
- */
-public class FakeAnnotation extends AnnotationGen {
-
- private String name;
- private String sig;
- private boolean isRuntimeVisible;
-
- public FakeAnnotation(String name, String sig, boolean isRuntimeVisible) {
- super(null, null, true, null);
- this.name = name;
- this.sig = sig;
- this.isRuntimeVisible = isRuntimeVisible;
- }
-
- public String getTypeName() {
- return name;
- }
-
- public String getTypeSignature() {
- return sig;
- }
-
- public void addElementNameValuePair(NameValuePair evp) {
- // doesnt need to know about name/value pairs
- }
-
- public void dump(DataOutputStream dos) throws IOException {
- // should be serialized
- }
-
- public int getTypeIndex() {
- return 0;
- }
-
- public List getValues() {
- return null;
- }
-
- public boolean isRuntimeVisible() {
- return isRuntimeVisible;
- }
-
- protected void setIsRuntimeVisible(boolean b) {
- }
-
- public String toShortString() {
- return "@" + this.name;
- }
-
- public String toString() {
- return this.name;
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/IfFinder.java b/weaver/src/org/aspectj/weaver/bcel/IfFinder.java
deleted file mode 100644
index c66aa8939..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/IfFinder.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2006 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.weaver.patterns.AbstractPatternNodeVisitor;
-import org.aspectj.weaver.patterns.AndPointcut;
-import org.aspectj.weaver.patterns.IfPointcut;
-import org.aspectj.weaver.patterns.NotPointcut;
-import org.aspectj.weaver.patterns.OrPointcut;
-
-/**
- * Look for an if() pointcut
- */
-class IfFinder extends AbstractPatternNodeVisitor {
- boolean hasIf = false;
-
- public Object visit(IfPointcut node, Object data) {
- if (node.alwaysFalse() || node.alwaysTrue()) {
- // IfFalse / IfTrue
- } else {
- hasIf = true;
- }
- return node;
- }
-
- public Object visit(AndPointcut node, Object data) {
- if (!hasIf)
- node.getLeft().accept(this, data);
- if (!hasIf)
- node.getRight().accept(this, data);
- return node;
- }
-
- public Object visit(NotPointcut node, Object data) {
- if (!hasIf)
- node.getNegatedPointcut().accept(this, data);
- return node;
- }
-
- public Object visit(OrPointcut node, Object data) {
- if (!hasIf)
- node.getLeft().accept(this, data);
- if (!hasIf)
- node.getRight().accept(this, data);
- return node;
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java
deleted file mode 100644
index 83189e1d4..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java
+++ /dev/null
@@ -1,1940 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2002-2010 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:
- * PARC initial implementation
- * Andy Clement 6Jul05 generics - signature attribute
- * Abraham Nevado
- * ******************************************************************/
-
-package org.aspectj.weaver.bcel;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.Vector;
-
-import org.aspectj.apache.bcel.Constants;
-import org.aspectj.apache.bcel.classfile.Attribute;
-import org.aspectj.apache.bcel.classfile.ConstantPool;
-import org.aspectj.apache.bcel.classfile.Field;
-import org.aspectj.apache.bcel.classfile.JavaClass;
-import org.aspectj.apache.bcel.classfile.Method;
-import org.aspectj.apache.bcel.classfile.Signature;
-import org.aspectj.apache.bcel.classfile.Synthetic;
-import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
-import org.aspectj.apache.bcel.generic.BasicType;
-import org.aspectj.apache.bcel.generic.ClassGen;
-import org.aspectj.apache.bcel.generic.FieldGen;
-import org.aspectj.apache.bcel.generic.InstructionConstants;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionHandle;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.apache.bcel.generic.ObjectType;
-import org.aspectj.apache.bcel.generic.Type;
-import org.aspectj.bridge.IMessage;
-import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.bridge.SourceLocation;
-import org.aspectj.weaver.AjAttribute;
-import org.aspectj.weaver.AjAttribute.WeaverState;
-import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.MemberKind;
-import org.aspectj.weaver.NameMangler;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.RuntimeVersion;
-import org.aspectj.weaver.Shadow;
-import org.aspectj.weaver.SignatureUtils;
-import org.aspectj.weaver.TypeVariable;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.UnresolvedType.TypeKind;
-import org.aspectj.weaver.WeaverMessages;
-import org.aspectj.weaver.WeaverStateInfo;
-import org.aspectj.weaver.World;
-import org.aspectj.weaver.bcel.asm.AsmDetector;
-import org.aspectj.weaver.bcel.asm.StackMapAdder;
-
-/**
- * Lazy lazy lazy. We don't unpack the underlying class unless necessary. Things like new methods and annotations accumulate in here
- * until they must be written out, don't add them to the underlying MethodGen! Things are slightly different if this represents an
- * Aspect.
- */
-public final class LazyClassGen {
-
- private static final Type[] ARRAY_7STRING_INT = new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING,
- Type.STRING, Type.STRING, Type.INT };
-
- private static final Type[] ARRAY_8STRING_INT = new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING,
- Type.STRING, Type.STRING, Type.STRING, Type.INT };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_METHOD = new Type[] {
- Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY, Type.CLASS_ARRAY, Type.CLASS, Type.INT
- };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_CONSTRUCTOR = new Type[] {
- Type.STRING, Type.INT, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY, Type.CLASS_ARRAY, Type.INT
- };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_CATCHCLAUSE = new Type[] {
- Type.STRING, Type.CLASS, Type.CLASS, Type.STRING, Type.INT
- };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_FIELD = new Type[] {
- Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS, Type.INT
- };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_INITIALIZER = new Type[] {
- Type.STRING, Type.INT, Type.CLASS, Type.INT
- };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_MONITOR = new Type[] {
- Type.STRING, Type.CLASS, Type.INT
- };
-
- private static final Type[] PARAMSIGNATURE_MAKESJP_ADVICE = new Type[] {
- Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY,
- Type.CLASS_ARRAY, Type.CLASS, Type.INT
- };
-
-
-
-
-
- private static final int ACC_SYNTHETIC = 0x1000;
-
- private static final String[] NO_STRINGS = new String[0];
-
- int highestLineNumber = 0; // ---- JSR 45 info
-
- private final SortedMap<String, InlinedSourceFileInfo> inlinedFiles = new TreeMap<String, InlinedSourceFileInfo>();
-
- private boolean regenerateGenericSignatureAttribute = false;
-
- private BcelObjectType myType; // XXX is not set for types we create
- private ClassGen myGen;
- private final ConstantPool cp;
- private final World world;
- private final String packageName = null;
-
- private final List<BcelField> fields = new ArrayList<BcelField>();
- private final List<LazyMethodGen> methodGens = new ArrayList<LazyMethodGen>();
- private final List<LazyClassGen> classGens = new ArrayList<LazyClassGen>();
- private final List<AnnotationGen> annotations = new ArrayList<AnnotationGen>();
- private int childCounter = 0;
-
- private final InstructionFactory fact;
-
- private boolean isSerializable = false;
- private boolean hasSerialVersionUIDField = false;
- private boolean serialVersionUIDRequiresInitialization = false;
- private long calculatedSerialVersionUID;
- private boolean hasClinit = false;
-
- private ResolvedType[] extraSuperInterfaces = null;
- private ResolvedType superclass = null;
-
- // ---
-
- static class InlinedSourceFileInfo {
- int highestLineNumber;
- int offset; // calculated
-
- InlinedSourceFileInfo(int highestLineNumber) {
- this.highestLineNumber = highestLineNumber;
- }
- }
-
- void addInlinedSourceFileInfo(String fullpath, int highestLineNumber) {
- Object o = inlinedFiles.get(fullpath);
- if (o != null) {
- InlinedSourceFileInfo info = (InlinedSourceFileInfo) o;
- if (info.highestLineNumber < highestLineNumber) {
- info.highestLineNumber = highestLineNumber;
- }
- } else {
- inlinedFiles.put(fullpath, new InlinedSourceFileInfo(highestLineNumber));
- }
- }
-
- void calculateSourceDebugExtensionOffsets() {
- int i = roundUpToHundreds(highestLineNumber);
- for (InlinedSourceFileInfo element : inlinedFiles.values()) {
- element.offset = i;
- i = roundUpToHundreds(i + element.highestLineNumber);
- }
- }
-
- private static int roundUpToHundreds(int i) {
- return ((i / 100) + 1) * 100;
- }
-
- int getSourceDebugExtensionOffset(String fullpath) {
- return inlinedFiles.get(fullpath).offset;
- }
-
- // private Unknown getSourceDebugExtensionAttribute() {
- // int nameIndex = cp.addUtf8("SourceDebugExtension");
- // String data = getSourceDebugExtensionString();
- // //System.err.println(data);
- // byte[] bytes = Utility.stringToUTF(data);
- // int length = bytes.length;
- //
- // return new Unknown(nameIndex, length, bytes, cp);
- // }
-
- // private LazyClassGen() {}
- // public static void main(String[] args) {
- // LazyClassGen m = new LazyClassGen();
- // m.highestLineNumber = 37;
- // m.inlinedFiles.put("boo/baz/foo.java", new InlinedSourceFileInfo( 83));
- // m.inlinedFiles.put("boo/barz/foo.java", new InlinedSourceFileInfo(292));
- // m.inlinedFiles.put("boo/baz/moo.java", new InlinedSourceFileInfo(128));
- // m.calculateSourceDebugExtensionOffsets();
- // System.err.println(m.getSourceDebugExtensionString());
- // }
-
- // For the entire pathname, we're using package names. This is probably
- // wrong.
- // private String getSourceDebugExtensionString() {
- // StringBuffer out = new StringBuffer();
- // String myFileName = getFileName();
- // // header section
- // out.append("SMAP\n");
- // out.append(myFileName);
- // out.append("\nAspectJ\n");
- // // stratum section
- // out.append("*S AspectJ\n");
- // // file section
- // out.append("*F\n");
- // out.append("1 ");
- // out.append(myFileName);
- // out.append("\n");
- // int i = 2;
- // for (Iterator iter = inlinedFiles.keySet().iterator(); iter.hasNext();) {
- // String element = (String) iter.next();
- // int ii = element.lastIndexOf('/');
- // if (ii == -1) {
- // out.append(i++); out.append(' ');
- // out.append(element); out.append('\n');
- // } else {
- // out.append("+ "); out.append(i++); out.append(' ');
- // out.append(element.substring(ii+1)); out.append('\n');
- // out.append(element); out.append('\n');
- // }
- // }
- // // emit line section
- // out.append("*L\n");
- // out.append("1#1,");
- // out.append(highestLineNumber);
- // out.append(":1,1\n");
- // i = 2;
- // for (Iterator iter = inlinedFiles.values().iterator(); iter.hasNext();) {
- // InlinedSourceFileInfo element = (InlinedSourceFileInfo) iter.next();
- // out.append("1#");
- // out.append(i++); out.append(',');
- // out.append(element.highestLineNumber); out.append(":");
- // out.append(element.offset + 1); out.append(",1\n");
- // }
- // // end section
- // out.append("*E\n");
- // // and finish up...
- // return out.toString();
- // }
-
- // ---- end JSR45-related stuff
-
- /** Emit disassembled class and newline to out */
- public static void disassemble(String path, String name, PrintStream out) throws IOException {
- if (null == out) {
- return;
- }
- // out.println("classPath: " + classPath);
-
- BcelWorld world = new BcelWorld(path);
-
- UnresolvedType ut = UnresolvedType.forName(name);
- ut.setNeedsModifiableDelegate(true);
- LazyClassGen clazz = new LazyClassGen(BcelWorld.getBcelObjectType(world.resolve(ut)));
- clazz.print(out);
- out.println();
- }
-
- public String getNewGeneratedNameTag() {
- return new Integer(childCounter++).toString();
- }
-
- // ----
-
- public LazyClassGen(String class_name, String super_class_name, String file_name, int access_flags, String[] interfaces,
- World world) {
- myGen = new ClassGen(class_name, super_class_name, file_name, access_flags, interfaces);
- cp = myGen.getConstantPool();
- fact = new InstructionFactory(myGen, cp);
- regenerateGenericSignatureAttribute = true;
- this.world = world;
- }
-
- public void setMajorMinor(int major, int minor) {
- myGen.setMajor(major);
- myGen.setMinor(minor);
- }
-
- public int getMajor() {
- return myGen.getMajor();
- }
-
- public int getMinor() {
- return myGen.getMinor();
- }
-
- // Non child type, so it comes from a real type in the world.
- public LazyClassGen(BcelObjectType myType) {
- myGen = new ClassGen(myType.getJavaClass());
- cp = myGen.getConstantPool();
- fact = new InstructionFactory(myGen, cp);
- this.myType = myType;
- world = myType.getResolvedTypeX().getWorld();
-
- /* Does this class support serialization */
- if (implementsSerializable(getType())) {
- isSerializable = true;
-
- // ResolvedMember[] fields = getType().getDeclaredFields();
- // for (int i = 0; i < fields.length; i++) {
- // ResolvedMember field = fields[i];
- // if (field.getName().equals("serialVersionUID")
- // && field.isStatic() && field.getType().equals(UnresolvedType.LONG))
- // {
- // hasSerialVersionUIDField = true;
- // }
- // }
- hasSerialVersionUIDField = hasSerialVersionUIDField(getType());
-
- ResolvedMember[] methods = getType().getDeclaredMethods();
- for (int i = 0; i < methods.length; i++) {
- ResolvedMember method = methods[i];
- if (method.getName().equals("<clinit>")) {
- if (method.getKind() != Member.STATIC_INITIALIZATION) {
- throw new RuntimeException("qui?");
- }
- hasClinit = true;
- }
- }
-
- // Do we need to calculate an SUID and add it?
- if (!getType().isInterface() && !hasSerialVersionUIDField && world.isAddSerialVerUID()) {
- calculatedSerialVersionUID = myGen.getSUID();
- FieldGen fg = new FieldGen(Constants.ACC_PRIVATE | Constants.ACC_FINAL | Constants.ACC_STATIC, BasicType.LONG,
- "serialVersionUID", getConstantPool());
- addField(fg);
- hasSerialVersionUIDField = true;
- serialVersionUIDRequiresInitialization = true;
- // warn about what we've done?
- if (world.getLint().calculatingSerialVersionUID.isEnabled()) {
- world.getLint().calculatingSerialVersionUID.signal(
- new String[] { getClassName(), Long.toString(calculatedSerialVersionUID) + "L" }, null, null);
- }
- }
- }
-
- ResolvedMember[] methods = myType.getDeclaredMethods();
- for (int i = 0; i < methods.length; i++) {
- addMethodGen(new LazyMethodGen((BcelMethod) methods[i], this));
- }
-
- // Method[] methods = myGen.getMethods();
- // for (int i = 0; i < methods.length; i++) {
- // addMethodGen(new LazyMethodGen(methods[i], this));
- // }
-
- ResolvedMember[] fields = myType.getDeclaredFields();
- for (int i = 0; i < fields.length; i++) {
- this.fields.add((BcelField) fields[i]);
- }
- }
-
- public static boolean hasSerialVersionUIDField(ResolvedType type) {
-
- ResolvedMember[] fields = type.getDeclaredFields();
- for (int i = 0; i < fields.length; i++) {
- ResolvedMember field = fields[i];
- if (field.getName().equals("serialVersionUID") && Modifier.isStatic(field.getModifiers())
- && field.getType().equals(UnresolvedType.LONG)) {
- return true;
- }
- }
-
- return false;
- }
-
- // public void addAttribute(Attribute i) {
- // myGen.addAttribute(i);
- // }
-
- // ----
-
- public String getInternalClassName() {
- return getConstantPool().getConstantString_CONSTANTClass(myGen.getClassNameIndex());
- // getConstantPool().getConstantString(
- // myGen.getClassNameIndex(),
- // Constants.CONSTANT_Class);
-
- }
-
- public String getInternalFileName() {
- String str = getInternalClassName();
- int index = str.lastIndexOf('/');
- if (index == -1) {
- return getFileName();
- } else {
- return str.substring(0, index + 1) + getFileName();
- }
- }
-
- /**
- * Returns the packagename - if its the default package we return an empty string
- */
- public String getPackageName() {
- if (packageName != null) {
- return packageName;
- }
- String str = getInternalClassName();
- int index = str.indexOf("<");
- if (index != -1) {
- str = str.substring(0, index); // strip off the generics guff
- }
- index = str.lastIndexOf("/");
- if (index == -1) {
- return "";
- }
- return str.substring(0, index).replace('/', '.');
- }
-
- public void addMethodGen(LazyMethodGen gen) {
- // assert gen.getClassName() == super.getClassName();
- methodGens.add(gen);
- if (highestLineNumber < gen.highestLineNumber) {
- highestLineNumber = gen.highestLineNumber;
- }
- }
-
- public boolean removeMethodGen(LazyMethodGen gen) {
- return methodGens.remove(gen);
- }
-
- public void addMethodGen(LazyMethodGen gen, ISourceLocation sourceLocation) {
- addMethodGen(gen);
- if (!gen.getMethod().isPrivate()) {
- warnOnAddedMethod(gen.getMethod(), sourceLocation);
- }
- }
-
- public void errorOnAddedField(FieldGen field, ISourceLocation sourceLocation) {
- if (isSerializable && !hasSerialVersionUIDField) {
- getWorld().getLint().serialVersionUIDBroken.signal(
- new String[] { myType.getResolvedTypeX().getName(), field.getName() }, sourceLocation, null);
- }
- }
-
- public void warnOnAddedInterface(String name, ISourceLocation sourceLocation) {
- warnOnModifiedSerialVersionUID(sourceLocation, "added interface " + name);
- }
-
- public void warnOnAddedMethod(Method method, ISourceLocation sourceLocation) {
- warnOnModifiedSerialVersionUID(sourceLocation, "added non-private method " + method.getName());
- }
-
- public void warnOnAddedStaticInitializer(Shadow shadow, ISourceLocation sourceLocation) {
- if (!hasClinit) {
- warnOnModifiedSerialVersionUID(sourceLocation, "added static initializer");
- }
- }
-
- public void warnOnModifiedSerialVersionUID(ISourceLocation sourceLocation, String reason) {
- if (isSerializable && !hasSerialVersionUIDField) {
- getWorld().getLint().needsSerialVersionUIDField.signal(new String[] { myType.getResolvedTypeX().getName().toString(),
- reason }, sourceLocation, null);
- }
- }
-
- public World getWorld() {
- return world;
- }
-
- public List<LazyMethodGen> getMethodGens() {
- return methodGens; // ???Collections.unmodifiableList(methodGens);
- }
-
- public List<BcelField> getFieldGens() {
- return fields;
- }
-
- public boolean fieldExists(String name) {
-// Field[] allFields = myGen.getFields();
-// if (allFields!=null) {
-// for (int i=0;i<allFields.length;i++) {
-// Field f = allFields[i];
-// if (f.getName().equals(name)) {
-// return f;
-// }
-// }
-// }
- for (BcelField f: fields) {
- if (f.getName().equals(name)) {
- return true;
- }
- }
- return false;
- }
-
- private void writeBack(BcelWorld world) {
- if (getConstantPool().getSize() > Short.MAX_VALUE) {
- reportClassTooBigProblem();
- return;
- }
-
- if (annotations.size() > 0) {
- for (AnnotationGen element : annotations) {
- myGen.addAnnotation(element);
- }
- // Attribute[] annAttributes =
- // org.aspectj.apache.bcel.classfile.Utility.getAnnotationAttributes(
- // getConstantPool(),annotations);
- // for (int i = 0; i < annAttributes.length; i++) {
- // Attribute attribute = annAttributes[i];
- // System.err.println("Adding attribute for "+attribute);
- // myGen.addAttribute(attribute);
- // }
- }
-
- // Add a weaver version attribute to the file being produced (if
- // necessary...)
- if (!myGen.hasAttribute("org.aspectj.weaver.WeaverVersion")) {
- myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverVersionInfo(), getConstantPool()));
- }
-
- // see 389678: TODO more finessing possible here?
- if (world.isOverWeaving()) {
- if (myGen.hasAttribute(WeaverState.AttributeName) && myType!=null && myType.getWeaverState() != null) {
- myGen.removeAttribute(myGen.getAttribute(WeaverState.AttributeName));
- myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverState(myType.getWeaverState()), getConstantPool()));
- }
- } else {
- if (!myGen.hasAttribute(WeaverState.AttributeName) && myType != null && myType.getWeaverState() != null) {
- myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverState(myType.getWeaverState()), getConstantPool()));
- }
- }
-
- // FIXME ATAJ needed only for slow Aspects.aspectOf() - keep or remove
- // make a lot of test fail since the test compare weaved class file
- // based on some test data as text files...
- // if (!myGen.isInterface()) {
- // addAjClassField();
- // }
-
- addAjcInitializers();
-
- // 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);
-
- for (LazyMethodGen gen : methodGens) {
- // we skip empty clinits
- if (isEmptyClinit(gen)) {
- continue;
- }
- myGen.addMethod(gen.getMethod());
- }
-
- len = fields.size();
- myGen.setFields(Field.NoFields);
- for (int i = 0; i < len; i++) {
- BcelField gen = fields.get(i);
- myGen.addField(gen.getField(cp));
- }
-
- if (sourceDebugExtensionSupportSwitchedOn) {
- if (inlinedFiles.size() != 0) {
- if (hasSourceDebugExtensionAttribute(myGen)) {
- world.showMessage(IMessage.WARNING, WeaverMessages.format(WeaverMessages.OVERWRITE_JSR45, getFileName()), null,
- null);
- }
- // myGen.addAttribute(getSourceDebugExtensionAttribute());
- }
- }
-
- fixupGenericSignatureAttribute();
- }
-
- /**
- * When working with Java generics, a signature attribute is attached to the type which indicates how it was declared. This
- * routine ensures the signature attribute for the class we are about to write out is correct. Basically its responsibilities
- * are:
- * <ol>
- * <li>
- * Checking whether the attribute needs changing (ie. did weaving change the type hierarchy) - if it did, remove the old
- * attribute
- * <li>
- * Check if we need an attribute at all, are we generic? are our supertypes parameterized/generic?
- * <li>
- * Build the new attribute which includes all typevariable, supertype and superinterface information
- * </ol>
- */
- private void fixupGenericSignatureAttribute() {
-
- if (getWorld() != null && !getWorld().isInJava5Mode()) {
- return;
- }
-
- // TODO asc generics Temporarily assume that types we generate dont need
- // a signature attribute (closure/etc).. will need
- // revisiting no doubt...
- // if (myType == null) {
- // return;
- // }
-
- // 1. Has anything changed that would require us to modify this
- // attribute?
- if (!regenerateGenericSignatureAttribute) {
- return;
- }
-
- // 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
- sigAttr = (Signature) myGen.getAttribute("Signature");
- }
-
- // 3. Do we need an attribute?
- boolean needAttribute = false;
- // If we had one before, we definetly still need one as types can't be
- // 'removed' from the hierarchy
- if (sigAttr != null) {
- needAttribute = true;
- }
-
- // check the interfaces
- if (!needAttribute) {
- if (myType != null) {
- ResolvedType[] interfaceRTXs = myType.getDeclaredInterfaces();
- for (int i = 0; i < interfaceRTXs.length; i++) {
- ResolvedType typeX = interfaceRTXs[i];
- if (typeX.isGenericType() || typeX.isParameterizedType()) {
- needAttribute = true;
- }
- }
- if (extraSuperInterfaces != null) {
- for (int i = 0; i < extraSuperInterfaces.length; i++) {
- ResolvedType interfaceType = extraSuperInterfaces[i];
- if (interfaceType.isGenericType() || interfaceType.isParameterizedType()) {
- needAttribute = true;
- }
- }
- }
- }
-
- if (myType == null) {
- ResolvedType superclassRTX = superclass;
- if (superclassRTX != null) {
- if (superclassRTX.isGenericType() || superclassRTX.isParameterizedType()) {
- needAttribute = true;
- }
- }
- } else {
- // check the supertype
- ResolvedType superclassRTX = getSuperClass();
- if (superclassRTX.isGenericType() || superclassRTX.isParameterizedType()) {
- needAttribute = true;
- }
- }
- }
-
- if (needAttribute) {
- StringBuffer signature = new StringBuffer();
- // first, the type variables...
- if (myType != null) {
- TypeVariable[] tVars = myType.getTypeVariables();
- if (tVars.length > 0) {
- signature.append("<");
- for (int i = 0; i < tVars.length; i++) {
- TypeVariable variable = tVars[i];
- signature.append(variable.getSignatureForAttribute());
- }
- signature.append(">");
- }
- }
- // now the supertype
- String supersig = getSuperClass().getSignatureForAttribute();
- signature.append(supersig);
- if (myType != null) {
- ResolvedType[] interfaceRTXs = myType.getDeclaredInterfaces();
- for (int i = 0; i < interfaceRTXs.length; i++) {
- String s = interfaceRTXs[i].getSignatureForAttribute();
- signature.append(s);
- }
- if (extraSuperInterfaces != null) {
- for (int i = 0; i < extraSuperInterfaces.length; i++) {
- String s = extraSuperInterfaces[i].getSignatureForAttribute();
- signature.append(s);
- }
- }
- }
- if (sigAttr != null) {
- myGen.removeAttribute(sigAttr);
- }
- myGen.addAttribute(createSignatureAttribute(signature.toString()));
- }
- }
-
- /**
- * Helper method to create a signature attribute based on a string signature: e.g. "Ljava/lang/Object;LI<Ljava/lang/Double;>;"
- */
- private Signature createSignatureAttribute(String signature) {
- int nameIndex = cp.addUtf8("Signature");
- int sigIndex = cp.addUtf8(signature);
- return new Signature(nameIndex, 2, sigIndex, cp);
- }
-
- /**
- *
- */
- private void reportClassTooBigProblem() {
- // PR 59208
- // we've generated a class that is just toooooooooo big (you've been
- // generating programs
- // again haven't you? come on, admit it, no-one writes classes this big
- // by hand).
- // 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.getModifiers(),
- myGen.getInterfaceNames());
- // raise an error against this compilation unit.
- getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CLASS_TOO_BIG, this.getClassName()),
- new SourceLocation(new File(myGen.getFileName()), 0), null);
- }
-
- private static boolean hasSourceDebugExtensionAttribute(ClassGen gen) {
- return gen.hasAttribute("SourceDebugExtension");
- }
-
- public JavaClass getJavaClass(BcelWorld world) {
- writeBack(world);
- return myGen.getJavaClass();
- }
-
- public byte[] getJavaClassBytesIncludingReweavable(BcelWorld world) {
- writeBack(world);
- byte[] wovenClassFileData = myGen.getJavaClass().getBytes();
- // At 1.6 stackmaps are optional, whilst at 1.7 and later they
- // are required (unless turning off the verifier)
- if ((myGen.getMajor() == Constants.MAJOR_1_6 && world.shouldGenerateStackMaps()) || myGen.getMajor() > Constants.MAJOR_1_6) {
- if (!AsmDetector.isAsmAround) {
- throw new BCException("Unable to find Asm for stackmap generation (Looking for 'aj.org.objectweb.asm.ClassReader'). Stackmap generation for woven code is required to avoid verify errors on a Java 1.7 or higher runtime");
- };
- wovenClassFileData = StackMapAdder.addStackMaps(world, wovenClassFileData);
- }
-
- WeaverStateInfo wsi = myType.getWeaverState();// getOrCreateWeaverStateInfo();
- if (wsi != null && wsi.isReweavable() && !world.isOverWeaving()) { // && !reweavableDataInserted
- // reweavableDataInserted = true;
- return wsi.replaceKeyWithDiff(wovenClassFileData);
- } else {
- return wovenClassFileData;
- }
- }
-
- public void addGeneratedInner(LazyClassGen newClass) {
- classGens.add(newClass);
- }
-
- public void addInterface(ResolvedType newInterface, ISourceLocation sourceLocation) {
- regenerateGenericSignatureAttribute = true;
-
- if (extraSuperInterfaces == null) {
- extraSuperInterfaces = new ResolvedType[1];
- extraSuperInterfaces[0] = newInterface;
- } else {
- ResolvedType[] x = new ResolvedType[extraSuperInterfaces.length + 1];
- System.arraycopy(extraSuperInterfaces, 0, x, 1, extraSuperInterfaces.length);
- x[0] = newInterface;
- extraSuperInterfaces = x;
- }
- myGen.addInterface(newInterface.getRawName());
- if (!newInterface.equals(UnresolvedType.SERIALIZABLE)) {
- warnOnAddedInterface(newInterface.getName(), sourceLocation);
- }
- }
-
- public void setSuperClass(ResolvedType newSuperclass) {
- regenerateGenericSignatureAttribute = true;
- superclass = newSuperclass;
- // myType.addParent(typeX); // used for the attribute
- if (newSuperclass.getGenericType() != null) {
- newSuperclass = newSuperclass.getGenericType();
- }
- myGen.setSuperclassName(newSuperclass.getName()); // used in the real
- // class data
- }
-
- // public String getSuperClassname() {
- // return myGen.getSuperclassName();
- // }
-
- public ResolvedType getSuperClass() {
- if (superclass != null) {
- return superclass;
- }
- return myType.getSuperclass();
- }
-
- public String[] getInterfaceNames() {
- return myGen.getInterfaceNames();
- }
-
- // non-recursive, may be a bug, ha ha.
- private List<LazyClassGen> getClassGens() {
- List<LazyClassGen> ret = new ArrayList<LazyClassGen>();
- ret.add(this);
- ret.addAll(classGens);
- return ret;
- }
-
- public List<UnwovenClassFile.ChildClass> getChildClasses(BcelWorld world) {
- if (classGens.isEmpty()) {
- return Collections.emptyList();
- }
- List<UnwovenClassFile.ChildClass> ret = new ArrayList<UnwovenClassFile.ChildClass>();
- for (LazyClassGen clazz : classGens) {
- byte[] bytes = clazz.getJavaClass(world).getBytes();
- String name = clazz.getName();
- int index = name.lastIndexOf('$');
- // XXX this could be bad, check use of dollar signs.
- name = name.substring(index + 1);
- ret.add(new UnwovenClassFile.ChildClass(name, bytes));
- }
- return ret;
- }
-
- @Override
- public String toString() {
- return toShortString();
- }
-
- public String toShortString() {
- String s = org.aspectj.apache.bcel.classfile.Utility.accessToString(myGen.getModifiers(), true);
- if (!s.equals("")) {
- s += " ";
- }
- s += org.aspectj.apache.bcel.classfile.Utility.classOrInterface(myGen.getModifiers());
- s += " ";
- s += myGen.getClassName();
- return s;
- }
-
- public String toLongString() {
- ByteArrayOutputStream s = new ByteArrayOutputStream();
- print(new PrintStream(s));
- return new String(s.toByteArray());
- }
-
- public void print() {
- print(System.out);
- }
-
- public void print(PrintStream out) {
- List<LazyClassGen> classGens = getClassGens();
- for (Iterator<LazyClassGen> iter = classGens.iterator(); iter.hasNext();) {
- LazyClassGen element = iter.next();
- element.printOne(out);
- if (iter.hasNext()) {
- out.println();
- }
- }
- }
-
- private void printOne(PrintStream out) {
- out.print(toShortString());
- out.print(" extends ");
- out.print(org.aspectj.apache.bcel.classfile.Utility.compactClassName(myGen.getSuperclassName(), false));
-
- int size = myGen.getInterfaces().length;
-
- if (size > 0) {
- out.print(" implements ");
- for (int i = 0; i < size; i++) {
- out.print(myGen.getInterfaceNames()[i]);
- if (i < size - 1) {
- out.print(", ");
- }
- }
- }
- out.print(":");
- out.println();
- // XXX make sure to pass types correctly around, so this doesn't happen.
- if (myType != null) {
- myType.printWackyStuff(out);
- }
- Field[] fields = myGen.getFields();
- for (int i = 0, len = fields.length; i < len; i++) {
- out.print(" ");
- out.println(fields[i]);
- }
- List<LazyMethodGen> methodGens = getMethodGens();
- for (Iterator<LazyMethodGen> iter = methodGens.iterator(); iter.hasNext();) {
- LazyMethodGen gen = iter.next();
- // we skip empty clinits
- if (isEmptyClinit(gen)) {
- continue;
- }
- gen.print(out, (myType != null ? myType.getWeaverVersionAttribute() : WeaverVersionInfo.UNKNOWN));
- if (iter.hasNext()) {
- out.println();
- }
- }
- // out.println(" ATTRIBS: " + Arrays.asList(myGen.getAttributes()));
-
- out.println("end " + toShortString());
- }
-
- private boolean isEmptyClinit(LazyMethodGen gen) {
-
- if (!gen.getName().equals("<clinit>")) {
- return false;
- }
- // System.err.println("checking clinig: " + gen);
- InstructionHandle start = gen.getBody().getStart();
- while (start != null) {
- if (Range.isRangeHandle(start) || (start.getInstruction().opcode == Constants.RETURN)) {
- start = start.getNext();
- } else {
- return false;
- }
- }
-
- return true;
- }
-
- public ConstantPool getConstantPool() {
- return cp;
- }
-
- public String getName() {
- return myGen.getClassName();
- }
-
- public boolean isWoven() {
- return myType.getWeaverState() != null;
- }
-
- public boolean isReweavable() {
- if (myType.getWeaverState() == null) {
- return true;
- }
- return myType.getWeaverState().isReweavable();
- }
-
- public Set<String> getAspectsAffectingType() {
- if (myType.getWeaverState() == null) {
- return null;
- }
- return myType.getWeaverState().getAspectsAffectingType();
- }
-
- public WeaverStateInfo getOrCreateWeaverStateInfo(boolean inReweavableMode) {
- WeaverStateInfo ret = myType.getWeaverState();
- if (ret != null) {
- return ret;
- }
- ret = new WeaverStateInfo(inReweavableMode);
- myType.setWeaverState(ret);
- return ret;
- }
-
- public InstructionFactory getFactory() {
- return fact;
- }
-
- public LazyMethodGen getStaticInitializer() {
- for (LazyMethodGen gen : methodGens) {
- // OPTIMIZE persist kind of member into the gen object? for clinit
- if (gen.getName().equals("<clinit>")) {
- return gen;
- }
- }
- LazyMethodGen clinit = new LazyMethodGen(Modifier.STATIC, Type.VOID, "<clinit>", new Type[0], NO_STRINGS, this);
- clinit.getBody().insert(InstructionConstants.RETURN);
- methodGens.add(clinit);
- return clinit;
- }
-
- /**
- * Retrieve the ajc$preClinit method - this method captures any initialization AspectJ wants to ensure happens in a class. It is
- * called from the static initializer. Maintaining this separation enables overweaving to ignore join points added due to
- * earlier weaves. If the ajc$preClinit method cannot be found, it is created and a call to it is placed in the real static
- * initializer (the call is placed at the start of the static initializer).
- *
- * @return the LazyMethodGen representing the ajc$ clinit
- */
- public LazyMethodGen getAjcPreClinit() {
- if (this.isInterface()) {
- throw new IllegalStateException();
- }
- for (LazyMethodGen methodGen : methodGens) {
- if (methodGen.getName().equals(NameMangler.AJC_PRE_CLINIT_NAME)) {
- return methodGen;
- }
- }
- LazyMethodGen ajcPreClinit = new LazyMethodGen(Modifier.PRIVATE | Modifier.STATIC, Type.VOID,
- NameMangler.AJC_PRE_CLINIT_NAME, Type.NO_ARGS, NO_STRINGS, this);
- ajcPreClinit.getBody().insert(InstructionConstants.RETURN);
- methodGens.add(ajcPreClinit);
- getStaticInitializer().getBody().insert(Utility.createInvoke(fact, ajcPreClinit));
- return ajcPreClinit;
- }
-
- /**
- * factory method for building multiple extended clinit methods. Constructs a new clinit method that invokes the previous one
- * and then returns it. The index is used as a name suffix.
- *
- * @param previousPreClinit
- * @param i
- */
- public LazyMethodGen createExtendedAjcPreClinit(LazyMethodGen previousPreClinit, int i) {
- LazyMethodGen ajcPreClinit = new LazyMethodGen(Modifier.PRIVATE | Modifier.STATIC, Type.VOID,
- NameMangler.AJC_PRE_CLINIT_NAME + i, Type.NO_ARGS, NO_STRINGS, this);
- ajcPreClinit.getBody().insert(InstructionConstants.RETURN);
- methodGens.add(ajcPreClinit);
- previousPreClinit.getBody().insert(Utility.createInvoke(fact, ajcPreClinit));
- return ajcPreClinit;
- }
-
- //
-
- // reflective thisJoinPoint support
- private Map<BcelShadow, Field> tjpFields = new HashMap<BcelShadow, Field>();
- Map<CacheKey, Field> annotationCachingFieldCache = new HashMap<CacheKey, Field>();
- private int tjpFieldsCounter = -1; // -1 means not yet initialized
- private int annoFieldsCounter = 0;
- public static final ObjectType proceedingTjpType = new ObjectType("org.aspectj.lang.ProceedingJoinPoint");
- public static final ObjectType tjpType = new ObjectType("org.aspectj.lang.JoinPoint");
- public static final ObjectType staticTjpType = new ObjectType("org.aspectj.lang.JoinPoint$StaticPart");
- public static final ObjectType typeForAnnotation = new ObjectType("java.lang.annotation.Annotation");
- public static final ObjectType enclosingStaticTjpType = new ObjectType("org.aspectj.lang.JoinPoint$EnclosingStaticPart");
- private static final ObjectType sigType = new ObjectType("org.aspectj.lang.Signature");
- // private static final ObjectType slType =
- // new ObjectType("org.aspectj.lang.reflect.SourceLocation");
- private static final ObjectType factoryType = new ObjectType("org.aspectj.runtime.reflect.Factory");
- private static final ObjectType classType = new ObjectType("java.lang.Class");
-
- public Field getTjpField(BcelShadow shadow, final boolean isEnclosingJp) {
- Field tjpField = tjpFields.get(shadow);
- if (tjpField != null) {
- return tjpField;
- }
-
- int modifiers = Modifier.STATIC;
-
- // J9: Can't always be final on Java 9 because it is set outside of clinit
- // But must be final in interface
- if (shadow.getEnclosingClass().isInterface()) {
- modifiers |= Modifier.FINAL;
- }
-
- // XXX - Do we ever inline before or after advice? If we do, then we
- // better include them in the check below. (or just change it to
- // shadow.getEnclosingMethod().getCanInline())
-
- // If the enclosing method is around advice, we could inline the join
- // point that has led to this shadow. If we do that then the TJP we are
- // creating here must be PUBLIC so it is visible to the type in which the
- // advice is inlined. (PR71377)
- LazyMethodGen encMethod = shadow.getEnclosingMethod();
- boolean shadowIsInAroundAdvice = false;
- if (encMethod != null && encMethod.getName().startsWith(NameMangler.PREFIX + "around")) {
- shadowIsInAroundAdvice = true;
- }
-
- if (getType().isInterface() || shadowIsInAroundAdvice) {
- modifiers |= Modifier.PUBLIC;
- } else {
- modifiers |= Modifier.PRIVATE;
- }
- ObjectType jpType = null;
- // Did not have different static joinpoint types in 1.2
- if (world.isTargettingAspectJRuntime12()) {
- jpType = staticTjpType;
- } else {
- jpType = isEnclosingJp ? enclosingStaticTjpType : staticTjpType;
- }
- if (tjpFieldsCounter == -1) {
- // not yet initialized, do it now
- if (!world.isOverWeaving()) {
- tjpFieldsCounter = 0;
- } else {
- List<BcelField> existingFields = getFieldGens();
- if (existingFields == null) {
- tjpFieldsCounter = 0;
- } else {
- BcelField lastField = null;
- // OPTIMIZE: go from last to first?
- for (BcelField field : existingFields) {
- if (field.getName().startsWith("ajc$tjp_")) {
- lastField = field;
- }
- }
- if (lastField == null) {
- tjpFieldsCounter = 0;
- } else {
- tjpFieldsCounter = Integer.parseInt(lastField.getName().substring(8)) + 1;
- // System.out.println("tjp counter starting at " + tjpFieldsCounter);
- }
- }
- }
- }
- if (!isInterface() && world.isTransientTjpFields()) {
- modifiers|=Modifier.TRANSIENT;
- }
- FieldGen fGen = new FieldGen(modifiers, jpType, "ajc$tjp_" + tjpFieldsCounter++, getConstantPool());
- addField(fGen);
- tjpField = fGen.getField();
- tjpFields.put(shadow, tjpField);
- return tjpField;
- }
-
- /**
- * Create a field in the type containing the shadow where the annotation retrieved during binding can be stored - for later fast
- * access.
- *
- * @param shadow the shadow at which the @annotation result is being cached
- * @return a field
- */
- public Field getAnnotationCachingField(BcelShadow shadow, ResolvedType toType, boolean isWithin) {
- // Multiple annotation types at a shadow. A different field would be required for each
- CacheKey cacheKey = new CacheKey(shadow, toType, isWithin);
- Field field = annotationCachingFieldCache.get(cacheKey);
- // System.out.println(field + " for shadow " + shadow);
- if (field == null) {
- // private static Annotation ajc$anno$<nnn>
- StringBuilder sb = new StringBuilder();
- sb.append(NameMangler.ANNOTATION_CACHE_FIELD_NAME);
- sb.append(annoFieldsCounter++);
- FieldGen annotationCacheField = new FieldGen(Modifier.PRIVATE | Modifier.STATIC, typeForAnnotation, sb.toString(), cp);
- addField(annotationCacheField);
- field = annotationCacheField.getField();
- annotationCachingFieldCache.put(cacheKey, field);
- }
- return field;
- }
-
- static class CacheKey {
- private Object key;
- private ResolvedType annotationType;
-
- // If the annotation is being accessed via @annotation on a shadow then we can use the shadows toString() (so two shadows
- // the same share a variable), but if it is @withincode() or @within() we can't share them (as the shadows may look the same
- // but be occurring 'within' different things). In the within cases we continue to use the shadow itself as the key.
- CacheKey(BcelShadow shadow, ResolvedType annotationType, boolean isWithin) {
- this.key = isWithin ? shadow : shadow.toString();
- this.annotationType = annotationType;
- }
-
- @Override
- public int hashCode() {
- return key.hashCode() * 37 + annotationType.hashCode();
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof CacheKey)) {
- return false;
- }
- CacheKey oCacheKey = (CacheKey) other;
- return key.equals(oCacheKey.key) && annotationType.equals(oCacheKey.annotationType);
- }
- }
-
- // FIXME ATAJ needed only for slow Aspects.aspectOf - keep or remove
- // private void addAjClassField() {
- // // Andy: Why build it again??
- // Field ajClassField = new FieldGen(
- // Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC,
- // classType,
- // "aj$class",
- // getConstantPool()).getField();
- // addField(ajClassField);
- //
- // InstructionList il = new InstructionList();
- // il.append(new PUSH(getConstantPool(), getClassName()));
- // il.append(fact.createInvoke("java.lang.Class", "forName", classType,
- // new Type[] {Type.STRING}, Constants.INVOKESTATIC));
- // il.append(fact.createFieldAccess(getClassName(), ajClassField.getName(),
- // classType, Constants.PUTSTATIC));
- //
- // getStaticInitializer().getBody().insert(il);
- // }
-
- private void addAjcInitializers() {
- if (tjpFields.size() == 0 && !serialVersionUIDRequiresInitialization) {
- return;
- }
- InstructionList[] il = null;
-
- if (tjpFields.size() > 0) {
- il = initializeAllTjps();
- }
-
- if (serialVersionUIDRequiresInitialization) {
- InstructionList[] ilSVUID = new InstructionList[1];
- ilSVUID[0] = new InstructionList();
- ilSVUID[0].append(InstructionFactory.PUSH(getConstantPool(), calculatedSerialVersionUID));
- ilSVUID[0].append(getFactory().createFieldAccess(getClassName(), "serialVersionUID", BasicType.LONG,
- Constants.PUTSTATIC));
- if (il == null) {
- il = ilSVUID;
- } else {
- InstructionList[] newIl = new InstructionList[il.length + ilSVUID.length];
- System.arraycopy(il, 0, newIl, 0, il.length);
- System.arraycopy(ilSVUID, 0, newIl, il.length, ilSVUID.length);
- il = newIl;
- }
- }
-
- LazyMethodGen prevMethod;
- LazyMethodGen nextMethod = null;
- if (this.isInterface()) { // Cannot sneak stuff into another static method in an interface
- prevMethod = getStaticInitializer();
- } else {
- prevMethod = getAjcPreClinit();
- }
- for (int counter = 1; counter <= il.length; counter++) {
- if (il.length > counter) {
- nextMethod = createExtendedAjcPreClinit(prevMethod, counter);
- }
- prevMethod.getBody().insert(il[counter - 1]);
- prevMethod = nextMethod;
- }
- }
-
- private InstructionList initInstructionList() {
- InstructionList list = new InstructionList();
- InstructionFactory fact = getFactory();
-
- // make a new factory
- list.append(fact.createNew(factoryType));
- list.append(InstructionFactory.createDup(1));
-
- list.append(InstructionFactory.PUSH(getConstantPool(), getFileName()));
-
- // load the current Class object
- // XXX check that this works correctly for inners/anonymous
- list.append(fact.PUSHCLASS(cp, myGen.getClassName()));
- // XXX do we need to worry about the fact the theorectically this could
- // throw
- // a ClassNotFoundException
-
- list.append(fact.createInvoke(factoryType.getClassName(), "<init>", Type.VOID, new Type[] { Type.STRING, classType },
- Constants.INVOKESPECIAL));
-
- list.append(InstructionFactory.createStore(factoryType, 0));
- return list;
- }
-
- private InstructionList[] initializeAllTjps() {
- Vector<InstructionList> lists = new Vector<InstructionList>();
-
- InstructionList list = initInstructionList();
- lists.add(list);
-
- List<Map.Entry<BcelShadow, Field>> entries = new ArrayList<Map.Entry<BcelShadow, Field>>(tjpFields.entrySet());
- Collections.sort(entries, new Comparator<Map.Entry<BcelShadow, Field>>() {
- @Override
- public int compare(Map.Entry<BcelShadow, Field> a, Map.Entry<BcelShadow, Field> b) {
- return (a.getValue()).getName().compareTo((b.getValue()).getName());
- }
- });
-
- long estimatedSize = 0;
- for (Iterator<Map.Entry<BcelShadow, Field>> i = entries.iterator(); i.hasNext();) {
- Map.Entry<BcelShadow, Field> entry = i.next();
- if (estimatedSize > Constants.MAX_CODE_SIZE) {
- estimatedSize = 0;
- list = initInstructionList();
- lists.add(list);
- }
- estimatedSize += entry.getValue().getSignature().getBytes().length;
- initializeTjp(fact, list, entry.getValue(), entry.getKey());
- }
- InstructionList listArrayModel[] = new InstructionList[1];
- return lists.toArray(listArrayModel);
- }
-
- private void initializeTjp(InstructionFactory fact, InstructionList list, Field field, BcelShadow shadow) {
- if (world.getTargetAspectjRuntimeLevel() == RuntimeVersion.V1_9) {
- initializeTjpOptimal(fact, list, field, shadow);
- return;
- }
- boolean fastSJP = false;
- // avoid fast SJP if it is for an enclosing joinpoint
- boolean isFastSJPAvailable = shadow.getWorld().isTargettingRuntime1_6_10()
- && !enclosingStaticTjpType.equals(field.getType());
-
- Member sig = shadow.getSignature();
-
- // load the factory
- list.append(InstructionFactory.createLoad(factoryType, 0));
-
- // load the kind
- list.append(InstructionFactory.PUSH(getConstantPool(), shadow.getKind().getName()));
-
- // create the signature
- if (world.isTargettingAspectJRuntime12() || !isFastSJPAvailable || !sig.getKind().equals(Member.METHOD)) {
- list.append(InstructionFactory.createLoad(factoryType, 0));
- }
-
- String signatureMakerName = SignatureUtils.getSignatureMakerName(sig);
- ObjectType signatureType = new ObjectType(SignatureUtils.getSignatureType(sig));
- UnresolvedType[] exceptionTypes = null;
- if (world.isTargettingAspectJRuntime12()) { // TAG:SUPPORTING12: We didn't have optimized factory methods in 1.2
- list.append(InstructionFactory.PUSH(cp, SignatureUtils.getSignatureString(sig, shadow.getWorld())));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
- Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.METHOD)) {
- BcelWorld w = shadow.getWorld();
-
- // For methods, push the parts of the signature on.
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
- list.append(InstructionFactory.PUSH(cp, sig.getName()));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
- exceptionTypes = sig.getExceptions(w);
- if (isFastSJPAvailable && exceptionTypes.length == 0) {
- fastSJP = true;
- } else {
- list.append(InstructionFactory.PUSH(cp, makeString(exceptionTypes)));
- }
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getReturnType())));
- // And generate a call to the variant of makeMethodSig() that takes the strings
- if (isFastSJPAvailable) {
- fastSJP = true;
- } else {
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY7,
- Constants.INVOKEVIRTUAL));
- }
-
- } else if (sig.getKind().equals(Member.MONITORENTER)) {
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
- Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.MONITOREXIT)) {
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
- Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.HANDLER)) {
- BcelWorld w = shadow.getWorld();
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY3,
- Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.CONSTRUCTOR)) {
- BcelWorld w = shadow.getWorld();
- if (w.isJoinpointArrayConstructionEnabled() && sig.getDeclaringType().isArray()) {
- // its the magical new jp
- list.append(InstructionFactory.PUSH(cp, makeString(Modifier.PUBLIC)));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
- list.append(InstructionFactory.PUSH(cp, "")); // sig.getParameterNames?
- list.append(InstructionFactory.PUSH(cp, ""));// sig.getExceptions?
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY5,
- Constants.INVOKEVIRTUAL));
- } else {
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getExceptions(w))));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY5,
- Constants.INVOKEVIRTUAL));
- }
- } else if (sig.getKind().equals(Member.FIELD)) {
- BcelWorld w = shadow.getWorld();
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
- list.append(InstructionFactory.PUSH(cp, sig.getName()));
- // see pr227401
- UnresolvedType dType = sig.getDeclaringType();
- if (dType.getTypekind() == TypeKind.PARAMETERIZED || dType.getTypekind() == TypeKind.GENERIC) {
- dType = sig.getDeclaringType().resolve(world).getGenericType();
- }
- list.append(InstructionFactory.PUSH(cp, makeString(dType)));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getReturnType())));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY4,
- Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.ADVICE)) {
- BcelWorld w = shadow.getWorld();
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
- list.append(InstructionFactory.PUSH(cp, sig.getName()));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterTypes())));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getParameterNames(w))));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getExceptions(w))));
- list.append(InstructionFactory.PUSH(cp, makeString((sig.getReturnType()))));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, new Type[] { Type.STRING,
- Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING }, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.STATIC_INITIALIZATION)) {
- BcelWorld w = shadow.getWorld();
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getModifiers(w))));
- list.append(InstructionFactory.PUSH(cp, makeString(sig.getDeclaringType())));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY2,
- Constants.INVOKEVIRTUAL));
- } else {
- // TODO looks like this block is unused code
- list.append(InstructionFactory.PUSH(cp, SignatureUtils.getSignatureString(sig, shadow.getWorld())));
- list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1,
- Constants.INVOKEVIRTUAL));
- }
-
- // XXX should load source location from shadow
- list.append(Utility.createConstant(fact, shadow.getSourceLine()));
-
- final String factoryMethod;
-
- // TAG:SUPPORTING12: We didn't have makeESJP() in 1.2
- if (world.isTargettingAspectJRuntime12()) {
- list.append(fact.createInvoke(factoryType.getClassName(), "makeSJP", staticTjpType, new Type[] { Type.STRING, sigType,
- Type.INT }, Constants.INVOKEVIRTUAL));
-
- // put it in the field
- list.append(fact.createFieldAccess(getClassName(), field.getName(), staticTjpType, Constants.PUTSTATIC));
-
- } else {
- if (staticTjpType.equals(field.getType())) {
- factoryMethod = "makeSJP";
- } else if (enclosingStaticTjpType.equals(field.getType())) {
- factoryMethod = "makeESJP";
- } else {
- throw new Error("should not happen");
- }
-
- if (fastSJP) {
- if (exceptionTypes != null && exceptionTypes.length != 0) {
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), ARRAY_8STRING_INT,
- Constants.INVOKEVIRTUAL));
- } else {
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), ARRAY_7STRING_INT,
- Constants.INVOKEVIRTUAL));
- }
- } else {
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), new Type[] { Type.STRING,
- sigType, Type.INT }, Constants.INVOKEVIRTUAL));
- }
-
- // put it in the field
- list.append(fact.createFieldAccess(getClassName(), field.getName(), field.getType(), Constants.PUTSTATIC));
- }
- }
-
- public String getFactoryMethod(Field field, BcelShadow shadow) {
- StringBuilder b = new StringBuilder();
- b.append("make");
- MemberKind kind = shadow.getSignature().getKind();
- if (kind.equals(Member.METHOD)) {
- b.append("Method");
- } else if (kind.equals(Member.CONSTRUCTOR)) {
- b.append("Constructor");
- } else if (kind.equals(Member.HANDLER)) {
- b.append("CatchClause");
- } else if (kind.equals(Member.FIELD)) {
- b.append("Field");
- } else if (kind.equals(Member.STATIC_INITIALIZATION)) {
- b.append("Initializer");
- } else if (kind.equals(Member.MONITORENTER)) {
- b.append("Lock");
- } else if (kind.equals(Member.MONITOREXIT)) {
- b.append("Unlock");
- } else if (kind.equals(Member.ADVICE)) {
- b.append("Advice");
- } else {
- throw new IllegalStateException(kind.toString());
- }
- if (staticTjpType.equals(field.getType())) {
- b.append("SJP");
- } else if (enclosingStaticTjpType.equals(field.getType())) {
- b.append("ESJP");
- }
- return b.toString();
- }
-
- /**
- * Generate optimal joinpoint initialization code.
- *
- * As of version 1.9.1 the runtime includes new factory methods for joinpoints that take classes, not strings
- * and using them requires different code generation. Using these instead of the old ones means we can avoid
- * deferred classloading for these types. By using the LDC instruction that loads classes, it also means
- * anything modifying woven code and changing type names will also pick up on these references.
- */
- private void initializeTjpOptimal(InstructionFactory fact, InstructionList list, Field field, BcelShadow shadow) {
- list.append(InstructionFactory.createLoad(factoryType, 0));
- pushString(list, shadow.getKind().getName());
- String factoryMethod = getFactoryMethod(field, shadow);
- Member sig = shadow.getSignature();
- BcelWorld w = shadow.getWorld();
-
- if (sig.getKind().equals(Member.METHOD)) {
- pushInt(list, sig.getModifiers(w));
- pushString(list, sig.getName());
- pushClass(list, sig.getDeclaringType());
- pushClasses(list, sig.getParameterTypes());
- pushStrings(list, sig.getParameterNames(w));
- pushClasses(list, sig.getExceptions(w));
- pushClass(list, sig.getReturnType());
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_METHOD, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.CONSTRUCTOR)) {
- if (w.isJoinpointArrayConstructionEnabled() && sig.getDeclaringType().isArray()) {
- pushInt(list, Modifier.PUBLIC);
- pushClass(list, sig.getDeclaringType());
- pushClasses(list, sig.getParameterTypes());
- pushStrings(list, null);
- pushClasses(list, null);
- } else {
- pushInt(list, sig.getModifiers(w));
- pushClass(list, sig.getDeclaringType());
- pushClasses(list, sig.getParameterTypes());
- pushStrings(list, sig.getParameterNames(w));
- pushClasses(list, sig.getExceptions(w));
- }
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_CONSTRUCTOR, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.HANDLER)) {
- pushClass(list, sig.getDeclaringType());
- pushClass(list, sig.getParameterTypes()[0]);
- String pname = null;
- String[] pnames = sig.getParameterNames(w);
- if (pnames != null && pnames.length>0) {
- pname = pnames[0];
- }
- pushString(list, pname);
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_CATCHCLAUSE, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.FIELD)) {
- pushInt(list, sig.getModifiers(w));
- pushString(list, sig.getName());
- // see pr227401
- UnresolvedType dType = sig.getDeclaringType();
- if (dType.getTypekind() == TypeKind.PARAMETERIZED || dType.getTypekind() == TypeKind.GENERIC) {
- dType = sig.getDeclaringType().resolve(world).getGenericType();
- }
- pushClass(list, dType);
- pushClass(list, sig.getReturnType());
- pushInt(list,shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_FIELD, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.STATIC_INITIALIZATION)) {
- pushInt(list, sig.getModifiers(w));
- pushClass(list, sig.getDeclaringType());
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_INITIALIZER, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.MONITORENTER)) {
- pushClass(list, sig.getDeclaringType());
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_MONITOR, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.MONITOREXIT)) {
- pushClass(list, sig.getDeclaringType());
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_MONITOR, Constants.INVOKEVIRTUAL));
- } else if (sig.getKind().equals(Member.ADVICE)) {
- pushInt(list, sig.getModifiers(w));
- pushString(list, sig.getName());
- pushClass(list, sig.getDeclaringType());
- pushClasses(list, sig.getParameterTypes());
- pushStrings(list, sig.getParameterNames(w));
- pushClasses(list, sig.getExceptions(w));
- pushClass(list, sig.getReturnType());
- pushInt(list, shadow.getSourceLine());
- list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(),
- PARAMSIGNATURE_MAKESJP_ADVICE, Constants.INVOKEVIRTUAL));
- } else {
- throw new IllegalStateException("not sure what to do: "+shadow);
- }
- list.append(fact.createFieldAccess(getClassName(), field.getName(), field.getType(), Constants.PUTSTATIC));
- }
-
- private void pushStrings(InstructionList list, String[] strings) {
- // Build an array loaded with the strings
- if (strings == null || strings.length == 0) {
- list.append(InstructionFactory.ACONST_NULL);
- } else {
- list.append(InstructionFactory.PUSH(cp, strings.length));
- list.append(fact.createNewArray(Type.STRING, (short)1));
- for (int s=0;s<strings.length;s++) {
- list.append(InstructionFactory.DUP);
- list.append(InstructionFactory.PUSH(cp, s));
- list.append(InstructionFactory.PUSH(cp, strings[s]));
- list.append(InstructionFactory.AASTORE);
- }
- }
- }
-
- private void pushClass(InstructionList list, UnresolvedType type) {
- if (type.isPrimitiveType()) {
- if (type.getSignature().equals("I")) {
- list.append(fact.createGetStatic("java/lang/Integer","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("D")) {
- list.append(fact.createGetStatic("java/lang/Double","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("S")) {
- list.append(fact.createGetStatic("java/lang/Short","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("J")) {
- list.append(fact.createGetStatic("java/lang/Long","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("F")) {
- list.append(fact.createGetStatic("java/lang/Float","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("C")) {
- list.append(fact.createGetStatic("java/lang/Character","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("B")) {
- list.append(fact.createGetStatic("java/lang/Byte","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("Z")) {
- list.append(fact.createGetStatic("java/lang/Boolean","TYPE", Type.CLASS));
- } else if (type.getSignature().equals("V")) {
- list.append(InstructionFactory.ACONST_NULL);
- }
- return;
- }
- String classString = makeLdcClassString(type);
- if (classString == null) {
- list.append(InstructionFactory.ACONST_NULL);
- } else {
- list.append(fact.PUSHCLASS(cp, classString));
- }
- }
-
- private void pushClasses(InstructionList list, UnresolvedType[] types) {
- // Build an array loaded with the class objects
- if (types == null || types.length == 0) {
- list.append(InstructionFactory.ACONST_NULL);
- } else {
- list.append(InstructionFactory.PUSH(cp, types.length));
- list.append(fact.createNewArray(Type.CLASS, (short)1));
- for (int t=0;t<types.length;t++) {
- list.append(InstructionFactory.DUP);
- list.append(InstructionFactory.PUSH(cp, t));
- pushClass(list, types[t]);
- list.append(InstructionFactory.AASTORE);
- }
- }
- }
-
- private final void pushString(InstructionList list, String string) {
- list.append(InstructionFactory.PUSH(cp, string));
- }
-
- private final void pushInt(InstructionList list, int value) {
- list.append(InstructionFactory.PUSH(cp, value));
- }
-
- protected String makeString(int i) {
- return Integer.toString(i, 16); // ??? expensive
- }
-
- protected String makeString(UnresolvedType t) {
- // this is the inverse of the odd behavior for Class.forName w/ arrays
- if (t.isArray()) {
- // this behavior matches the string used by the eclipse compiler for
- // Foo.class literals
- return t.getSignature().replace('/', '.');
- } else {
- if (t.isParameterizedType()) {
- return t.getRawType().getName();
- } else {
- return t.getName();
- }
- }
- }
-
- protected String makeLdcClassString(UnresolvedType type) {
- if (type.isVoid() || type.isPrimitiveType()) {
- return null;
- }
- if (type.isArray()) {
- return type.getSignature();
- } else {
- if (type.isParameterizedType()) {
- type = type.getRawType();
- }
- String signature = type.getSignature();
- if (signature.length() ==1 ) {
- return signature;
- }
- return signature.substring(1,signature.length()-1);
- }
- }
-
- protected String makeString(UnresolvedType[] types) {
- if (types == null) {
- return "";
- }
- StringBuilder buf = new StringBuilder();
- for (int i = 0, len = types.length; i < len; i++) {
- if (i > 0) {
- buf.append(':');
- }
- buf.append(makeString(types[i]));
- }
- return buf.toString();
- }
-
- protected String makeString(String[] names) {
- if (names == null) {
- return "";
- }
- StringBuilder buf = new StringBuilder();
- for (int i = 0, len = names.length; i < len; i++) {
- if (i > 0) {
- buf.append(':');
- }
- buf.append(names[i]);
- }
- return buf.toString();
- }
-
- public ResolvedType getType() {
- if (myType == null) {
- return null;
- }
- return myType.getResolvedTypeX();
- }
-
- public BcelObjectType getBcelObjectType() {
- return myType;
- }
-
- public String getFileName() {
- return myGen.getFileName();
- }
-
- // for *new* fields
- private void addField(FieldGen field) {
- makeSyntheticAndTransientIfNeeded(field);
- BcelField bcelField = null;
- if (getBcelObjectType() != null) {
- bcelField = new BcelField(getBcelObjectType(), field.getField());
- } else {
- bcelField = new BcelField(getName(), field.getField(), world);
- }
- fields.add(bcelField);
- // myGen.addField(field.getField());
- }
-
- private void makeSyntheticAndTransientIfNeeded(FieldGen field) {
- if (field.getName().startsWith(NameMangler.PREFIX) && !field.getName().startsWith("ajc$interField$")
- && !field.getName().startsWith("ajc$instance$")) {
- // it's an aj added field
- // first do transient
- if (!field.isStatic()) {
- field.setModifiers(field.getModifiers() | Constants.ACC_TRANSIENT);
- }
- // then do synthetic
- if (getWorld().isInJava5Mode()) {
- // add the synthetic modifier flag
- field.setModifiers(field.getModifiers() | ACC_SYNTHETIC);
- }
- if (!hasSyntheticAttribute(field.getAttributes())) {
- // belt and braces, do the attribute even on Java 5 in addition
- // to the modifier flag
- // Attribute[] oldAttrs = field.getAttributes();
- // Attribute[] newAttrs = new Attribute[oldAttrs.length + 1];
- // System.arraycopy(oldAttrs, 0, newAttrs, 0, oldAttrs.length);
- ConstantPool cpg = myGen.getConstantPool();
- int index = cpg.addUtf8("Synthetic");
- Attribute synthetic = new Synthetic(index, 0, new byte[0], cpg);
- field.addAttribute(synthetic);
- // newAttrs[newAttrs.length - 1] = synthetic;
- // field.setAttributes(newAttrs);
- }
- }
- }
-
- private boolean hasSyntheticAttribute(List<Attribute> attributes) {
- for (int i = 0; i < attributes.size(); i++) {
- if ((attributes.get(i)).getName().equals("Synthetic")) {
- return true;
- }
- }
- return false;
- }
-
- public void addField(FieldGen field, ISourceLocation sourceLocation) {
- addField(field);
- if (!(field.isPrivate() && (field.isStatic() || field.isTransient()))) {
- errorOnAddedField(field, sourceLocation);
- }
- }
-
- public String getClassName() {
- return myGen.getClassName();
- }
-
- public boolean isInterface() {
- return myGen.isInterface();
- }
-
- public boolean isAbstract() {
- return myGen.isAbstract();
- }
-
- public LazyMethodGen getLazyMethodGen(Member m) {
- return getLazyMethodGen(m.getName(), m.getSignature(), false);
- }
-
- public LazyMethodGen getLazyMethodGen(String name, String signature) {
- return getLazyMethodGen(name, signature, false);
- }
-
- public LazyMethodGen getLazyMethodGen(String name, String signature, boolean allowMissing) {
- for (LazyMethodGen gen : methodGens) {
- if (gen.getName().equals(name) && gen.getSignature().equals(signature)) {
- return gen;
- }
- }
-
- if (!allowMissing) {
- throw new BCException("Class " + this.getName() + " does not have a method " + name + " with signature " + signature);
- }
-
- return null;
- }
-
- public void forcePublic() {
- myGen.setModifiers(Utility.makePublic(myGen.getModifiers()));
- }
-
- public boolean hasAnnotation(UnresolvedType t) {
-
- // annotations on the real thing
- AnnotationGen agens[] = myGen.getAnnotations();
- if (agens == null) {
- return false;
- }
- for (int i = 0; i < agens.length; i++) {
- AnnotationGen gen = agens[i];
- if (t.equals(UnresolvedType.forSignature(gen.getTypeSignature()))) {
- return true;
- }
- }
-
- // annotations added during this weave
-
- return false;
- }
-
- public void addAnnotation(AnnotationGen a) {
- if (!hasAnnotation(UnresolvedType.forSignature(a.getTypeSignature()))) {
- annotations.add(new AnnotationGen(a, getConstantPool(), true));
- }
- }
-
- public void addAttribute(AjAttribute attribute) {
- myGen.addAttribute(Utility.bcelAttribute(attribute, getConstantPool()));
- }
-
- public void addAttribute(Attribute attribute) {
- myGen.addAttribute(attribute);
- }
-
- public Collection<Attribute> getAttributes() {
- return myGen.getAttributes();
- }
-
- // this test is like asking:
- // if
- // (UnresolvedType.SERIALIZABLE.resolve(getType().getWorld()).isAssignableFrom
- // (getType())) {
- // only we don't do that because this forces us to find all the supertypes
- // of the type,
- // and if one of them is missing we fail, and it's not worth failing just to
- // put out
- // a warning message!
- private boolean implementsSerializable(ResolvedType aType) {
- if (aType.getSignature().equals(UnresolvedType.SERIALIZABLE.getSignature())) {
- return true;
- }
-
- ResolvedType[] interfaces = aType.getDeclaredInterfaces();
- for (int i = 0; i < interfaces.length; i++) {
- if (interfaces[i].isMissing()) {
- continue;
- }
- if (implementsSerializable(interfaces[i])) {
- return true;
- }
- }
- ResolvedType superType = aType.getSuperclass();
- if (superType != null && !superType.isMissing()) {
- return implementsSerializable(superType);
- }
- return false;
- }
-
- public boolean isAtLeastJava5() {
- return (myGen.getMajor() >= Constants.MAJOR_1_5);
- }
-
- /**
- * Return the next available field name with the specified 'prefix', e.g. for prefix 'class$' where class$0, class$1 exist then
- * return class$2
- */
- public String allocateField(String prefix) {
- int highestAllocated = -1;
- List<BcelField> fs = getFieldGens();
- for (BcelField field : fs) {
- if (field.getName().startsWith(prefix)) {
- try {
- int num = Integer.parseInt(field.getName().substring(prefix.length()));
- if (num > highestAllocated) {
- highestAllocated = num;
- }
- } catch (NumberFormatException nfe) {
- // something wrong with the number on the end of that
- // field...
- }
- }
- }
- return prefix + Integer.toString(highestAllocated + 1);
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
deleted file mode 100644
index 2655a3456..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
+++ /dev/null
@@ -1,1870 +0,0 @@
-/* *******************************************************************
- * 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.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-
-import org.aspectj.apache.bcel.Constants;
-import org.aspectj.apache.bcel.classfile.Attribute;
-import org.aspectj.apache.bcel.classfile.ConstantPool;
-import org.aspectj.apache.bcel.classfile.Method;
-import org.aspectj.apache.bcel.classfile.Synthetic;
-import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
-import org.aspectj.apache.bcel.generic.BranchHandle;
-import org.aspectj.apache.bcel.generic.ClassGenException;
-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.InstructionHandle;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.apache.bcel.generic.InstructionSelect;
-import org.aspectj.apache.bcel.generic.InstructionTargeter;
-import org.aspectj.apache.bcel.generic.LineNumberTag;
-import org.aspectj.apache.bcel.generic.LocalVariableTag;
-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.AjAttribute;
-import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
-import org.aspectj.weaver.AnnotationAJ;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.ISourceContext;
-import org.aspectj.weaver.MemberImpl;
-import org.aspectj.weaver.NameMangler;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.Shadow;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.WeaverMessages;
-import org.aspectj.weaver.World;
-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 and to serialize, but that's it.
- *
- * <p>
- * At any rate, there are two ways to create LazyMethodGens. One is from a method, which does work through MethodGen to do the
- * correct thing. The other is the creation of a completely empty LazyMethodGen, and it is used when we're constructing code from
- * scratch.
- *
- * <p>
- * We stay away from targeters for rangey things like Shadows and Exceptions.
- */
-public final class LazyMethodGen implements Traceable {
-
- private static final AnnotationAJ[] NO_ANNOTATIONAJ = new AnnotationAJ[] {};
-
- private int modifiers;
- private Type returnType;
- private final String name;
- private Type[] argumentTypes;
- // private final String[] argumentNames;
- private String[] declaredExceptions;
- private InstructionList body;
- private List<Attribute> attributes;
- private List<AnnotationAJ> newAnnotations;
- private List<ResolvedType> annotationsForRemoval;
- private AnnotationAJ[][] newParameterAnnotations;
- private final LazyClassGen enclosingClass;
- private BcelMethod memberView;
- private AjAttribute.EffectiveSignatureAttribute effectiveSignature;
- int highestLineNumber = 0;
- boolean wasPackedOptimally = false;
- private Method savedMethod = null;
-
- // Some tools that may post process the output bytecode do not long local variable tables
- // to be generated as one reason the tables may be missing in the first place is because
- // the bytecode is odd. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=470658
- private final boolean originalMethodHasLocalVariableTable;
-
- /*
- * 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 created Tags. (see unpackLocals/unpackLineNumbers). As we have our own copy of Bcel, why
- * not create the right thing straightaway? So setting this to true will call the MethodGen ctor() in such a way that it creates
- * Tags - removing the need for unpackLocals/unpackLineNumbers - HOWEVER see the ensureAllLineNumberSetup() method for some
- * other relevant info.
- *
- * Whats the difference between a Tag and a Gen? A Tag is more lightweight, it doesn't know which instructions it targets, it
- * relies on the instructions targettingit - this reduces the amount of targeter manipulation we have to do.
- */
-
- /**
- * 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 we can get JSR45 information correct. If/when we do _actual_ inlining, we'll need to subtype
- * LineNumberTag to have external line numbers.
- */
- String fromFilename = null;
- private int maxLocals;
- private boolean canInline = true;
- private boolean isSynthetic = false;
- List<BcelShadow> matchedShadows;
- // Used for interface introduction - this is the type of the interface the method is technically on
- public ResolvedType definingType = null;
-
- static class LightweightBcelMethod extends BcelMethod {
-
- LightweightBcelMethod(BcelObjectType declaringType, Method method) {
- super(declaringType, method);
- // TODO Auto-generated constructor stub
- }
-
- }
-
- public LazyMethodGen(int modifiers, Type returnType, String name, Type[] paramTypes, String[] declaredExceptions,
- LazyClassGen enclosingClass) {
- // enclosingClass.getName() + ", " + returnType);
- this.memberView = null; // should be okay, since constructed ones aren't woven into
- this.modifiers = modifiers;
- this.returnType = returnType;
- this.name = name;
- this.argumentTypes = paramTypes;
- // this.argumentNames = Utility.makeArgNames(paramTypes.length);
- this.declaredExceptions = declaredExceptions;
- if (!Modifier.isAbstract(modifiers)) {
- body = new InstructionList();
- setMaxLocals(calculateMaxLocals());
- } else {
- body = null;
- }
- this.attributes = new ArrayList<Attribute>();
- this.enclosingClass = enclosingClass;
- assertGoodBody();
- this.originalMethodHasLocalVariableTable = true; // it is a new method, we want an lvar table
-
- // @AJ advice are not inlined by default since requires further analysis and weaving ordering control
- // TODO AV - improve - note: no room for improvement as long as aspects are reweavable
- // since the inlined version with wrappers and an to be done annotation to keep
- // inline state will be garbaged due to reweavable impl
- if (memberView != null && isAdviceMethod()) {
- if (enclosingClass.getType().isAnnotationStyleAspect()) {
- // TODO we could check for @Around advice as well
- this.canInline = false;
- }
- }
- }
-
- private int calculateMaxLocals() {
- int ret = Modifier.isStatic(modifiers) ? 0 : 1; // will there be a 'this'?
- for (Type type : argumentTypes) {
- ret += type.getSize();
- }
- return ret;
- }
-
- // build from an existing method, lazy build saves most work for
- // initialization
- public LazyMethodGen(Method m, LazyClassGen enclosingClass) {
- savedMethod = m;
-
- this.enclosingClass = enclosingClass;
- if (!(m.isAbstract() || m.isNative()) && m.getCode() == null) {
- throw new RuntimeException("bad non-abstract method with no code: " + m + " on " + enclosingClass);
- }
- if ((m.isAbstract() || m.isNative()) && m.getCode() != null) {
- throw new RuntimeException("bad abstract method with code: " + m + " on " + enclosingClass);
- }
- this.memberView = new BcelMethod(enclosingClass.getBcelObjectType(), m);
- this.originalMethodHasLocalVariableTable = savedMethod.getLocalVariableTable()!=null;
- this.modifiers = m.getModifiers();
- this.name = m.getName();
-
- // @AJ advice are not inlined by default since requires further analysis
- // and weaving ordering control
- // TODO AV - improve - note: no room for improvement as long as aspects
- // are reweavable
- // since the inlined version with wrappers and an to be done annotation
- // to keep
- // inline state will be garbaged due to reweavable impl
- if (memberView != null && isAdviceMethod()) {
- if (enclosingClass.getType().isAnnotationStyleAspect()) {
- // TODO we could check for @Around advice as well
- this.canInline = false;
- }
- }
- }
-
- private boolean isAbstractOrNative(int modifiers) {
- return Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers);
- }
-
- public LazyMethodGen(BcelMethod m, LazyClassGen enclosingClass) {
- savedMethod = m.getMethod();
- this.enclosingClass = enclosingClass;
- if (!isAbstractOrNative(m.getModifiers()) && savedMethod.getCode() == null) {
- throw new RuntimeException("bad non-abstract method with no code: " + m + " on " + enclosingClass);
- }
- if (isAbstractOrNative(m.getModifiers()) && savedMethod.getCode() != null) {
- throw new RuntimeException("bad abstract method with code: " + m + " on " + enclosingClass);
- }
- // this.memberView = new BcelMethod(enclosingClass.getBcelObjectType(),
- // m);
- this.memberView = m;
- this.modifiers = savedMethod.getModifiers();
- this.name = m.getName();
- this.originalMethodHasLocalVariableTable = savedMethod.getLocalVariableTable() != null;
- // @AJ advice are not inlined by default since requires further analysis
- // and weaving ordering control
- // TODO AV - improve - note: no room for improvement as long as aspects
- // are reweavable
- // since the inlined version with wrappers and an to be done annotation
- // to keep
- // inline state will be garbaged due to reweavable impl
- if (memberView != null && isAdviceMethod()) {
- if (enclosingClass.getType().isAnnotationStyleAspect()) {
- // TODO we could check for @Around advice as well
- this.canInline = false;
- }
- }
-
- }
-
- public boolean hasDeclaredLineNumberInfo() {
- return (memberView != null && memberView.hasDeclarationLineNumberInfo());
- }
-
- public int getDeclarationLineNumber() {
- if (hasDeclaredLineNumberInfo()) {
- return memberView.getDeclarationLineNumber();
- } else {
- return -1;
- }
- }
-
- public int getDeclarationOffset() {
- if (hasDeclaredLineNumberInfo()) {
- return memberView.getDeclarationOffset();
- } else {
- return 0;
- }
- }
-
- public void addAnnotation(AnnotationAJ ax) {
- initialize();
- if (memberView == null) {
- // If member view is null, we manage them in newAnnotations
- if (newAnnotations == null) {
- newAnnotations = new ArrayList<AnnotationAJ>();
- }
- newAnnotations.add(ax);
- } else {
- memberView.addAnnotation(ax);
- }
- }
-
- public void removeAnnotation(ResolvedType annotationType) {
- initialize();
- if (memberView == null) {
- // If member view is null, we manage them in newAnnotations
- if (annotationsForRemoval == null) {
- annotationsForRemoval = new ArrayList<ResolvedType>();
- }
- annotationsForRemoval.add(annotationType);
- } else {
- memberView.removeAnnotation(annotationType);
- }
- }
-
- public void addParameterAnnotation(int parameterNumber, AnnotationAJ anno) {
- initialize();
- if (memberView == null) {
- if (newParameterAnnotations == null) {
- // time to create it
- int pcount = getArgumentTypes().length;
- newParameterAnnotations = new AnnotationAJ[pcount][];
- for (int i = 0; i < pcount; i++) {
- if (i == parameterNumber) {
- newParameterAnnotations[i] = new AnnotationAJ[1];
- newParameterAnnotations[i][0] = anno;
- } else {
- newParameterAnnotations[i] = NO_ANNOTATIONAJ;
- }
- }
- } else {
- AnnotationAJ[] currentAnnoArray = newParameterAnnotations[parameterNumber];
- AnnotationAJ[] newAnnoArray = new AnnotationAJ[currentAnnoArray.length + 1];
- System.arraycopy(currentAnnoArray, 0, newAnnoArray, 0, currentAnnoArray.length);
- newAnnoArray[currentAnnoArray.length] = anno;
- newParameterAnnotations[parameterNumber] = newAnnoArray;
- }
- } else {
- memberView.addParameterAnnotation(parameterNumber, anno);
- }
- }
-
- public ResolvedType[] getAnnotationTypes() {
- initialize();
- if (memberView == null && newAnnotations!=null && newAnnotations.size()!=0) {
- // TODO Ignoring removed annotations for now
- ResolvedType[] annotationTypes = new ResolvedType[newAnnotations.size()];
- for (int a=0,len=newAnnotations.size();a<len;a++) {
- annotationTypes[a] = newAnnotations.get(a).getType();
- }
- return annotationTypes;
- }
- return null;
- }
-
- public AnnotationAJ[] getAnnotations() {
- initialize();
- if (memberView == null && newAnnotations!=null && newAnnotations.size()!=0) {
- return newAnnotations.toArray(new AnnotationAJ[newAnnotations.size()]);
- }
- return null;
- }
-
- public boolean hasAnnotation(UnresolvedType annotationType) {
- initialize();
- if (memberView == null) {
- if (annotationsForRemoval != null) {
- for (ResolvedType at : annotationsForRemoval) {
- if (at.equals(annotationType)) {
- return false;
- }
- }
- }
- // Check local annotations first
- if (newAnnotations != null) {
- for (AnnotationAJ annotation : newAnnotations) {
- if (annotation.getTypeSignature().equals(annotationType.getSignature())) {
- return true;
- }
- }
- }
- memberView = new BcelMethod(getEnclosingClass().getBcelObjectType(), getMethod());
- return memberView.hasAnnotation(annotationType);
- }
- return memberView.hasAnnotation(annotationType);
- }
-
- private void initialize() {
- if (returnType != null) {
- return;
- }
- MethodGen gen = new MethodGen(savedMethod, enclosingClass.getName(), enclosingClass.getConstantPool(), true);
-
- this.returnType = gen.getReturnType();
- this.argumentTypes = gen.getArgumentTypes();
- this.declaredExceptions = gen.getExceptions();
- this.attributes = gen.getAttributes();
- // this.annotations = gen.getAnnotations();
- this.maxLocals = gen.getMaxLocals();
-
- // this.returnType = BcelWorld.makeBcelType(memberView.getReturnType());
- // this.argumentTypes =
- // BcelWorld.makeBcelTypes(memberView.getParameterTypes());
- //
- // this.declaredExceptions =
- // UnresolvedType.getNames(memberView.getExceptions());
- // //gen.getExceptions();
- // this.attributes = new Attribute[0]; //gen.getAttributes();
- // this.maxLocals = savedMethod.getCode().getMaxLocals();
-
- if (gen.isAbstract() || gen.isNative()) {
- body = null;
- } else {
- // body = new InstructionList(savedMethod.getCode().getCode());
- body = gen.getInstructionList();
- unpackHandlers(gen);
- ensureAllLineNumberSetup();
- highestLineNumber = gen.getHighestlinenumber();
- }
- assertGoodBody();
- }
-
- // XXX we're relying on the javac promise I've just made up that we won't
- // have an early exception
- // in the list mask a later exception: That is, for two exceptions E and F,
- // if E preceeds F, then either E \cup F = {}, or E \nonstrictsubset F. So
- // when we add F,
- // we add it on the _OUTSIDE_ of any handlers that share starts or ends with
- // it.
-
- // with that in mind, we merrily go adding ranges for exceptions.
-
- private void unpackHandlers(MethodGen gen) {
- CodeExceptionGen[] exns = gen.getExceptionHandlers();
- if (exns != null) {
- int len = exns.length;
- // if (len > 0) hasExceptionHandlers = true;
- int priority = len - 1;
- for (int i = 0; i < len; i++, priority--) {
- CodeExceptionGen exn = exns[i];
-
- InstructionHandle start = Range.genStart(body, getOutermostExceptionStart(exn.getStartPC()));
- InstructionHandle end = Range.genEnd(body, getOutermostExceptionEnd(exn.getEndPC()));
- // this doesn't necessarily handle overlapping correctly!!!
- ExceptionRange er = new ExceptionRange(body, exn.getCatchType() == null ? null : BcelWorld.fromBcel(exn
- .getCatchType()), priority);
- er.associateWithTargets(start, end, exn.getHandlerPC());
- exn.setStartPC(null); // also removes from target
- exn.setEndPC(null); // also removes from target
- exn.setHandlerPC(null); // also removes from target
- }
- gen.removeExceptionHandlers();
- }
- }
-
- private InstructionHandle getOutermostExceptionStart(InstructionHandle ih) {
- while (true) {
- if (ExceptionRange.isExceptionStart(ih.getPrev())) {
- ih = ih.getPrev();
- } else {
- return ih;
- }
- }
- }
-
- private InstructionHandle getOutermostExceptionEnd(InstructionHandle ih) {
- while (true) {
- if (ExceptionRange.isExceptionEnd(ih.getNext())) {
- ih = ih.getNext();
- } else {
- return ih;
- }
- }
- }
-
- /**
- * 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 has the right line number. This is necessary because some of
- * them may be extracted out into other methods - and it'd be useful for them to maintain the source line number for debugging.
- */
- public void ensureAllLineNumberSetup() {
- LineNumberTag lastKnownLineNumberTag = null;
- boolean skip = false;
- for (InstructionHandle ih = body.getStart(); ih != null; ih = ih.getNext()) {
- skip = false;
- for (InstructionTargeter targeter : ih.getTargeters()) {
- if (targeter instanceof LineNumberTag) {
- lastKnownLineNumberTag = (LineNumberTag) targeter;
- skip = true;
- }
- }
- if (lastKnownLineNumberTag != null && !skip) {
- ih.addTargeter(lastKnownLineNumberTag);
- }
- }
- }
-
- // ===============
-
- public int allocateLocal(Type type) {
- return allocateLocal(type.getSize());
- }
-
- public int allocateLocal(int slots) {
- int max = getMaxLocals();
- setMaxLocals(max + slots);
- return max;
- }
-
- public Method getMethod() {
- if (savedMethod != null) {
- return savedMethod; // ??? this relies on gentle treatment of
- // constant pool
- }
-
- try {
- MethodGen gen = pack();
- savedMethod = gen.getMethod();
- return savedMethod;
- } catch (ClassGenException e) {
- enclosingClass
- .getBcelObjectType()
- .getResolvedTypeX()
- .getWorld()
- .showMessage(
- IMessage.ERROR,
- WeaverMessages.format(WeaverMessages.PROBLEM_GENERATING_METHOD, this.getClassName(), this.getName(),
- e.getMessage()),
- this.getMemberView() == null ? null : this.getMemberView().getSourceLocation(), null);
- // throw e; PR 70201.... let the normal problem reporting
- // infrastructure deal with this rather than crashing.
- body = null;
- MethodGen gen = pack();
- return gen.getMethod();
- } catch (RuntimeException re) {
- if (re.getCause() instanceof ClassGenException) {
- enclosingClass
- .getBcelObjectType()
- .getResolvedTypeX()
- .getWorld()
- .showMessage(
- IMessage.ERROR,
- WeaverMessages.format(WeaverMessages.PROBLEM_GENERATING_METHOD, this.getClassName(),
- this.getName(), re.getCause().getMessage()),
- this.getMemberView() == null ? null : this.getMemberView().getSourceLocation(), null);
- // throw e; PR 70201.... let the normal problem reporting
- // infrastructure deal with this rather than crashing.
- body = null;
- MethodGen gen = pack();
- return gen.getMethod();
- }
- throw re;
- }
- }
-
- public void markAsChanged() {
- if (wasPackedOptimally) {
- throw new RuntimeException("Already packed method is being re-modified: " + getClassName() + " " + toShortString());
- }
- initialize();
- savedMethod = null;
- }
-
- // =============================
-
- @Override
- public String toString() {
- BcelObjectType bot = enclosingClass.getBcelObjectType();
- WeaverVersionInfo weaverVersion = (bot == null ? WeaverVersionInfo.CURRENT : bot.getWeaverVersionAttribute());
- return toLongString(weaverVersion);
- }
-
- public String toShortString() {
- String access = org.aspectj.apache.bcel.classfile.Utility.accessToString(getAccessFlags());
-
- StringBuffer buf = new StringBuffer();
-
- if (!access.equals("")) {
- buf.append(access);
- buf.append(" ");
- }
- buf.append(org.aspectj.apache.bcel.classfile.Utility.signatureToString(getReturnType().getSignature(), true));
- buf.append(" ");
- buf.append(getName());
- buf.append("(");
- {
- int len = argumentTypes.length;
- if (len > 0) {
- buf.append(org.aspectj.apache.bcel.classfile.Utility.signatureToString(argumentTypes[0].getSignature(), true));
- for (int i = 1; i < argumentTypes.length; i++) {
- buf.append(", ");
- buf.append(org.aspectj.apache.bcel.classfile.Utility.signatureToString(argumentTypes[i].getSignature(), true));
- }
- }
- }
- buf.append(")");
-
- {
- int len = declaredExceptions != null ? declaredExceptions.length : 0;
- if (len > 0) {
- buf.append(" throws ");
- buf.append(declaredExceptions[0]);
- for (int i = 1; i < declaredExceptions.length; i++) {
- buf.append(", ");
- buf.append(declaredExceptions[i]);
- }
- }
- }
- return buf.toString();
- }
-
- public String toLongString(WeaverVersionInfo weaverVersion) {
- ByteArrayOutputStream s = new ByteArrayOutputStream();
- print(new PrintStream(s), weaverVersion);
- return new String(s.toByteArray());
- }
-
- public void print(WeaverVersionInfo weaverVersion) {
- print(System.out, weaverVersion);
- }
-
- public void print(PrintStream out, WeaverVersionInfo weaverVersion) {
- out.print(" " + toShortString());
- printAspectAttributes(out, weaverVersion);
-
- InstructionList body = getBody();
- if (body == null) {
- out.println(";");
- return;
- }
- out.println(":");
- new BodyPrinter(out).run();
- out.println(" end " + toShortString());
- }
-
- private void printAspectAttributes(PrintStream out, WeaverVersionInfo weaverVersion) {
- ISourceContext context = null;
- if (enclosingClass != null && enclosingClass.getType() != null) {
- context = enclosingClass.getType().getSourceContext();
- }
- List<AjAttribute> as = Utility.readAjAttributes(getClassName(), attributes.toArray(new Attribute[] {}), context, null, weaverVersion,
- new BcelConstantPoolReader(this.enclosingClass.getConstantPool()));
- if (!as.isEmpty()) {
- out.println(" " + as.get(0)); // XXX assuming exactly one
- // attribute, munger...
- }
- }
-
- private class BodyPrinter {
- Map<InstructionHandle, String> labelMap = new HashMap<InstructionHandle, String>();
-
- InstructionList body;
- PrintStream out;
- ConstantPool pool;
-
- BodyPrinter(PrintStream out) {
- this.pool = enclosingClass.getConstantPool();
- this.body = getBodyForPrint();
- this.out = out;
- }
-
- BodyPrinter(PrintStream out, InstructionList il) {
- this.pool = enclosingClass.getConstantPool();
- this.body = il;
- this.out = out;
- }
-
- void run() {
- // killNops();
- assignLabels();
- print();
- }
-
- // label assignment
- void assignLabels() {
- LinkedList<ExceptionRange> exnTable = new LinkedList<ExceptionRange>();
- String pendingLabel = null;
- // boolean hasPendingTargeters = false;
- int lcounter = 0;
- for (InstructionHandle ih = body.getStart(); ih != null; ih = ih.getNext()) {
- Iterator<InstructionTargeter> tIter = ih.getTargeters().iterator();
- while (tIter.hasNext()) {
- InstructionTargeter t = tIter.next();// targeters
- // [
- // i
- // ]
- // ;
- if (t instanceof ExceptionRange) {
- // assert isRangeHandle(h);
- ExceptionRange r = (ExceptionRange) t;
- if (r.getStart() == ih) {
- insertHandler(r, exnTable);
- }
- } else if (t instanceof InstructionBranch) {
- if (pendingLabel == null) {
- pendingLabel = "L" + lcounter++;
- }
- } else {
- // assert isRangeHandle(h)
- }
- }
- if (pendingLabel != null) {
- labelMap.put(ih, pendingLabel);
- if (!Range.isRangeHandle(ih)) {
- pendingLabel = null;
- }
- }
- }
- int ecounter = 0;
- for (ExceptionRange er: exnTable) {
- String exceptionLabel = "E" + ecounter++;
- labelMap.put(Range.getRealStart(er.getHandler()), exceptionLabel);
- labelMap.put(er.getHandler(), exceptionLabel);
- }
- }
-
- // printing
-
- void print() {
- int depth = 0;
- int currLine = -1;
- bodyPrint: for (InstructionHandle ih = body.getStart(); ih != null; ih = ih.getNext()) {
- if (Range.isRangeHandle(ih)) {
- Range r = Range.getRange(ih);
- // don't print empty ranges, that is, ranges who contain no
- // actual instructions
- for (InstructionHandle xx = r.getStart(); Range.isRangeHandle(xx); xx = xx.getNext()) {
- if (xx == r.getEnd()) {
- continue bodyPrint;
- }
- }
-
- // doesn't handle nested: if (r.getStart().getNext() ==
- // r.getEnd()) continue;
- if (r.getStart() == ih) {
- printRangeString(r, depth++);
- } else {
- if (r.getEnd() != ih) {
- throw new RuntimeException("bad");
- }
- printRangeString(r, --depth);
- }
- } else {
- printInstruction(ih, depth);
- int line = getLineNumber(ih, currLine);
- if (line != currLine) {
- currLine = line;
- out.println(" (line " + line + ")");
- } else {
- out.println();
- }
- }
- }
- }
-
- void printRangeString(Range r, int depth) {
- printDepth(depth);
- out.println(getRangeString(r, labelMap));
- }
-
- String getRangeString(Range r, Map<InstructionHandle, String> labelMap) {
- if (r instanceof ExceptionRange) {
- ExceptionRange er = (ExceptionRange) r;
- return er.toString() + " -> " + labelMap.get(er.getHandler());
- //
- // + " PRI " + er.getPriority();
- } else {
- return r.toString();
- }
- }
-
- void printDepth(int depth) {
- pad(BODY_INDENT);
- while (depth > 0) {
- out.print("| ");
- depth--;
- }
- }
-
- void printLabel(String s, int depth) {
- int space = Math.max(CODE_INDENT - depth * 2, 0);
- if (s == null) {
- pad(space);
- } else {
- space = Math.max(space - (s.length() + 2), 0);
- pad(space);
- out.print(s);
- out.print(": ");
- }
- }
-
- void printInstruction(InstructionHandle h, int depth) {
- printDepth(depth);
- printLabel(labelMap.get(h), depth);
-
- Instruction inst = h.getInstruction();
- if (inst.isConstantPoolInstruction()) {
- out.print(Constants.OPCODE_NAMES[inst.opcode].toUpperCase());
- out.print(" ");
- out.print(pool.constantToString(pool.getConstant(inst.getIndex())));
- } else if (inst instanceof InstructionSelect) {
- InstructionSelect sinst = (InstructionSelect) inst;
- out.println(Constants.OPCODE_NAMES[sinst.opcode].toUpperCase());
- int[] matches = sinst.getMatchs();
- InstructionHandle[] targets = sinst.getTargets();
- InstructionHandle defaultTarget = sinst.getTarget();
- for (int i = 0, len = matches.length; i < len; i++) {
- printDepth(depth);
- printLabel(null, depth);
- out.print(" ");
- out.print(matches[i]);
- out.print(": \t");
- out.println(labelMap.get(targets[i]));
- }
- printDepth(depth);
- printLabel(null, depth);
- out.print(" ");
- out.print("default: \t");
- out.print(labelMap.get(defaultTarget));
- } else if (inst instanceof InstructionBranch) {
- InstructionBranch brinst = (InstructionBranch) inst;
- out.print(Constants.OPCODE_NAMES[brinst.getOpcode()].toUpperCase());
- out.print(" ");
- out.print(labelMap.get(brinst.getTarget()));
- } else if (inst.isLocalVariableInstruction()) {
- // LocalVariableInstruction lvinst = (LocalVariableInstruction)
- // inst;
- out.print(inst.toString(false).toUpperCase());
- int index = inst.getIndex();
- LocalVariableTag tag = getLocalVariableTag(h, index);
- if (tag != null) {
- out.print(" // ");
- out.print(tag.getType());
- out.print(" ");
- out.print(tag.getName());
- }
- } else {
- out.print(inst.toString(false).toUpperCase());
- }
- }
-
- static final int BODY_INDENT = 4;
- static final int CODE_INDENT = 16;
-
- void pad(int size) {
- for (int i = 0; i < size; i++) {
- out.print(" ");
- }
- }
- }
-
- static LocalVariableTag getLocalVariableTag(InstructionHandle ih, int index) {
- for (InstructionTargeter t : ih.getTargeters()) {
- if (t instanceof LocalVariableTag) {
- LocalVariableTag lvt = (LocalVariableTag) t;
- if (lvt.getSlot() == index) {
- return lvt;
- }
- }
- }
- return null;
- }
-
- static int getLineNumber(InstructionHandle ih, int prevLine) {
- for (InstructionTargeter t : ih.getTargeters()) {
- if (t instanceof LineNumberTag) {
- return ((LineNumberTag) t).getLineNumber();
- }
- }
- return prevLine;
- }
-
- public boolean isStatic() {
- return Modifier.isStatic(getAccessFlags());
- }
-
- public boolean isAbstract() {
- return Modifier.isAbstract(getAccessFlags());
- }
-
- public boolean isBridgeMethod() {
- return (getAccessFlags() & Constants.ACC_BRIDGE) != 0;
- }
-
- public void addExceptionHandler(InstructionHandle start, InstructionHandle end, InstructionHandle handlerStart,
- ObjectType catchType, boolean highPriority) {
-
- InstructionHandle start1 = Range.genStart(body, start);
- InstructionHandle end1 = Range.genEnd(body, end);
-
- ExceptionRange er = new ExceptionRange(body, (catchType == null ? null : BcelWorld.fromBcel(catchType)), highPriority);
- er.associateWithTargets(start1, end1, handlerStart);
- }
-
- public int getAccessFlags() {
- return modifiers;
- }
-
- public int getAccessFlagsWithoutSynchronized() {
- if (isSynchronized()) {
- return modifiers - Modifier.SYNCHRONIZED;
- }
- return modifiers;
- }
-
- public boolean isSynchronized() {
- return (modifiers & Modifier.SYNCHRONIZED) != 0;
- }
-
- public void setAccessFlags(int newFlags) {
- this.modifiers = newFlags;
- }
-
- public Type[] getArgumentTypes() {
- initialize();
- return argumentTypes;
- }
-
- public LazyClassGen getEnclosingClass() {
- return enclosingClass;
- }
-
- public int getMaxLocals() {
- return maxLocals;
- }
-
- public String getName() {
- return name;
- }
-
- public String getGenericReturnTypeSignature() {
- if (memberView == null) {
- return getReturnType().getSignature();
- } else {
- return memberView.getGenericReturnType().getSignature();
- }
- }
-
- public Type getReturnType() {
- initialize();
- return returnType;
- }
-
- public void setMaxLocals(int maxLocals) {
- this.maxLocals = maxLocals;
- }
-
- public InstructionList getBody() {
- markAsChanged();
- return body;
- }
-
- public InstructionList getBodyForPrint() {
- return body;
- }
-
- public boolean hasBody() {
- if (savedMethod != null) {
- return savedMethod.getCode() != null;
- }
- return body != null;
- }
-
- public List<Attribute> getAttributes() {
- return attributes;
- }
-
- public String[] getDeclaredExceptions() {
- return declaredExceptions;
- }
-
- public String getClassName() {
- return enclosingClass.getName();
- }
-
- // ---- packing!
-
- public MethodGen pack() {
- forceSyntheticForAjcMagicMembers();
-
- // killNops();
- int flags = getAccessFlags();
- if (enclosingClass.getWorld().isJoinpointSynchronizationEnabled()
- && enclosingClass.getWorld().areSynchronizationPointcutsInUse()) {
- flags = getAccessFlagsWithoutSynchronized();
- }
- MethodGen gen = new MethodGen(flags, getReturnType(), getArgumentTypes(), null, // getArgumentNames(),
- getName(), getEnclosingClass().getName(), new InstructionList(), getEnclosingClass().getConstantPool());
- for (int i = 0, len = declaredExceptions.length; i < len; i++) {
- gen.addException(declaredExceptions[i]);
- }
-
- for (Attribute attr : attributes) {
- gen.addAttribute(attr);
- }
-
- if (newAnnotations != null) {
- for (AnnotationAJ element : newAnnotations) {
- gen.addAnnotation(new AnnotationGen(((BcelAnnotation) element).getBcelAnnotation(), gen.getConstantPool(), true));
- }
- }
-
- if (newParameterAnnotations != null) {
- for (int i = 0; i < newParameterAnnotations.length; i++) {
- AnnotationAJ[] annos = newParameterAnnotations[i];
- for (int j = 0; j < annos.length; j++) {
- gen.addParameterAnnotation(i,
- new AnnotationGen(((BcelAnnotation) annos[j]).getBcelAnnotation(), gen.getConstantPool(), true));
- }
- }
- }
-
- if (memberView != null && memberView.getAnnotations() != null && memberView.getAnnotations().length != 0) {
- AnnotationAJ[] ans = memberView.getAnnotations();
- for (int i = 0, len = ans.length; i < len; i++) {
- AnnotationGen a = ((BcelAnnotation) ans[i]).getBcelAnnotation();
- gen.addAnnotation(new AnnotationGen(a, gen.getConstantPool(), true));
- }
- }
-
- if (isSynthetic) {
- if (enclosingClass.getWorld().isInJava5Mode()) {
- gen.setModifiers(gen.getModifiers() | Constants.ACC_SYNTHETIC);
- }
- if (!hasAttribute("Synthetic")) {
- // belt and braces, do the attribute even on Java 5 in addition to the modifier flag
- ConstantPool cpg = gen.getConstantPool();
- int index = cpg.addUtf8("Synthetic");
- gen.addAttribute(new Synthetic(index, 0, new byte[0], cpg));
- }
- }
-
- if (hasBody()) {
- if (this.enclosingClass.getWorld().shouldFastPackMethods()) {
- if (isAdviceMethod() || getName().equals("<clinit>")) {
- packBody(gen);
- } else {
- optimizedPackBody(gen);
- }
- } else {
- packBody(gen);
- }
-
- gen.setMaxLocals(true);
- gen.setMaxStack();
- } else {
- gen.setInstructionList(null);
- }
- return gen;
- }
-
- private boolean hasAttribute(String attributeName) {
- for (Attribute attr: attributes) {
- if (attr.getName().equals(attributeName)) {
- return true;
- }
- }
- return false;
- }
-
- private void forceSyntheticForAjcMagicMembers() {
- if (NameMangler.isSyntheticMethod(getName(), inAspect())) {
- makeSynthetic();
- }
- }
-
- private boolean inAspect() {
- BcelObjectType objectType = enclosingClass.getBcelObjectType();
- return (objectType == null ? false : objectType.isAspect());
- }
-
- public void makeSynthetic() {
- isSynthetic = true;
- }
-
- private static class LVPosition {
- InstructionHandle start = null;
- InstructionHandle end = null;
- }
-
- /**
- * fill the newly created method gen with our body, inspired by InstructionList.copy()
- */
- public void packBody(MethodGen gen) {
- InstructionList fresh = gen.getInstructionList();
- Map<InstructionHandle, InstructionHandle> map = copyAllInstructionsExceptRangeInstructionsInto(fresh);
-
- // at this point, no rangeHandles are in fresh. Let's use that...
-
- /*
- * Update branch targets and insert various attributes. Insert our exceptionHandlers into a sorted list, so they can be
- * added in order later.
- */
- InstructionHandle oldInstructionHandle = getBody().getStart();
- InstructionHandle newInstructionHandle = fresh.getStart();
- LinkedList<ExceptionRange> exceptionList = new LinkedList<ExceptionRange>();
-
- Map<LocalVariableTag, LVPosition> localVariables = new HashMap<LocalVariableTag, LVPosition>();
-
- int currLine = -1;
- int lineNumberOffset = (fromFilename == null) ? 0 : getEnclosingClass().getSourceDebugExtensionOffset(fromFilename);
-
- while (oldInstructionHandle != null) {
- if (map.get(oldInstructionHandle) == null) {
- // must be a range instruction since they're the only things we
- // didn't copy across
- handleRangeInstruction(oldInstructionHandle, exceptionList);
- // just increment ih.
- oldInstructionHandle = oldInstructionHandle.getNext();
- } else {
- // assert map.get(ih) == jh
- Instruction oldInstruction = oldInstructionHandle.getInstruction();
- Instruction newInstruction = newInstructionHandle.getInstruction();
-
- if (oldInstruction instanceof InstructionBranch) {
- handleBranchInstruction(map, oldInstruction, newInstruction);
- }
-
- // now deal with line numbers
- // and store up info for local variables
- for (InstructionTargeter targeter : oldInstructionHandle.getTargeters()) {
- if (targeter instanceof LineNumberTag) {
- int line = ((LineNumberTag) targeter).getLineNumber();
- if (line != currLine) {
- gen.addLineNumber(newInstructionHandle, line + lineNumberOffset);
- currLine = line;
- }
- } else if (targeter instanceof LocalVariableTag) {
- LocalVariableTag lvt = (LocalVariableTag) targeter;
- LVPosition p = 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 = newInstructionHandle;
- localVariables.put(lvt, newp);
- } else {
- p.end = newInstructionHandle;
- }
- }
- }
-
- // now continue
- oldInstructionHandle = oldInstructionHandle.getNext();
- newInstructionHandle = newInstructionHandle.getNext();
- }
- }
-
- addExceptionHandlers(gen, map, exceptionList);
- if (originalMethodHasLocalVariableTable || enclosingClass
- .getBcelObjectType()
- .getResolvedTypeX()
- .getWorld().generateNewLvts) {
- if (localVariables.size() == 0) {
- // Might be a case of 173978 where around advice on an execution join point
- // has caused everything to be extracted from the method and thus we
- // are left with no local variables, not even the ones for 'this' and
- // parameters passed to the method
- createNewLocalVariables(gen);
- } else {
- 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);
- }
- }
-
- private void createNewLocalVariables(MethodGen gen) {
- gen.removeLocalVariables();
- // ignore <clinit> or <init> for now
- if (!getName().startsWith("<")) {
- int slot = 0;
- InstructionHandle start = gen.getInstructionList().getStart();
- InstructionHandle end = gen.getInstructionList().getEnd();
- // Add a 'this' if non-static
- if (!isStatic()) {
- String cname = this.enclosingClass.getClassName();
- if (cname == null) {
- return; // give up for now
- }
- Type enclosingType = BcelWorld.makeBcelType(UnresolvedType.forName(cname));
- gen.addLocalVariable("this", enclosingType, slot++, start, end);
- }
- // Add entries for the method arguments
- String[] paramNames = (memberView == null ? null : memberView.getParameterNames());
- if (paramNames != null) {
- for (int i = 0; i < argumentTypes.length; i++) {
- String pname = paramNames[i];
- if (pname == null) {
- pname = "arg" + i;
- }
- gen.addLocalVariable(pname, argumentTypes[i], slot, start, end);
- slot += argumentTypes[i].getSize();
- }
- }
- }
- }
-
- private World getWorld() {
- return enclosingClass.getBcelObjectType().getResolvedTypeX().getWorld();
- }
- /*
- * Optimized packing that does a 'local packing' of the code rather than building a brand new method and packing into it. Only
- * usable when the packing is going to be done just once.
- */
- public void optimizedPackBody(MethodGen gen) {
- InstructionList theBody = getBody();
- InstructionHandle iHandle = theBody.getStart();
-
- int currLine = -1;
- int lineNumberOffset = (fromFilename == null) ? 0 : getEnclosingClass().getSourceDebugExtensionOffset(fromFilename);
- Map<LocalVariableTag, LVPosition> localVariables = new HashMap<LocalVariableTag, LVPosition>();
- LinkedList<ExceptionRange> exceptionList = new LinkedList<ExceptionRange>();
- Set<InstructionHandle> forDeletion = new HashSet<InstructionHandle>();
- Set<BranchHandle> branchInstructions = new HashSet<BranchHandle>();
- // 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((BranchHandle) iHandle);
- }
-
- for (InstructionTargeter targeter : iHandle.getTargetersCopy()) {
- 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 = 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 (BranchHandle branchHandle : branchInstructions) {
- handleBranchInstruction(branchHandle, forDeletion);
- }
- // now add exception handlers
- for (ExceptionRange r : exceptionList) {
- 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 (InstructionHandle handle : forDeletion) {
- try {
- theBody.delete(handle);
- } catch (TargetLostException e) {
- e.printStackTrace();
- }
- }
- gen.setInstructionList(theBody);
- if (originalMethodHasLocalVariableTable || getWorld().generateNewLvts) {
- if (localVariables.size() == 0) {
- // Might be a case of 173978 where around advice on an execution join point
- // has caused everything to be extracted from the method and thus we
- // are left with no local variables, not even the ones for 'this' and
- // parameters passed to the method
- createNewLocalVariables(gen);
- } else {
- 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);
- }
- wasPackedOptimally = true;
- }
-
- private void addLocalVariables(MethodGen gen, Map<LocalVariableTag, LVPosition> localVariables) {
- // now add local variables
- gen.removeLocalVariables();
-
- // this next iteration _might_ be overkill, but we had problems with
- // bcel before with duplicate local variables. Now that we're patching
- // bcel we should be able to do without it if we're paranoid enough
- // through the rest of the compiler.
- InstructionHandle methodStart = gen.getInstructionList().getStart();
- InstructionHandle methodEnd = gen.getInstructionList().getEnd();
-
- // Determine how many 'slots' are used by parameters to the method.
- // Then below we can determine if a local variable is a parameter variable, if it is
- // we force its range to from the method start (as it may have been shuffled down
- // due to insertion of advice like cflow entry)
- int paramSlots = gen.isStatic() ? 0 : 1;
- Type[] argTypes = gen.getArgumentTypes();
- if (argTypes != null) {
- for (int i = 0; i < argTypes.length; i++) {
- if (argTypes[i].getSize() == 2) {
- paramSlots += 2;
- } else {
- paramSlots += 1;
- }
- }
- }
- if (!this.enclosingClass.getWorld().generateNewLvts) {
- // Here the generateNewLvts option is used to control "Do not damage unusually positioned local
- // variables that represent method parameters". Strictly speaking local variables that represent
- // method parameters effectively have a bytecode range from 0..end_of_method - however some
- // tools generate bytecode that specifies a compressed range. The code below would normally
- // extend the parameter local variables to cover the full method but by setting paramSlots to -1
- // here we cause the code below to avoid modifying any local vars that represent method
- // parameters.
- paramSlots = -1;
- }
-
- Map<InstructionHandle, Set<Integer>> duplicatedLocalMap = new HashMap<InstructionHandle, Set<Integer>>();
- for (LocalVariableTag tag : localVariables.keySet()) {
- // have we already added one with the same slot number and start
- // location?
- // if so, just continue.
- LVPosition lvpos = localVariables.get(tag);
- InstructionHandle start = (tag.getSlot() < paramSlots ? methodStart : lvpos.start);
- InstructionHandle end = (tag.getSlot() < paramSlots ? methodEnd : lvpos.end);
- Set<Integer> slots = duplicatedLocalMap.get(start);
- if (slots == null) {
- slots = new HashSet<Integer>();
- duplicatedLocalMap.put(start, slots);
- } else if (slots.contains(new Integer(tag.getSlot()))) {
- // we already have a var starting at this tag with this slot
- continue;
- }
- slots.add(Integer.valueOf(tag.getSlot()));
- Type t = tag.getRealType();
- if (t == null) {
- t = BcelWorld.makeBcelType(UnresolvedType.forSignature(tag.getType()));
- }
- gen.addLocalVariable(tag.getName(), t, tag.getSlot(), start, end);
- }
- }
-
- private void addExceptionHandlers(MethodGen gen, Map<InstructionHandle, InstructionHandle> map,
- LinkedList<ExceptionRange> exnList) {
- // now add exception handlers
- for (ExceptionRange r : exnList) {
- if (r.isEmpty()) {
- continue;
- }
- InstructionHandle rMappedStart = remap(r.getRealStart(), map);
- InstructionHandle rMappedEnd = remap(r.getRealEnd(), map);
- InstructionHandle rMappedHandler = remap(r.getHandler(), map);
- gen.addExceptionHandler(rMappedStart, rMappedEnd, rMappedHandler, (r.getCatchType() == null) ? null
- : (ObjectType) BcelWorld.makeBcelType(r.getCatchType()));
- }
- }
-
- private void handleBranchInstruction(Map<InstructionHandle, InstructionHandle> map, Instruction oldInstruction,
- Instruction newInstruction) {
- InstructionBranch oldBranchInstruction = (InstructionBranch) oldInstruction;
- InstructionBranch newBranchInstruction = (InstructionBranch) newInstruction;
- InstructionHandle oldTarget = oldBranchInstruction.getTarget(); // old
- // target
-
- // New target is in hash map
- newBranchInstruction.setTarget(remap(oldTarget, map));
-
- 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
- newTargets[k] = remap(oldTargets[k], map);
- newTargets[k].addTargeter(newBranchInstruction);
- }
- }
- }
-
- private InstructionHandle jumpForward(InstructionHandle t, Set<InstructionHandle> handlesForDeletion) {
- InstructionHandle target = t;
- if (handlesForDeletion.contains(target)) {
- do {
- target = target.getNext();
- } while (handlesForDeletion.contains(target));
- }
- return target;
- }
-
- /**
- * Process a branch instruction with respect to instructions that are about to be deleted. If the target for the branch is a
- * candidate for deletion, move it to the next valid instruction after the deleted target.
- */
- private void handleBranchInstruction(BranchHandle branchHandle, Set<InstructionHandle> 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
- InstructionSelect iSelect = (InstructionSelect) branchInstruction;
- InstructionHandle[] targets = iSelect.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));
- iSelect.setTarget(k, oneTarget);
- oneTarget.addTargeter(branchInstruction);
- }
- }
- }
- }
-
- private void handleRangeInstruction(InstructionHandle ih, LinkedList<ExceptionRange> exnList) {
- // we're a range instruction
- Range r = Range.getRange(ih);
- if (r instanceof ExceptionRange) {
- ExceptionRange er = (ExceptionRange) r;
- if (er.getStart() == ih) {
- // System.err.println("er " + er);
- if (!er.isEmpty()) {
- // order is important, insert handlers in order of start
- insertHandler(er, exnList);
- }
- }
- } else {
- // we must be a shadow range or something equally useless,
- // so forget about doing anything
- }
- }
-
- /*
- * Make copies of all instructions, append them to the new list and associate old instruction references with the new ones,
- * i.e., a 1:1 mapping.
- */
- private Map<InstructionHandle, InstructionHandle> copyAllInstructionsExceptRangeInstructionsInto(InstructionList intoList) {
- Map<InstructionHandle, InstructionHandle> map = new HashMap<InstructionHandle, InstructionHandle>();
- for (InstructionHandle ih = getBody().getStart(); ih != null; ih = ih.getNext()) {
- if (Range.isRangeHandle(ih)) {
- continue;
- }
- Instruction inst = ih.getInstruction();
- Instruction copy = Utility.copyInstruction(inst);
-
- if (copy instanceof InstructionBranch) {
- map.put(ih, intoList.append((InstructionBranch) copy));
- } else {
- map.put(ih, intoList.append(copy));
- }
- }
- return map;
- }
-
- /**
- * This procedure should not currently be used.
- */
- // public void killNops() {
- // InstructionHandle curr = body.getStart();
- // while (true) {
- // if (curr == null) break;
- // InstructionHandle next = curr.getNext();
- // if (curr.getInstruction() instanceof NOP) {
- // InstructionTargeter[] targeters = curr.getTargeters();
- // if (targeters != null) {
- // for (int i = 0, len = targeters.length; i < len; i++) {
- // InstructionTargeter targeter = targeters[i];
- // targeter.updateTarget(curr, next);
- // }
- // }
- // try {
- // body.delete(curr);
- // } catch (TargetLostException e) {
- // }
- // }
- // 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 handle, Map<InstructionHandle, InstructionHandle> map) {
- while (true) {
- InstructionHandle ret = map.get(handle);
- if (ret == null) {
- handle = handle.getNext();
- } else {
- return ret;
- }
- }
- }
-
- // Update to all these comments, ASC 11-01-2005
- // The right thing to do may be to do more with priorities as
- // we create new exception handlers, but that is a relatively
- // complex task. In the meantime, just taking account of the
- // priority here enables a couple of bugs to be fixed to do
- // with using return or break in code that contains a finally
- // block (pr78021,pr79554).
-
- // exception ordering.
- // What we should be doing is dealing with priority inversions way earlier
- // than we are
- // and counting on the tree structure. In which case, the below code is in
- // fact right.
-
- // XXX THIS COMMENT BELOW IS CURRENTLY WRONG.
- // An exception A preceeds an exception B in the exception table iff:
-
- // * A and B were in the original method, and A preceeded B in the original
- // exception table
- // * If A has a higher priority than B, than it preceeds B.
- // * If A and B have the same priority, then the one whose START happens
- // EARLIEST has LEAST priority.
- // in short, the outermost exception has least priority.
- // we implement this with a LinkedList. We could possibly implement this
- // with a java.util.SortedSet,
- // but I don't trust the only implementation, TreeSet, to do the right
- // thing.
-
- /* private */static void insertHandler(ExceptionRange fresh, LinkedList<ExceptionRange> l) {
- // Old implementation, simply: l.add(0,fresh);
- for (ListIterator<ExceptionRange> iter = l.listIterator(); iter.hasNext();) {
- ExceptionRange r = iter.next();
- // int freal = fresh.getRealStart().getPosition();
- // int rreal = r.getRealStart().getPosition();
- if (fresh.getPriority() >= r.getPriority()) {
- iter.previous();
- iter.add(fresh);
- return;
- }
- }
-
- // we have reached the end
- l.add(fresh);
- }
-
- public boolean isPrivate() {
- return Modifier.isPrivate(getAccessFlags());
- }
-
- public boolean isProtected() {
- return Modifier.isProtected(getAccessFlags());
- }
-
- public boolean isDefault() {
- return !(isProtected() || isPrivate() || isPublic());
- }
-
- public boolean isPublic() {
- return Modifier.isPublic(getAccessFlags());
- }
-
- // ----
-
- /**
- * A good body is a body with the following properties:
- *
- * <ul>
- * <li>For each branch instruction S in body, target T of S is in body.
- * <li>For each branch instruction S in body, target T of S has S as a targeter.
- * <li>For each instruction T in body, for each branch instruction S that is a targeter of T, S is in body.
- * <li>For each non-range-handle instruction T in body, for each instruction S that is a targeter of T, S is either a branch
- * instruction, an exception range or a tag
- * <li>For each range-handle instruction T in body, there is exactly one targeter S that is a range.
- * <li>For each range-handle instruction T in body, the range R targeting T is in body.
- * <li>For each instruction T in body, for each exception range R targeting T, R is in body.
- * <li>For each exception range R in body, let T := R.handler. T is in body, and R is one of T's targeters
- * <li>All ranges are properly nested: For all ranges Q and R, if Q.start preceeds R.start, then R.end preceeds Q.end.
- * </ul>
- *
- * Where the shorthand "R is in body" means "R.start is in body, R.end is in body, and any InstructionHandle stored in a field
- * of R (such as an exception handle) is in body".
- */
-
- public void assertGoodBody() {
- if (true) {
- return; // only enable for debugging
- }
- assertGoodBody(getBody(), toString());
- }
-
- public static void assertGoodBody(InstructionList il, String from) {
- if (true) {
- return; // only to be enabled for debugging
- }
-// if (il == null) {
-// return;
-// }
-// Set body = new HashSet();
-// Stack<Range> ranges = new Stack<Range>();
-// for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) {
-// body.add(ih);
-// if (ih.getInstruction() instanceof InstructionBranch) {
-// body.add(ih.getInstruction());
-// }
-// }
-//
-// for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) {
-// assertGoodHandle(ih, body, ranges, from);
-// Iterator<InstructionTargeter> tIter = ih.getTargeters().iterator();
-// while (tIter.hasNext()) {
-// assertGoodTargeter(tIter.next(), ih, body, from);
-// }
-// }
- }
-
-// private static void assertGoodHandle(InstructionHandle ih, Set body, Stack<Range> ranges, String from) {
-// Instruction inst = ih.getInstruction();
-// if ((inst instanceof InstructionBranch) ^ (ih instanceof BranchHandle)) {
-// throw new BCException("bad instruction/handle pair in " + from);
-// }
-// if (Range.isRangeHandle(ih)) {
-// assertGoodRangeHandle(ih, body, ranges, from);
-// } else if (inst instanceof InstructionBranch) {
-// assertGoodBranchInstruction((BranchHandle) ih, (InstructionBranch) inst, body, ranges, from);
-// }
-// }
-
-// private static void assertGoodBranchInstruction(BranchHandle ih, InstructionBranch inst, Set body, Stack<Range> ranges,
-// String from) {
-// if (ih.getTarget() != inst.getTarget()) {
-// throw new BCException("bad branch instruction/handle pair in " + from);
-// }
-// InstructionHandle target = ih.getTarget();
-// assertInBody(target, body, from);
-// assertTargetedBy(target, inst, from);
-// if (inst instanceof InstructionSelect) {
-// InstructionSelect sel = (InstructionSelect) inst;
-// InstructionHandle[] itargets = sel.getTargets();
-// for (int k = itargets.length - 1; k >= 0; k--) {
-// assertInBody(itargets[k], body, from);
-// assertTargetedBy(itargets[k], inst, from);
-// }
-// }
-// }
-
- /** ih is an InstructionHandle or a BranchInstruction */
-// private static void assertInBody(Object ih, Set body, String from) {
-// if (!body.contains(ih)) {
-// throw new BCException("thing not in body in " + from);
-// }
-// }
-
-// private static void assertGoodRangeHandle(InstructionHandle ih, Set body, Stack ranges, String from) {
-// Range r = getRangeAndAssertExactlyOne(ih, from);
-// assertGoodRange(r, body, from);
-// if (r.getStart() == ih) {
-// ranges.push(r);
-// } else if (r.getEnd() == ih) {
-// if (ranges.peek() != r) {
-// throw new BCException("bad range inclusion in " + from);
-// }
-// ranges.pop();
-// }
-// }
-
-// private static void assertGoodRange(Range r, Set body, String from) {
-// assertInBody(r.getStart(), body, from);
-// assertRangeHandle(r.getStart(), from);
-// assertTargetedBy(r.getStart(), r, from);
-//
-// assertInBody(r.getEnd(), body, from);
-// assertRangeHandle(r.getEnd(), from);
-// assertTargetedBy(r.getEnd(), r, from);
-//
-// if (r instanceof ExceptionRange) {
-// ExceptionRange er = (ExceptionRange) r;
-// assertInBody(er.getHandler(), body, from);
-// assertTargetedBy(er.getHandler(), r, from);
-// }
-// }
-
-// private static void assertRangeHandle(InstructionHandle ih, String from) {
-// if (!Range.isRangeHandle(ih)) {
-// throw new BCException("bad range handle " + ih + " in " + from);
-// }
-// }
-
- private static void assertTargetedBy(InstructionHandle target, InstructionTargeter targeter, String from) {
- Iterator tIter = target.getTargeters().iterator();
- while (tIter.hasNext()) {
- if (((InstructionTargeter) tIter.next()) == targeter) {
- return;
- }
- }
- throw new RuntimeException("bad targeting relationship in " + from);
- }
-
- private static void assertTargets(InstructionTargeter targeter, InstructionHandle target, String from) {
- if (targeter instanceof Range) {
- Range r = (Range) targeter;
- if (r.getStart() == target || r.getEnd() == target) {
- return;
- }
- if (r instanceof ExceptionRange) {
- if (((ExceptionRange) r).getHandler() == target) {
- return;
- }
- }
- } else if (targeter instanceof InstructionBranch) {
- InstructionBranch bi = (InstructionBranch) targeter;
- if (bi.getTarget() == target) {
- return;
- }
- if (targeter instanceof InstructionSelect) {
- InstructionSelect sel = (InstructionSelect) targeter;
- InstructionHandle[] itargets = sel.getTargets();
- for (int k = itargets.length - 1; k >= 0; k--) {
- if (itargets[k] == target) {
- return;
- }
- }
- }
- } else if (targeter instanceof Tag) {
- return;
- }
- throw new BCException(targeter + " doesn't target " + target + " in " + from);
- }
-
- private static Range getRangeAndAssertExactlyOne(InstructionHandle ih, String from) {
- Range ret = null;
- Iterator<InstructionTargeter> tIter = ih.getTargeters().iterator();
- if (!tIter.hasNext()) {
- throw new BCException("range handle with no range in " + from);
- }
- while (tIter.hasNext()) {
- InstructionTargeter ts = tIter.next();
- if (ts instanceof Range) {
- if (ret != null) {
- throw new BCException("range handle with multiple ranges in " + from);
- }
- ret = (Range) ts;
- }
- }
- if (ret == null) {
- throw new BCException("range handle with no range in " + from);
- }
- return ret;
- }
-
-// private static void assertGoodTargeter(InstructionTargeter t, InstructionHandle ih, Set body, String from) {
-// assertTargets(t, ih, from);
-// if (t instanceof Range) {
-// assertGoodRange((Range) t, body, from);
-// } else if (t instanceof InstructionBranch) {
-// assertInBody(t, body, from);
-// }
-// }
-
- // ----
-
- boolean isAdviceMethod() {
- if (memberView == null) {
- return false;
- }
- return memberView.getAssociatedShadowMunger() != null;
- }
-
- boolean isAjSynthetic() {
- if (memberView == null) {
- return true;
- }
- return memberView.isAjSynthetic();
- }
-
- boolean isSynthetic() {
- if (memberView == null) {
- return false;
- }
- return memberView.isSynthetic();
- }
-
- public ISourceLocation getSourceLocation() {
- if (memberView != null) {
- return memberView.getSourceLocation();
- }
- return null;
- }
-
- public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature() {
- // if (memberView == null) return null;
- if (effectiveSignature != null) {
- return effectiveSignature;
- }
- return memberView.getEffectiveSignature();
- }
-
- public void setEffectiveSignature(ResolvedMember member, Shadow.Kind kind, boolean shouldWeave) {
- this.effectiveSignature = new AjAttribute.EffectiveSignatureAttribute(member, kind, shouldWeave);
- }
-
- public String getSignature() {
- if (memberView != null) {
- return memberView.getSignature();
- }
- return MemberImpl.typesToSignature(BcelWorld.fromBcel(getReturnType()), BcelWorld.fromBcel(getArgumentTypes()), false);
- }
-
- public String getParameterSignature() {
- if (memberView != null) {
- return memberView.getParameterSignature();
- }
- return MemberImpl.typesToSignature(BcelWorld.fromBcel(getArgumentTypes()));
- }
-
- public BcelMethod getMemberView() {
- return memberView;
- }
-
- public void forcePublic() {
- markAsChanged();
- modifiers = Utility.makePublic(modifiers);
- }
-
- public boolean getCanInline() {
- return canInline;
- }
-
- public void setCanInline(boolean canInline) {
- this.canInline = canInline;
- }
-
- public void addAttribute(Attribute attribute) {
- attributes.add(attribute);
- }
-
- public String toTraceString() {
- return toShortString();
- }
-
- public ConstantPool getConstantPool() {
- return enclosingClass.getConstantPool();
- }
-
- public static boolean isConstructor(LazyMethodGen aMethod) {
- return aMethod.getName().equals("<init>");
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/Range.java b/weaver/src/org/aspectj/weaver/bcel/Range.java
deleted file mode 100644
index fa162c526..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/Range.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/* *******************************************************************
- * 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.util.Iterator;
-
-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.InstructionTargeter;
-import org.aspectj.weaver.BCException;
-
-abstract class Range implements InstructionTargeter {
-
- protected InstructionList body;
- protected InstructionHandle start;
- protected InstructionHandle end;
-
- // ---- initialization
-
- protected Range(InstructionList il) {
- this.body = il;
- }
-
- // ----
-
- final InstructionList getBody() {
- return body;
- }
-
- final InstructionHandle getStart() {
- return start;
- }
-
- final InstructionHandle getEnd() {
- return end;
- }
-
- // ----
-
- boolean isEmpty() {
- InstructionHandle ih = start;
- // System.err.println(" looking for " + end);
- while (ih != end) {
- // System.err.println(" ih " + ih);
- if (!Range.isRangeHandle(ih)) {
- return false;
- }
- ih = ih.getNext();
- }
- return true;
- }
-
- static InstructionHandle getRealStart(InstructionHandle ih) {
- while (Range.isRangeHandle(ih)) {
- ih = ih.getNext();
- }
- return ih;
- }
-
- InstructionHandle getRealStart() {
- return getRealStart(start);
- }
-
- static InstructionHandle getRealEnd(InstructionHandle ih) {
- while (Range.isRangeHandle(ih)) {
- ih = ih.getPrev();
- }
- return ih;
- }
-
- InstructionHandle getRealEnd() {
- return getRealEnd(end);
- }
-
- InstructionHandle getRealNext() {
- return getRealStart(end);
- }
-
- // ----
-
- InstructionHandle insert(Instruction i, Where where) {
- InstructionList il = new InstructionList();
- InstructionHandle ret = il.insert(i);
- insert(il, where);
- return ret;
- }
-
- void insert(InstructionList freshIl, Where where) {
- InstructionHandle h;
- if (where == InsideBefore || where == OutsideBefore) {
- h = getStart();
- } else {
- h = getEnd();
- }
- if (where == InsideBefore || where == OutsideAfter) {
- body.append(h, freshIl);
- } else {
- InstructionHandle newStart = body.insert(h, freshIl);
- if (where == OutsideBefore) {
- // XXX this is slow. There's a better design than this. We should
- // never have to retarget branches apart from the creation of ranges.
- // basically, we should never weave OutsideBefore.
- BcelShadow.retargetAllBranches(h, newStart);
- }
- }
-
- }
-
- InstructionHandle append(Instruction i) {
- return insert(i, InsideAfter);
- }
-
- void append(InstructionList i) {
- insert(i, InsideAfter);
- }
-
- private static void setLineNumberFromNext(InstructionHandle ih) {
- int lineNumber = Utility.getSourceLine(ih.getNext());
- if (lineNumber != -1) {
- Utility.setSourceLine(ih, lineNumber);
- }
- }
-
- static InstructionHandle genStart(InstructionList body) {
- InstructionHandle ih = body.insert(Range.RANGEINSTRUCTION);
- setLineNumberFromNext(ih);
- return ih;
- }
-
- static InstructionHandle genEnd(InstructionList body) {
- return body.append(Range.RANGEINSTRUCTION);
- }
-
- static InstructionHandle genStart(InstructionList body, InstructionHandle ih) {
- if (ih == null) {
- return genStart(body);
- }
- InstructionHandle freshIh = body.insert(ih, Range.RANGEINSTRUCTION);
- setLineNumberFromNext(freshIh);
- return freshIh;
- }
-
- static InstructionHandle genEnd(InstructionList body, InstructionHandle ih) {
- if (ih == null) {
- return genEnd(body);
- }
- return body.append(ih, Range.RANGEINSTRUCTION);
- }
-
- // -----
-
- public boolean containsTarget(InstructionHandle ih) {
- return false;
- }
-
- public final void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
- throw new RuntimeException("Ranges must be updated with an enclosing instructionList");
- }
-
- protected void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih, InstructionList new_il) {
- old_ih.removeTargeter(this);
- if (new_ih != null) {
- new_ih.addTargeter(this);
- }
- body = new_il;
-
- if (old_ih == start) {
- start = new_ih;
- }
- if (old_ih == end) {
- end = new_ih;
- }
- }
-
- public static final boolean isRangeHandle(InstructionHandle ih) {
- if (ih == null) {
- return false;
- }
- return ih.getInstruction() == Range.RANGEINSTRUCTION;
- }
-
- protected static final Range getRange(InstructionHandle ih) {
- // assert isRangeHandle(ih)
- Range ret = null;
- Iterator<InstructionTargeter> tIter = ih.getTargeters().iterator();
- while (tIter.hasNext()) {
- InstructionTargeter targeter = tIter.next();
- if (targeter instanceof Range) {
- Range r = (Range) targeter;
- if (r.getStart() != ih && r.getEnd() != ih) {
- continue;
- }
- if (ret != null) {
- throw new BCException("multiple ranges on same range handle: " + ret + ", " + targeter);
- }
- ret = r;
- }
- }
- if (ret == null) {
- throw new BCException("shouldn't happen");
- }
- return ret;
- }
-
- // ----
-
- static final Where InsideBefore = new Where("insideBefore");
- static final Where InsideAfter = new Where("insideAfter");
- static final Where OutsideBefore = new Where("outsideBefore");
- static final Where OutsideAfter = new Where("outsideAfter");
-
- // ---- constants
-
- // note that this is STUPIDLY copied by Instruction.copy(), so don't do that.
-
- public static final Instruction RANGEINSTRUCTION = InstructionConstants.IMPDEP1;
-
- // ----
-
- static class Where {
- private String name;
-
- public Where(String name) {
- this.name = name;
- }
-
- public String toString() {
- return name;
- }
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/ShadowRange.java b/weaver/src/org/aspectj/weaver/bcel/ShadowRange.java
deleted file mode 100644
index 47c8400c5..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/ShadowRange.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/* *******************************************************************
- * 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.util.Iterator;
-
-import org.aspectj.apache.bcel.generic.Instruction;
-import org.aspectj.apache.bcel.generic.InstructionBranch;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-import org.aspectj.apache.bcel.generic.InstructionHandle;
-import org.aspectj.apache.bcel.generic.InstructionLV;
-import org.aspectj.apache.bcel.generic.InstructionList;
-import org.aspectj.apache.bcel.generic.InstructionSelect;
-import org.aspectj.apache.bcel.generic.InstructionTargeter;
-import org.aspectj.apache.bcel.generic.LocalVariableTag;
-import org.aspectj.apache.bcel.generic.RET;
-import org.aspectj.apache.bcel.generic.TargetLostException;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.IntMap;
-import org.aspectj.weaver.Shadow;
-
-final class ShadowRange extends Range {
-
- private BcelShadow shadow;
-
- // ---- initialization
-
- /**
- * After this constructor is called, this range is not well situated unless both {@link #associateWithTargets} and
- * {@link #associateWithShadow} are called.
- */
- public ShadowRange(InstructionList body) {
- super(body);
- }
-
- protected void associateWithTargets(InstructionHandle start, InstructionHandle end) {
- // assert body.contains(start) && body.contains(end);
- this.start = start;
- this.end = end;
- start.addTargeter(this);
- end.addTargeter(this);
- }
-
- public void associateWithShadow(BcelShadow shadow) {
- this.shadow = shadow;
- shadow.setRange(this);
- }
-
- // ----
-
- public Shadow.Kind getKind() {
- return shadow.getKind();
- }
-
- @Override
- public String toString() {
- return shadow.toString();
- }
-
- void extractInstructionsInto(LazyMethodGen freshMethod, IntMap remap, boolean addReturn) {
- LazyMethodGen.assertGoodBody(getBody(), toString());
- freshMethod.assertGoodBody();
- InstructionList freshBody = freshMethod.getBody();
-
- for (InstructionHandle oldIh = start.getNext(); oldIh != end; oldIh = oldIh.getNext()) {
- // first we copy the instruction itself.
- Instruction oldI = oldIh.getInstruction();
- Instruction freshI = (oldI == RANGEINSTRUCTION) ? oldI : Utility.copyInstruction(oldI);
-
- // Now we add it to the new instruction list.
- InstructionHandle freshIh;
- if (freshI instanceof InstructionBranch) {
- // If it's a targeting instruction,
- // update the target(s) to point to the new copy instead of the old copy.
- InstructionBranch oldBranch = (InstructionBranch) oldI;
- InstructionBranch freshBranch = (InstructionBranch) freshI;
- InstructionHandle oldTarget = oldBranch.getTarget();
- oldTarget.removeTargeter(oldBranch);
- oldTarget.addTargeter(freshBranch);
- if (freshBranch instanceof InstructionSelect) {
- InstructionSelect oldSelect = (InstructionSelect) oldI;
- InstructionSelect freshSelect = (InstructionSelect) freshI;
- InstructionHandle[] oldTargets = freshSelect.getTargets();
- for (int k = oldTargets.length - 1; k >= 0; k--) {
- oldTargets[k].removeTargeter(oldSelect);
- oldTargets[k].addTargeter(freshSelect);
- }
- }
- freshIh = freshBody.append(freshBranch);
- } else {
- freshIh = freshBody.append(freshI);
- }
-
- // if source comes before target:
- // source <--> target
- // --> [process: target.removeTargeter(source); target.addTargeter(sourcecopy)]
- // source ---------\
- // v
- // sourcecopy <--> target
- // --> [ process: sourcecopy.updateTarget(target, targetcopy) ]
- // source ----> target
- // sourcecopy <--> targetcopy
-
- // if target comes before source
-
- // target <--> source
- // --> [process: source.updateTarget(target, targetcopy) ]
- // target
- // targetcopy <--> source
- // --> [process: targetcopy.removeTargeter(source); targetcopy.addTargeter(sourcecopy)]
- // target source
- // v
- // targetcopy <--> sourcecopy
-
- // now deal with the old instruction's targeters. Update them all to point to us
- // instead of the old instruction. We use updateTarget to do this. One goal is
- // to make sure we remove all targeters from the old guy, so we can successfully
- // delete it.
- for (InstructionTargeter source : oldIh.getTargetersCopy()) {
- if (source instanceof LocalVariableTag) {
- Shadow.Kind kind = getKind();
- if (kind == Shadow.AdviceExecution || kind == Shadow.ConstructorExecution || kind == Shadow.MethodExecution
- || kind == Shadow.PreInitialization || kind == Shadow.Initialization
- || kind == Shadow.StaticInitialization) {
- LocalVariableTag sourceLocalVariableTag = (LocalVariableTag) source;
- if (sourceLocalVariableTag.getSlot() == 0) {
- // might be 'this' so should be renamed if being dumped in a static method 277616
- if (sourceLocalVariableTag.getName().equals("this")) {
- sourceLocalVariableTag.setName("ajc$this");
- }
- }
- // if we're extracting a whole block we can do this...
- source.updateTarget(oldIh, freshIh);
- } else {
- // XXX destroying local variable info
- // but only for a call or get join point, so no big deal
- source.updateTarget(oldIh, null);
- }
- } else if (source instanceof Range) {
- // exceptions and shadows are just moved
- ((Range) source).updateTarget(oldIh, freshIh, freshBody);
- } else {
- // line numbers can be shared,
- // branches will be copied along with us.
- source.updateTarget(oldIh, freshIh);
- }
- }
- // we're now done with the old instruction entirely, and will ignore them through
- // the rest of this loop. The only time we'll see them again is a second pass to
- // delete them.
-
- // now deal with local variable instructions. If this points to a remapped
- // frame location, update the instruction's index. If this doesn't,
- // do compaction/expansion: allocate a new local variable, and modify the remap
- // to handle it. XXX We're doing the safe thing and allocating ALL these local variables
- // as double-wides, in case the location is found to hold a double-wide later.
- if (freshI.isLocalVariableInstruction() || freshI instanceof RET) {
- // IndexedInstruction indexedI = (IndexedInstruction) freshI;
- int oldIndex = freshI.getIndex();
- int freshIndex;
- if (!remap.hasKey(oldIndex)) {
- freshIndex = freshMethod.allocateLocal(2);
- remap.put(oldIndex, freshIndex);
- } else {
- freshIndex = remap.get(oldIndex);
- }
- if (freshI instanceof RET) {
- freshI.setIndex(freshIndex);
- } else {
- freshI = ((InstructionLV) freshI).setIndexAndCopyIfNecessary(freshIndex);
- freshIh.setInstruction(freshI);
- }
- }
- // System.err.println("JUST COPIED: " +
- // oldIh.getInstruction().toString(freshMethod.getEnclosingClass().getConstantPoolGen().getConstantPool())
- // + " INTO " +
- // freshIh.getInstruction().toString(freshMethod.getEnclosingClass().getConstantPoolGen().getConstantPool()));
- }
-
- // now go through again and update variable slots that have been altered as a result
- // of remapping...
- for (InstructionHandle newIh = freshBody.getStart(); newIh != freshBody.getEnd(); newIh = newIh.getNext()) {
- Iterator<InstructionTargeter> tIter = newIh.getTargeters().iterator();
- while (tIter.hasNext()) {
- InstructionTargeter source = tIter.next();
- if (source instanceof LocalVariableTag) {
- LocalVariableTag lvt = (LocalVariableTag) source;
- if (!lvt.isRemapped() && remap.hasKey(lvt.getSlot())) {
- lvt.updateSlot(remap.get(lvt.getSlot()));
- }
- }
- }
- }
-
- // we've now copied out all the instructions.
- // now delete the instructions... we've already taken care of the damn
- // targets, but since TargetLostException is checked, we have to do this stuff.
- try {
- for (InstructionHandle oldIh = start.getNext(); oldIh != end;) {
- InstructionHandle next = oldIh.getNext();
- body.delete(oldIh);
- oldIh = next;
- }
- } catch (TargetLostException e) {
- throw new BCException("shouldn't have gotten a target lost");
- }
-
- // now add the return, if one is warranted.
- InstructionHandle ret = null;
- if (addReturn) {
- // we really should pull this out somewhere...
- ret = freshBody.append(InstructionFactory.createReturn(freshMethod.getReturnType()));
- }
- // and remap all the old targeters of the end handle of the range to the return.
- for (InstructionTargeter t : end.getTargetersCopy()) {
- if (t == this) {
- continue;
- }
- if (!addReturn) {
- throw new BCException("range has target, but we aren't adding a return");
- } else {
- t.updateTarget(end, ret);
- }
- }
-
- LazyMethodGen.assertGoodBody(getBody(), toString());
- freshMethod.assertGoodBody();
- }
-
- public BcelShadow getShadow() {
- return shadow;
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/TypeAnnotationAccessVar.java b/weaver/src/org/aspectj/weaver/bcel/TypeAnnotationAccessVar.java
deleted file mode 100644
index e23174389..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/TypeAnnotationAccessVar.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/* *******************************************************************
- * 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.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.ResolvedType;
-import org.aspectj.weaver.UnresolvedType;
-
-/**
- * Used for @this() @target() @args() - represents accessing an annotated 'thing'. Main use is to create the instructions that
- * retrieve the annotation from the 'thing' - see createLoadInstructions()
- */
-public class TypeAnnotationAccessVar extends BcelVar {
-
- private BcelVar target;
-
- public TypeAnnotationAccessVar(ResolvedType type, BcelVar theAnnotatedTargetIsStoredHere) {
- super(type, 0);
- target = theAnnotatedTargetIsStoredHere;
- }
-
- public String toString() {
- return "TypeAnnotationAccessVar(" + 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));
- }
-
- public InstructionList createLoadInstructions(ResolvedType toType, InstructionFactory fact) {
- InstructionList il = new InstructionList();
- Type jlClass = BcelWorld.makeBcelType(UnresolvedType.JL_CLASS);
- Type jlaAnnotation = BcelWorld.makeBcelType(UnresolvedType.ANNOTATION);
- 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.getName())));
- il.append(fact.createInvoke("java/lang/Class", "getAnnotation", jlaAnnotation, new Type[] { jlClass },
- Constants.INVOKEVIRTUAL));
- il.append(Utility.createConversion(fact, jlaAnnotation, BcelWorld.makeBcelType(toType)));
- return il;
-
- }
-
- 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));
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/TypeDelegateResolver.java b/weaver/src/org/aspectj/weaver/bcel/TypeDelegateResolver.java
deleted file mode 100644
index 2a29c927a..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/TypeDelegateResolver.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2010 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, SpringSource
- * ******************************************************************/
-package org.aspectj.weaver.bcel;
-
-import org.aspectj.weaver.ReferenceType;
-import org.aspectj.weaver.ReferenceTypeDelegate;
-
-/**
- * A type delegate resolver is able to create type delegates for a named reference type. A type delegate will implement
- * ReferenceTypeDelegate. There are three kind of delegate already in existence: those created for eclipse structures, those
- * created for bytecode structures, and those created based on reflection.
- *
- * @author Andy Clement
- */
-public interface TypeDelegateResolver {
-
- ReferenceTypeDelegate getDelegate(ReferenceType referenceType);
-
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/UnwovenClassFile.java b/weaver/src/org/aspectj/weaver/bcel/UnwovenClassFile.java
deleted file mode 100644
index 7076316f7..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/UnwovenClassFile.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/* *******************************************************************
- * 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.BufferedOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-
-import org.aspectj.apache.bcel.classfile.JavaClass;
-import org.aspectj.util.FileUtil;
-import org.aspectj.weaver.IUnwovenClassFile;
-
-public class UnwovenClassFile implements IUnwovenClassFile {
- protected String filename;
- protected char[] charfilename;
- protected byte[] bytes;
- // protected JavaClass javaClass = null;
- // protected byte[] writtenBytes = null;
- protected List<ChildClass> writtenChildClasses = Collections.emptyList();
- protected String className = null;
- protected boolean isModule = false;
-
- public UnwovenClassFile(String filename, byte[] bytes) {
- this.filename = filename;
- this.isModule = filename.toLowerCase().endsWith("module-info.java");
- this.bytes = bytes;
- }
-
- /** Use if the classname is known, saves a bytecode parse */
- public UnwovenClassFile(String filename, String classname, byte[] bytes) {
- this.filename = filename;
- this.isModule = filename.toLowerCase().endsWith("module-info.class");
- this.className = classname;
- this.bytes = bytes;
- }
-
- public boolean shouldBeWoven() {
- // Skip module-info files for now, they aren't really types
- return !isModule;
- }
-
- public String getFilename() {
- return filename;
- }
-
- public String makeInnerFileName(String innerName) {
- String prefix = filename.substring(0, filename.length() - 6); // strip the .class
- return prefix + "$" + innerName + ".class";
- }
-
- public byte[] getBytes() {
- // if (bytes == null) bytes = javaClass.getBytes();
- return bytes;
- }
-
- public JavaClass getJavaClass() {
- // XXX need to know when to make a new class and when not to
- // XXX this is an important optimization
- if (getBytes() == null) {
- System.out.println("no bytes for: " + getFilename());
- // Thread.currentThread().dumpStack();
- Thread.dumpStack();
- }
- return Utility.makeJavaClass(filename, getBytes());
- // if (javaClass == null) javaClass = Utility.makeJavaClass(filename, getBytes());
- // return javaClass;
- }
-
- public void writeUnchangedBytes() throws IOException {
- writeWovenBytes(getBytes(), Collections.<ChildClass>emptyList());
- }
-
- public void writeWovenBytes(byte[] bytes, List<ChildClass> childClasses) throws IOException {
- writeChildClasses(childClasses);
-
- // System.err.println("should write: " + getClassName());
-
- // System.err.println("about to write: " + this + ", " + writtenBytes + ", ");
- // + writtenBytes != null + " && " + unchanged(bytes, writtenBytes) );
-
- // if (writtenBytes != null && unchanged(bytes, writtenBytes)) return;
-
- // System.err.println(" actually wrote it");
-
- BufferedOutputStream os = FileUtil.makeOutputStream(new File(filename));
- os.write(bytes);
- os.close();
-
- // writtenBytes = bytes;
- }
-
- private void writeChildClasses(List<ChildClass> childClasses) throws IOException {
- // ??? we only really need to delete writtenChildClasses whose
- // ??? names aren't in childClasses; however, it's unclear
- // ??? how much that will affect performance
- deleteAllChildClasses();
-
- childClasses.removeAll(writtenChildClasses); // XXX is this right
-
- for (ChildClass childClass : childClasses) {
- writeChildClassFile(childClass.name, childClass.bytes);
- }
-
- writtenChildClasses = childClasses;
-
- }
-
- private void writeChildClassFile(String innerName, byte[] bytes) throws IOException {
- BufferedOutputStream os = FileUtil.makeOutputStream(new File(makeInnerFileName(innerName)));
- os.write(bytes);
- os.close();
- }
-
- protected void deleteAllChildClasses() {
- for (ChildClass childClass : writtenChildClasses) {
- deleteChildClassFile(childClass.name);
- }
- }
-
- protected void deleteChildClassFile(String innerName) {
- File childClassFile = new File(makeInnerFileName(innerName));
- childClassFile.delete();
- }
-
- /* private */static boolean unchanged(byte[] b1, byte[] b2) {
- int len = b1.length;
- if (b2.length != len)
- return false;
- for (int i = 0; i < len; i++) {
- if (b1[i] != b2[i])
- return false;
- }
- return true;
- }
-
- public char[] getClassNameAsChars() {
- if (charfilename == null) {
- charfilename = getClassName().replace('.', '/').toCharArray();
- }
- return charfilename;
- }
-
- public String getClassName() {
- if (className == null)
- className = getJavaClass().getClassName(); // OPTIMIZE quicker way to determine name??? surely?
- return className;
- }
-
- @Override
- public String toString() {
- return "UnwovenClassFile(" + filename + ", " + getClassName() + ")";
- }
-
- // 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;
-
- ChildClass(String name, byte[] bytes) {
- this.name = name;
- this.bytes = bytes;
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof ChildClass))
- return false;
- ChildClass o = (ChildClass) other;
- return o.name.equals(name) && unchanged(o.bytes, bytes);
- }
-
- @Override
- public int hashCode() {
- return name.hashCode();
- }
-
- @Override
- public String toString() {
- return "(ChildClass " + name + ")";
- }
- }
-
- public void setClassNameAsChars(char[] classNameAsChars) {
- this.charfilename = classNameAsChars;
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/UnwovenClassFileWithThirdPartyManagedBytecode.java b/weaver/src/org/aspectj/weaver/bcel/UnwovenClassFileWithThirdPartyManagedBytecode.java
deleted file mode 100644
index 18edc8413..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/UnwovenClassFileWithThirdPartyManagedBytecode.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * 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:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.aspectj.weaver.bcel;
-
-/**
- * @author colyer This subclass of UnwovenClassFile allows a third-party to manage the actual bytes that comprise the class. This
- * means the third party can return a reference to an existing array, or create the bytes on demand, or apply any other
- * strategy that makes sense. By refering to bytes held elsewhere, the goal is to reduce the overall memory consumption by
- * not holding a copy.
- */
-public class UnwovenClassFileWithThirdPartyManagedBytecode extends UnwovenClassFile {
-
- IByteCodeProvider provider;
-
- public interface IByteCodeProvider {
- byte[] getBytes();
- }
-
- // OPTIMIZE make classname an input char[]
- public UnwovenClassFileWithThirdPartyManagedBytecode(String filename, String classname, IByteCodeProvider provider) {
- super(filename, classname, null);
- this.provider = provider;
- }
-
- public byte[] getBytes() {
- return provider.getBytes();
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/Utility.java b/weaver/src/org/aspectj/weaver/bcel/Utility.java
deleted file mode 100644
index 4acf032fc..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/Utility.java
+++ /dev/null
@@ -1,719 +0,0 @@
-/* *******************************************************************
- * 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.ByteArrayInputStream;
-import java.io.IOException;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Hashtable;
-import java.util.Iterator;
-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.Unknown;
-import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValue;
-import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
-import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
-import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValue;
-import org.aspectj.apache.bcel.generic.ArrayType;
-import org.aspectj.apache.bcel.generic.BasicType;
-import org.aspectj.apache.bcel.generic.Instruction;
-import org.aspectj.apache.bcel.generic.InstructionByte;
-import org.aspectj.apache.bcel.generic.InstructionCP;
-import org.aspectj.apache.bcel.generic.InstructionConstants;
-import org.aspectj.apache.bcel.generic.InstructionFactory;
-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.InstructionShort;
-import org.aspectj.apache.bcel.generic.InstructionTargeter;
-import org.aspectj.apache.bcel.generic.LineNumberTag;
-import org.aspectj.apache.bcel.generic.ObjectType;
-import org.aspectj.apache.bcel.generic.ReferenceType;
-import org.aspectj.apache.bcel.generic.SwitchBuilder;
-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.AjAttribute.WeaverVersionInfo;
-import org.aspectj.weaver.AnnotationAJ;
-import org.aspectj.weaver.BCException;
-import org.aspectj.weaver.ConstantPoolReader;
-import org.aspectj.weaver.ISourceContext;
-import org.aspectj.weaver.Lint;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.Utils;
-import org.aspectj.weaver.World;
-
-public class Utility {
-
- private final static char PACKAGE_INITIAL_CHAR = AjAttribute.AttributePrefix.charAt(0);
-
- public static List<AjAttribute> readAjAttributes(String classname, Attribute[] as, ISourceContext context, World w,
- AjAttribute.WeaverVersionInfo version, ConstantPoolReader dataDecompressor) {
- List<AjAttribute> attributes = new ArrayList<AjAttribute>();
-
- // first pass, look for version
- List<Unknown> forSecondPass = new ArrayList<Unknown>();
- for (int i = as.length - 1; i >= 0; i--) {
- Attribute a = as[i];
- if (a instanceof Unknown) {
- Unknown u = (Unknown) a;
- String name = u.getName();
- if (name.charAt(0) == PACKAGE_INITIAL_CHAR) { // 'o'rg.aspectj
- if (name.startsWith(AjAttribute.AttributePrefix)) {
- if (name.endsWith(WeaverVersionInfo.AttributeName)) {
- version = (AjAttribute.WeaverVersionInfo) AjAttribute.read(version, name, u.getBytes(), context, w,
- dataDecompressor);
- 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() + ". Please update your AspectJ.");
- }
- }
- forSecondPass.add(u);
- }
- }
- }
- }
-
- // FIXASC why going backwards? is it important
- for (int i = forSecondPass.size() - 1; i >= 0; i--) {
- Unknown a = forSecondPass.get(i);
- String name = a.getName();
- AjAttribute attr = AjAttribute.read(version, name, a.getBytes(), context, w, dataDecompressor);
- if (attr != null) {
- attributes.add(attr);
- }
- }
- return attributes;
- }
-
- /*
- * Ensure we report a nice source location - particular in the case where the source info is missing (binary weave).
- */
- public static String beautifyLocation(ISourceLocation isl) {
- StringBuffer nice = new StringBuffer();
- if (isl == null || isl.getSourceFile() == null || isl.getSourceFile().getName().indexOf("no debug info available") != -1) {
- nice.append("no debug info available");
- } else {
- // can't use File.getName() as this fails when a Linux box
- // encounters a path created on Windows and vice-versa
- int takeFrom = isl.getSourceFile().getPath().lastIndexOf('/');
- if (takeFrom == -1) {
- takeFrom = isl.getSourceFile().getPath().lastIndexOf('\\');
- }
- nice.append(isl.getSourceFile().getPath().substring(takeFrom + 1));
- if (isl.getLine() != 0) {
- nice.append(":").append(isl.getLine());
- }
- }
- return nice.toString();
- }
-
- public static Instruction createSuperInvoke(InstructionFactory fact, BcelWorld world, Member signature) {
- short kind;
- if (Modifier.isInterface(signature.getModifiers())) {
- throw new RuntimeException("bad");
- } else if (Modifier.isPrivate(signature.getModifiers()) || signature.getName().equals("<init>")) {
- throw new RuntimeException("unimplemented, possibly bad");
- } else if (Modifier.isStatic(signature.getModifiers())) {
- throw new RuntimeException("bad");
- } else {
- kind = Constants.INVOKESPECIAL;
- }
-
- return fact.createInvoke(signature.getDeclaringType().getName(), signature.getName(),
- BcelWorld.makeBcelType(signature.getReturnType()), BcelWorld.makeBcelTypes(signature.getParameterTypes()), kind);
- }
-
- public static Instruction createInvoke(InstructionFactory fact, BcelWorld world, Member signature) {
- short kind;
- int signatureModifiers = signature.getModifiers();
- if (Modifier.isInterface(signatureModifiers)) {
- kind = Constants.INVOKEINTERFACE;
- } else if (Modifier.isStatic(signatureModifiers)) {
- kind = Constants.INVOKESTATIC;
- } else if (Modifier.isPrivate(signatureModifiers) || signature.getName().equals("<init>")) {
- kind = Constants.INVOKESPECIAL;
- } else {
- kind = Constants.INVOKEVIRTUAL;
- }
-
- UnresolvedType targetType = signature.getDeclaringType();
- if (targetType.isParameterizedType()) {
- targetType = targetType.resolve(world).getGenericType();
- }
- return fact.createInvoke(targetType.getName(), signature.getName(), BcelWorld.makeBcelType(signature.getReturnType()),
- BcelWorld.makeBcelTypes(signature.getParameterTypes()), kind);
- }
-
- public static Instruction createGet(InstructionFactory fact, Member signature) {
- short kind;
- if (Modifier.isStatic(signature.getModifiers())) {
- kind = Constants.GETSTATIC;
- } else {
- kind = Constants.GETFIELD;
- }
-
- return fact.createFieldAccess(signature.getDeclaringType().getName(), signature.getName(),
- BcelWorld.makeBcelType(signature.getReturnType()), kind);
- }
-
- public static Instruction createSet(InstructionFactory fact, Member signature) {
- short kind;
- if (Modifier.isStatic(signature.getModifiers())) {
- kind = Constants.PUTSTATIC;
- } else {
- kind = Constants.PUTFIELD;
- }
-
- return fact.createFieldAccess(signature.getDeclaringType().getName(), signature.getName(),
- BcelWorld.makeBcelType(signature.getReturnType()), kind);
- }
-
- public static Instruction createInstanceof(InstructionFactory fact, ReferenceType t) {
- int cpoolEntry = (t instanceof ArrayType) ? fact.getConstantPool().addArrayClass((ArrayType) t) : fact.getConstantPool()
- .addClass((ObjectType) t);
- return new InstructionCP(Constants.INSTANCEOF, cpoolEntry);
- }
-
- public static Instruction createInvoke(InstructionFactory fact, LazyMethodGen m) {
- short kind;
- if (m.getEnclosingClass().isInterface()) {
- if (m.isStatic()) {
- // For static methods on interfaces
- kind = Constants.INVOKESTATIC;
- } else {
- kind = Constants.INVOKEINTERFACE;
- }
- } else if (m.isStatic()) {
- kind = Constants.INVOKESTATIC;
- } else if (m.isPrivate() || m.getName().equals("<init>")) {
- kind = Constants.INVOKESPECIAL;
- } else {
- kind = Constants.INVOKEVIRTUAL;
- }
-
- return fact.createInvoke(m.getClassName(), m.getName(), m.getReturnType(), m.getArgumentTypes(), kind, m.getEnclosingClass().isInterface());
- }
-
- /**
- * Create an invoke instruction
- *
- * @param fact
- * @param kind INVOKEINTERFACE, INVOKEVIRTUAL..
- * @param member
- * @return
- */
- public static Instruction createInvoke(InstructionFactory fact, short kind, Member member) {
- return fact.createInvoke(member.getDeclaringType().getName(), member.getName(),
- BcelWorld.makeBcelType(member.getReturnType()), BcelWorld.makeBcelTypes(member.getParameterTypes()), kind);
- }
-
- private static String[] argNames = new String[] { "arg0", "arg1", "arg2", "arg3", "arg4" };
-
- // ??? these should perhaps be cached. Remember to profile this to see if
- // it's a problem.
- public static String[] makeArgNames(int n) {
- String[] ret = new String[n];
- for (int i = 0; i < n; i++) {
- if (i < 5) {
- ret[i] = argNames[i];
- } else {
- ret[i] = "arg" + i;
- }
- }
- return ret;
- }
-
- // Lookup table, for converting between pairs of types, it gives
- // us the method name in the Conversions class
- private static Hashtable<String, String> validBoxing = new Hashtable<String, String>();
-
- static {
- validBoxing.put("Ljava/lang/Byte;B", "byteObject");
- validBoxing.put("Ljava/lang/Character;C", "charObject");
- validBoxing.put("Ljava/lang/Double;D", "doubleObject");
- validBoxing.put("Ljava/lang/Float;F", "floatObject");
- validBoxing.put("Ljava/lang/Integer;I", "intObject");
- validBoxing.put("Ljava/lang/Long;J", "longObject");
- validBoxing.put("Ljava/lang/Short;S", "shortObject");
- validBoxing.put("Ljava/lang/Boolean;Z", "booleanObject");
- validBoxing.put("BLjava/lang/Byte;", "byteValue");
- validBoxing.put("CLjava/lang/Character;", "charValue");
- validBoxing.put("DLjava/lang/Double;", "doubleValue");
- validBoxing.put("FLjava/lang/Float;", "floatValue");
- validBoxing.put("ILjava/lang/Integer;", "intValue");
- validBoxing.put("JLjava/lang/Long;", "longValue");
- validBoxing.put("SLjava/lang/Short;", "shortValue");
- validBoxing.put("ZLjava/lang/Boolean;", "booleanValue");
- }
-
- public static void appendConversion(InstructionList il, InstructionFactory fact, ResolvedType fromType, ResolvedType toType) {
- if (!toType.isConvertableFrom(fromType) && !fromType.isConvertableFrom(toType)) {
- throw new BCException("can't convert from " + fromType + " to " + toType);
- }
- // XXX I'm sure this test can be simpler but my brain hurts and this works
- World w = toType.getWorld();
- if (w == null) { // dbg349636
- throw new IllegalStateException("Debug349636: Unexpectedly found world null for type " + toType.getName());
- }
-
- if (!w.isInJava5Mode()) {
- if (toType.needsNoConversionFrom(fromType)) {
- return;
- }
- } else {
- if (toType.needsNoConversionFrom(fromType) && !(toType.isPrimitiveType() ^ fromType.isPrimitiveType())) {
- return;
- }
- }
- if (toType.equals(UnresolvedType.VOID)) {
- // assert fromType.equals(UnresolvedType.OBJECT)
- il.append(InstructionFactory.createPop(fromType.getSize()));
- } else if (fromType.equals(UnresolvedType.VOID)) {
- // assert toType.equals(UnresolvedType.OBJECT)
- il.append(InstructionFactory.createNull(Type.OBJECT));
- return;
- } else if (fromType.equals(UnresolvedType.OBJECT)) {
- Type to = BcelWorld.makeBcelType(toType);
- if (toType.isPrimitiveType()) {
- String name = toType.toString() + "Value";
- il.append(fact.createInvoke("org.aspectj.runtime.internal.Conversions", name, to, new Type[] { Type.OBJECT },
- Constants.INVOKESTATIC));
- } else {
- il.append(fact.createCheckCast((ReferenceType) to));
- }
- } else if (toType.equals(UnresolvedType.OBJECT)) {
- // assert fromType.isPrimitive()
- Type from = BcelWorld.makeBcelType(fromType);
- String name = fromType.toString() + "Object";
- il.append(fact.createInvoke("org.aspectj.runtime.internal.Conversions", name, Type.OBJECT, new Type[] { from },
- Constants.INVOKESTATIC));
- } else if (toType.getWorld().isInJava5Mode() && validBoxing.get(toType.getSignature() + fromType.getSignature()) != null) {
- // XXX could optimize by using any java boxing code that may be just
- // before the call...
- Type from = BcelWorld.makeBcelType(fromType);
- Type to = BcelWorld.makeBcelType(toType);
- String name = validBoxing.get(toType.getSignature() + fromType.getSignature());
- if (toType.isPrimitiveType()) {
- il.append(fact.createInvoke("org.aspectj.runtime.internal.Conversions", name, to, new Type[] { Type.OBJECT },
- Constants.INVOKESTATIC));
- } else {
- il.append(fact.createInvoke("org.aspectj.runtime.internal.Conversions", name, Type.OBJECT, new Type[] { from },
- Constants.INVOKESTATIC));
- il.append(fact.createCheckCast((ReferenceType) to));
- }
- } else if (fromType.isPrimitiveType()) {
- // assert toType.isPrimitive()
- Type from = BcelWorld.makeBcelType(fromType);
- Type to = BcelWorld.makeBcelType(toType);
- try {
- Instruction i = fact.createCast(from, to);
- if (i != null) {
- il.append(i);
- } else {
- il.append(fact.createCast(from, Type.INT));
- il.append(fact.createCast(Type.INT, to));
- }
- } catch (RuntimeException e) {
- il.append(fact.createCast(from, Type.INT));
- il.append(fact.createCast(Type.INT, to));
- }
- } else {
- Type to = BcelWorld.makeBcelType(toType);
- // assert ! fromType.isPrimitive() && ! toType.isPrimitive()
- il.append(fact.createCheckCast((ReferenceType) to));
- }
- }
-
- public static InstructionList createConversion(InstructionFactory factory, Type fromType, Type toType) {
- return createConversion(factory, fromType, toType, false);
- }
-
- public static InstructionList createConversion(InstructionFactory fact, Type fromType, Type toType, boolean allowAutoboxing) {
- // System.out.println("cast to: " + toType);
-
- InstructionList il = new InstructionList();
-
- // PR71273
- if ((fromType.equals(Type.BYTE) || fromType.equals(Type.CHAR) || fromType.equals(Type.SHORT)) && (toType.equals(Type.INT))) {
- return il;
- }
-
- if (fromType.equals(toType)) {
- return il;
- }
- if (toType.equals(Type.VOID)) {
- il.append(InstructionFactory.createPop(fromType.getSize()));
- return il;
- }
-
- if (fromType.equals(Type.VOID)) {
- if (toType instanceof BasicType) {
- throw new BCException("attempting to cast from void to basic type");
- }
- il.append(InstructionFactory.createNull(Type.OBJECT));
- return il;
- }
-
- if (fromType.equals(Type.OBJECT)) {
- if (toType instanceof BasicType) {
- String name = toType.toString() + "Value";
- il.append(fact.createInvoke("org.aspectj.runtime.internal.Conversions", name, toType, new Type[] { Type.OBJECT },
- Constants.INVOKESTATIC));
- return il;
- }
- }
-
- if (toType.equals(Type.OBJECT)) {
- if (fromType instanceof BasicType) {
- String name = fromType.toString() + "Object";
- il.append(fact.createInvoke("org.aspectj.runtime.internal.Conversions", name, Type.OBJECT, new Type[] { fromType },
- Constants.INVOKESTATIC));
- return il;
- } else if (fromType instanceof ReferenceType) {
- return il;
- } else {
- throw new RuntimeException();
- }
- }
-
- if (fromType instanceof ReferenceType && ((ReferenceType) fromType).isAssignmentCompatibleWith(toType)) {
- return il;
- }
-
- if (allowAutoboxing) {
- if (toType instanceof BasicType && fromType instanceof ReferenceType) {
- // unboxing
- String name = toType.toString() + "Value";
- il.append(fact.createInvoke("org.aspectj.runtime.internal.Conversions", name, toType, new Type[] { Type.OBJECT },
- Constants.INVOKESTATIC));
- return il;
- }
-
- if (fromType instanceof BasicType && toType instanceof ReferenceType) {
- // boxing
- String name = fromType.toString() + "Object";
- il.append(fact.createInvoke("org.aspectj.runtime.internal.Conversions", name, Type.OBJECT, new Type[] { fromType },
- Constants.INVOKESTATIC));
- il.append(fact.createCast(Type.OBJECT, toType));
- return il;
- }
- }
-
- il.append(fact.createCast(fromType, toType));
- return il;
- }
-
- public static Instruction createConstant(InstructionFactory fact, int value) {
- Instruction inst;
- switch (value) {
- case -1:
- inst = InstructionConstants.ICONST_M1;
- break;
- case 0:
- inst = InstructionConstants.ICONST_0;
- break;
- case 1:
- inst = InstructionConstants.ICONST_1;
- break;
- case 2:
- inst = InstructionConstants.ICONST_2;
- break;
- case 3:
- inst = InstructionConstants.ICONST_3;
- break;
- case 4:
- inst = InstructionConstants.ICONST_4;
- break;
- case 5:
- inst = InstructionConstants.ICONST_5;
- break;
- default:
- if (value <= Byte.MAX_VALUE && value >= Byte.MIN_VALUE) {
- inst = new InstructionByte(Constants.BIPUSH, (byte) value);
- } else if (value <= Short.MAX_VALUE && value >= Short.MIN_VALUE) {
- inst = new InstructionShort(Constants.SIPUSH, (short) value);
- } else {
- int ii = fact.getClassGen().getConstantPool().addInteger(value);
- inst = new InstructionCP(value <= Constants.MAX_BYTE ? Constants.LDC : Constants.LDC_W, ii);
- }
- break;
- }
- return inst;
- }
-
- /** For testing purposes: bit clunky but does work */
- public static int testingParseCounter = 0;
-
- public static JavaClass makeJavaClass(String filename, byte[] bytes) {
- try {
- testingParseCounter++;
- ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes), filename);
- return parser.parse();
- } catch (IOException e) {
- throw new BCException("malformed class file");
- }
- }
-
- /**
- * 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, InstructionList replacementInstructions,
- LazyMethodGen enclosingMethod) {
- InstructionList il = enclosingMethod.getBody();
- InstructionHandle fresh = il.append(ih, replacementInstructions);
- deleteInstruction(ih, fresh, enclosingMethod);
- }
-
- /**
- * delete an instruction handle and retarget all targeters of the deleted instruction to the next instruction. Obviously, this
- * should not be used to delete a control transfer instruction unless you know what you're doing.
- *
- * @param ih the instruction handle to delete.
- * @param enclosingMethod where to find ih's instruction list.
- */
- public static void deleteInstruction(InstructionHandle ih, LazyMethodGen enclosingMethod) {
- deleteInstruction(ih, ih.getNext(), enclosingMethod);
- }
-
- /**
- * delete an instruction handle and retarget all targeters of the deleted instruction to the provided target.
- *
- * @param ih the instruction handle to delete
- * @param retargetTo the instruction handle to retarget targeters of ih to.
- * @param enclosingMethod where to find ih's instruction list.
- */
- public static void deleteInstruction(InstructionHandle ih, InstructionHandle retargetTo, LazyMethodGen enclosingMethod) {
- InstructionList il = enclosingMethod.getBody();
- for (InstructionTargeter targeter : ih.getTargetersCopy()) {
- targeter.updateTarget(ih, retargetTo);
- }
- ih.removeAllTargeters();
- try {
- il.delete(ih);
- } catch (TargetLostException e) {
- throw new BCException("this really can't happen");
- }
- }
-
- /**
- * Fix for Bugzilla #39479, #40109 patch contributed by Andy Clement
- *
- * Need to manually copy Select instructions - if we rely on the the 'fresh' object created by copy(), the InstructionHandle
- * array 'targets' inside the Select object will not have been deep copied, so modifying targets in fresh will modify the
- * original Select - not what we want ! (It is a bug in BCEL to do with cloning Select objects).
- *
- * <pre>
- * declare error:
- * call(* Instruction.copy()) &amp;&amp; within(org.aspectj.weaver)
- * &amp;&amp; !withincode(* Utility.copyInstruction(Instruction)):
- * &quot;use Utility.copyInstruction to work-around bug in Select.copy()&quot;;
- * </pre>
- */
- public static Instruction copyInstruction(Instruction i) {
- if (i instanceof InstructionSelect) {
- InstructionSelect freshSelect = (InstructionSelect) i;
-
- // Create a new targets array that looks just like the existing one
- InstructionHandle[] targets = new InstructionHandle[freshSelect.getTargets().length];
- for (int ii = 0; ii < targets.length; ii++) {
- targets[ii] = freshSelect.getTargets()[ii];
- }
-
- // Create a new select statement with the new targets array
-
- return new SwitchBuilder(freshSelect.getMatchs(), targets, freshSelect.getTarget()).getInstruction();
- } else {
- return i.copy(); // Use clone for shallow copy...
- }
- }
-
- /** returns -1 if no source line attribute */
- // this naive version overruns the JVM stack size, if only Java understood
- // tail recursion...
- // public static int getSourceLine(InstructionHandle ih) {
- // if (ih == null) return -1;
- //
- // InstructionTargeter[] ts = ih.getTargeters();
- // if (ts != null) {
- // for (int j = ts.length - 1; j >= 0; j--) {
- // InstructionTargeter t = ts[j];
- // if (t instanceof LineNumberTag) {
- // return ((LineNumberTag)t).getLineNumber();
- // }
- // }
- // }
- // return getSourceLine(ih.getNext());
- // }
- public static int getSourceLine(InstructionHandle ih) {// ,boolean
- // goforwards) {
- int lookahead = 0;
- // arbitrary rule that we will never lookahead more than 100
- // instructions for a line #
- while (lookahead++ < 100) {
- if (ih == null) {
- return -1;
- }
- Iterator<InstructionTargeter> tIter = ih.getTargeters().iterator();
- while (tIter.hasNext()) {
- InstructionTargeter t = tIter.next();
- if (t instanceof LineNumberTag) {
- return ((LineNumberTag) t).getLineNumber();
- }
- }
- // if (goforwards) ih=ih.getNext(); else
- ih = ih.getPrev();
- }
- // System.err.println("no line information available for: " + ih);
- return -1;
- }
-
- // public static int getSourceLine(InstructionHandle ih) {
- // return getSourceLine(ih,false);
- // }
-
- // 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 BcelVar[] pushAndReturnArrayOfVars(ResolvedType[] proceedParamTypes, InstructionList il, InstructionFactory fact,
- LazyMethodGen enclosingMethod) {
- int len = proceedParamTypes.length;
- BcelVar[] ret = new BcelVar[len];
-
- for (int i = len - 1; i >= 0; i--) {
- ResolvedType typeX = proceedParamTypes[i];
- Type type = BcelWorld.makeBcelType(typeX);
- int local = enclosingMethod.allocateLocal(type);
-
- il.append(InstructionFactory.createStore(type, local));
- ret[i] = new BcelVar(typeX, local);
- }
- return ret;
- }
-
- public static boolean isConstantPushInstruction(Instruction i) {
- long ii = Constants.instFlags[i.opcode];
- return ((ii & Constants.PUSH_INST) != 0 && (ii & Constants.CONSTANT_INST) != 0);
- }
-
- /**
- * Checks for suppression specified on the member or on the declaring type of that member
- */
- public static boolean isSuppressing(Member member, String lintkey) {
- boolean isSuppressing = Utils.isSuppressing(member.getAnnotations(), lintkey);
- if (isSuppressing) {
- return true;
- }
- UnresolvedType type = member.getDeclaringType();
- if (type instanceof ResolvedType) {
- return Utils.isSuppressing(((ResolvedType) type).getAnnotations(), lintkey);
- }
- return false;
- }
-
- public static List<Lint.Kind> getSuppressedWarnings(AnnotationAJ[] anns, Lint lint) {
- if (anns == null) {
- return Collections.emptyList();
- }
- // Go through the annotation types
- List<Lint.Kind> suppressedWarnings = new ArrayList<Lint.Kind>();
- boolean found = false;
- for (int i = 0; !found && i < anns.length; i++) {
- // Check for the SuppressAjWarnings annotation
- if (UnresolvedType.SUPPRESS_AJ_WARNINGS.getSignature().equals(
- ((BcelAnnotation) anns[i]).getBcelAnnotation().getTypeSignature())) {
- found = true;
- // Two possibilities:
- // 1. there are no values specified (i.e. @SuppressAjWarnings)
- // 2. there are values specified (i.e. @SuppressAjWarnings("A")
- // or @SuppressAjWarnings({"A","B"})
- List<NameValuePair> vals = ((BcelAnnotation) anns[i]).getBcelAnnotation().getValues();
- if (vals == null || vals.isEmpty()) { // (1)
- suppressedWarnings.addAll(lint.allKinds());
- } else { // (2)
- // We know the value is an array value
- ArrayElementValue array = (ArrayElementValue) (vals.get(0)).getValue();
- ElementValue[] values = array.getElementValuesArray();
- for (int j = 0; j < values.length; j++) {
- // We know values in the array are strings
- SimpleElementValue value = (SimpleElementValue) values[j];
- Lint.Kind lintKind = lint.getLintKind(value.getValueString());
- if (lintKind != null) {
- suppressedWarnings.add(lintKind);
- }
- }
- }
- }
- }
- return suppressedWarnings;
- }
-
- // 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 Attribute bcelAttribute(AjAttribute a, ConstantPool pool) {
- int nameIndex = pool.addUtf8(a.getNameString());
- byte[] bytes = a.getBytes(new BcelConstantPoolWriter(pool));
- int length = bytes.length;
-
- return new Unknown(nameIndex, length, bytes, pool);
- }
-} \ No newline at end of file
diff --git a/weaver/src/org/aspectj/weaver/bcel/asm/AsmDetector.java b/weaver/src/org/aspectj/weaver/bcel/asm/AsmDetector.java
deleted file mode 100644
index 5d5bb6990..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/asm/AsmDetector.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/* *******************************************************************
- * 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
- * ******************************************************************/
-package org.aspectj.weaver.bcel.asm;
-
-import java.lang.reflect.Method;
-
-/**
- * Determines if a version of asm is around that will enable us to add stack map attributes to classes that we produce.
- *
- * @author Andy Clement
- */
-public class AsmDetector {
-
- public static boolean isAsmAround;
-
- static {
- try {
- Class<?> reader = Class.forName("aj.org.objectweb.asm.ClassReader");
- Class<?> visitor = Class.forName("aj.org.objectweb.asm.ClassVisitor");
- Method m = reader.getMethod("accept", new Class[] { visitor, Integer.TYPE });
- isAsmAround = m != null;
- } catch (Exception e) {
- isAsmAround = false;
- }
- // System.out.println(isAsmAround?"ASM detected":"No ASM found");
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/bcel/asm/StackMapAdder.java b/weaver/src/org/aspectj/weaver/bcel/asm/StackMapAdder.java
deleted file mode 100644
index dd3965b61..000000000
--- a/weaver/src/org/aspectj/weaver/bcel/asm/StackMapAdder.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2008, 2018 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
- * ******************************************************************/
-package org.aspectj.weaver.bcel.asm;
-
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.World;
-
-import aj.org.objectweb.asm.ClassReader;
-import aj.org.objectweb.asm.ClassVisitor;
-import aj.org.objectweb.asm.ClassWriter;
-import aj.org.objectweb.asm.MethodVisitor;
-import aj.org.objectweb.asm.Opcodes;
-
-/**
- * Uses asm to add the stack map attribute to methods in a class. The class is passed in as pure byte data and then a reader/writer
- * process it. The writer is wired into the world so that types can be resolved and getCommonSuperClass() can be implemented without
- * class loading using the context class loader.
- *
- * It is important that the constant pool is preserved here and asm does not try to remove unused entries. That is because some
- * entries are refered to from classfile attributes. Asm cannot see into these attributes so does not realise the constant pool
- * entries are in use. In order to ensure the copying of cp occurs, we use the variant super constructor call in AspectJConnectClassWriter
- * that passes in the classreader. However, ordinarily that change causes a further optimization: that if a classreader sees
- * a methodvisitor that has been created by a ClassWriter then it just copies the data across without changing it (and so it
- * fails to attach the stackmapattribute). In order to avoid this further optimization we use our own minimal MethodVisitor.
- *
- * @author Andy Clement
- */
-public class StackMapAdder {
-
- public static byte[] addStackMaps(World world, byte[] data) {
- try {
- ClassReader cr = new ClassReader(data);
- ClassWriter cw = new AspectJConnectClassWriter(cr, world);
- ClassVisitor cv = new AspectJClassVisitor(cw);
- cr.accept(cv, 0);
- return cw.toByteArray();
- } catch (Throwable t) {
- System.err.println("AspectJ Internal Error: unable to add stackmap attributes. " + t.getMessage());
- AsmDetector.isAsmAround = false;
- return data;
- }
- }
-
- private static class AspectJClassVisitor extends ClassVisitor {
-
- public AspectJClassVisitor(ClassVisitor classwriter) {
- super(Opcodes.ASM7, classwriter);
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
- MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
- return new AJMethodVisitor(mv);
- }
-
- // Minimal pass through MethodVisitor just so that the ClassReader doesn't see one that has been directly
- // created by a ClassWriter (see top level class comment)
- static class AJMethodVisitor extends MethodVisitor {
- public AJMethodVisitor(MethodVisitor mv) {
- super(Opcodes.ASM7,mv);
- }
- }
-
- }
-
- private static class AspectJConnectClassWriter extends ClassWriter {
- private final World world;
-
- public AspectJConnectClassWriter(ClassReader cr, World w) {
- super(cr, ClassWriter.COMPUTE_FRAMES); // passing in cr is necessary so cpool isnt modified (see 2.2.4 of asm doc)
- this.world = w;
- }
-
-
- // Implementation of getCommonSuperClass() that avoids Class.forName()
- @Override
- protected String getCommonSuperClass(final String type1, final String type2) {
-
- ResolvedType resolvedType1 = world.resolve(UnresolvedType.forName(type1.replace('/', '.')));
- ResolvedType resolvedType2 = world.resolve(UnresolvedType.forName(type2.replace('/', '.')));
-
- if (resolvedType1.isAssignableFrom(resolvedType2)) {
- return type1;
- }
-
- if (resolvedType2.isAssignableFrom(resolvedType1)) {
- return type2;
- }
-
- if (resolvedType1.isInterface() || resolvedType2.isInterface()) {
- return "java/lang/Object";
- } else {
- do {
- resolvedType1 = resolvedType1.getSuperclass();
- if (resolvedType1 == null) {
- // This happens if some types are missing, the getSuperclass() call on
- // MissingResolvedTypeWithKnownSignature will return the Missing type which
- // in turn returns a superclass of null. By returning Object here it
- // should surface the cantFindType message raised in the first problematic
- // getSuperclass call
- return "java/lang/Object";
- }
- if (resolvedType1.isParameterizedOrGenericType()) {
- resolvedType1 = resolvedType1.getRawType();
- }
- } while (!resolvedType1.isAssignableFrom(resolvedType2));
- return resolvedType1.getRawName().replace('.', '/');
- }
- }
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/loadtime/IWeavingContext.java b/weaver/src/org/aspectj/weaver/loadtime/IWeavingContext.java
deleted file mode 100644
index 51b781e86..000000000
--- a/weaver/src/org/aspectj/weaver/loadtime/IWeavingContext.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*******************************************************************************
- * 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:
- * David Knibb initial implementation
- *******************************************************************************/
-package org.aspectj.weaver.loadtime;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Enumeration;
-import java.util.List;
-
-import org.aspectj.weaver.loadtime.definition.Definition;
-import org.aspectj.weaver.tools.WeavingAdaptor;
-
-/**
- * This class adds support to AspectJ for an OSGi environment
- *
- * @author David Knibb
- */
-public interface IWeavingContext {
-
- /**
- * Allows the standard ClassLoader.getResources() mechanisms to be
- * replaced with a different implementation.
- * In an OSGi environment, this will allow for filtering to take
- * place on the results of ClassLoader.getResources(). In a non-OSGi
- * environment, ClassLoader.getResources should be returned.
- * @param name the name of the resource to search for
- * @return an enumeration containing all of the matching resources found
- * @throws IOException
- */
- public Enumeration<URL> getResources(String name) throws IOException;
-
- /**
- * In an OSGi environment, determin which bundle a URL originated from.
- * In a non-OSGi environment, implementors should return <code>null<code>.
- * @param url
- * @return
- * @deprecated use getFile() or getClassLoaderName()
- */
- public String getBundleIdFromURL(URL url);
-
- /**
- * In an environment with multiple class loaders allows each to be
- * identified using something safer and possibly shorter than toString
- * @return name of the associated class loader
- */
- public String getClassLoaderName ();
-
- public ClassLoader getClassLoader();
-
- /**
- * Format a URL
- * @return filename
- */
- public String getFile(URL url);
-
- /**
- * In an environment with multiple class loaders allows messages
- * to identified according to the weaving context
- * @return short name
- */
- public String getId ();
-
- /**
- * Return true if the classloader associated with this weaving context
- * is the one that will define the class with the specified name.
- * In a delegating classloader hierarchy this might check the parent won't
- * define it and the child will - in OSGi it will do something else.
- * @param classname name of the class, eg. "java.lang.String"
- * @return true if the associated classloader will define the class
- */
- 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<Definition> getDefinitions(final ClassLoader loader, WeavingAdaptor adaptor);
-
-}
diff --git a/weaver/src/org/aspectj/weaver/loadtime/definition/Definition.java b/weaver/src/org/aspectj/weaver/loadtime/definition/Definition.java
deleted file mode 100644
index de780156e..000000000
--- a/weaver/src/org/aspectj/weaver/loadtime/definition/Definition.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*******************************************************************************
- * 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:
- * Alexandre Vasseur initial implementation
- *******************************************************************************/
-package org.aspectj.weaver.loadtime.definition;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A POJO that contains raw strings from the XML (sort of XMLBean for our simple LTW DTD)
- *
- * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
- */
-public class Definition {
-
- private final StringBuffer weaverOptions;
- private final List<String> dumpPatterns;
- private boolean dumpBefore;
- private boolean perClassloaderDumpDir;
- private final List<String> includePatterns;
- private final List<String> excludePatterns;
- private final List<String> aspectClassNames;
- private final List<String> aspectExcludePatterns;
- private final List<String> aspectIncludePatterns;
- private final List<Definition.ConcreteAspect> concreteAspects;
-
- /**
- * When aspects are defined, they can specify a scope type pattern and then will only apply to types matching that pattern.
- */
- private final Map<String, String> scopedAspects;
-
- /**
- * Some aspects (from aspect libraries) will describe a type that must be around for them to function properly
- */
- private final Map<String, String> requiredTypesForAspects;
-
- public Definition() {
- weaverOptions = new StringBuffer();
- dumpBefore = false;
- perClassloaderDumpDir = false;
- dumpPatterns = new ArrayList<String>();
- includePatterns = new ArrayList<String>();
- excludePatterns = new ArrayList<String>();
- aspectClassNames = new ArrayList<String>();
- aspectExcludePatterns = new ArrayList<String>();
- aspectIncludePatterns = new ArrayList<String>();
- concreteAspects = new ArrayList<Definition.ConcreteAspect>();
- scopedAspects = new HashMap<String, String>();
- requiredTypesForAspects = new HashMap<String, String>();
- }
-
- public String getWeaverOptions() {
- return weaverOptions.toString();
- }
-
- public List<String> getDumpPatterns() {
- return dumpPatterns;
- }
-
- public void setDumpBefore(boolean b) {
- dumpBefore = b;
- }
-
- public boolean shouldDumpBefore() {
- return dumpBefore;
- }
-
- public void setCreateDumpDirPerClassloader(boolean b) {
- perClassloaderDumpDir = b;
- }
-
- public boolean createDumpDirPerClassloader() {
- return perClassloaderDumpDir;
- }
-
- public List<String> getIncludePatterns() {
- return includePatterns;
- }
-
- public List<String> getExcludePatterns() {
- return excludePatterns;
- }
-
- public List<String> getAspectClassNames() {
- return aspectClassNames;
- }
-
- public List<String> getAspectExcludePatterns() {
- return aspectExcludePatterns;
- }
-
- public List<String> getAspectIncludePatterns() {
- return aspectIncludePatterns;
- }
-
- public List<Definition.ConcreteAspect> getConcreteAspects() {
- return concreteAspects;
- }
-
- public static class ConcreteAspect {
- public final String name;
- public final String extend;
- public final String precedence;
- public final List<Definition.Pointcut> pointcuts;
- public final List<Definition.DeclareAnnotation> declareAnnotations;
- public final List<Definition.PointcutAndAdvice> pointcutsAndAdvice;
- public final String perclause;
- public List<Definition.DeclareErrorOrWarning> deows;
-
- public ConcreteAspect(String name, String extend) {
- this(name, extend, null, null);
- }
-
- public ConcreteAspect(String name, String extend, String precedence, String perclause) {
- this.name = name;
- // make sure extend set to null if ""
- if (extend == null || extend.length() == 0) {
- this.extend = null;
- if (precedence == null || precedence.length() == 0) {
- // if (pointcutsAndAdvice.size() == 0) {
- // throw new RuntimeException("Not allowed");
- // }
- }
- } else {
- this.extend = extend;
- }
- this.precedence = precedence;
- this.pointcuts = new ArrayList<Definition.Pointcut>();
- this.declareAnnotations = new ArrayList<Definition.DeclareAnnotation>();
- this.pointcutsAndAdvice = new ArrayList<Definition.PointcutAndAdvice>();
- this.deows = new ArrayList<Definition.DeclareErrorOrWarning>();
- this.perclause = perclause;
- }
- }
-
- public static class Pointcut {
- public final String name;
- public final String expression;
-
- public Pointcut(String name, String expression) {
- this.name = name;
- this.expression = expression;
- }
- }
-
- public enum AdviceKind {
- Before, After, AfterReturning, AfterThrowing, Around;
- }
-
- public enum DeclareAnnotationKind {
- Method, Field, Type;
- }
-
- public static class DeclareAnnotation {
- public final DeclareAnnotationKind declareAnnotationKind;
- public final String pattern;
- public final String annotation;
-
- public DeclareAnnotation(DeclareAnnotationKind kind, String pattern, String annotation) {
- this.declareAnnotationKind = kind;
- this.pattern = pattern;
- this.annotation = annotation;
- }
- }
-
- public static class PointcutAndAdvice {
- public final AdviceKind adviceKind;
- public final String pointcut;
- public final String adviceClass; // com.foo.Bar
- public final String adviceMethod; // foo(java.lang.String,org.aspectj.lang.JoinPoint)
-
- public PointcutAndAdvice(AdviceKind adviceKind, String pointcut, String adviceClass, String adviceMethod) {
- this.adviceKind = adviceKind;
- this.pointcut = pointcut;
- this.adviceClass = adviceClass;
- this.adviceMethod = adviceMethod;
- }
- }
-
- public static class DeclareErrorOrWarning {
- public final boolean isError;
- public final String pointcut;
- public final String message;
-
- public DeclareErrorOrWarning(boolean isError, String pointcut, String message) {
- this.isError = isError;
- this.pointcut = pointcut;
- this.message = message;
- }
- }
-
- public void appendWeaverOptions(String option) {
- weaverOptions.append(option.trim()).append(' ');
- }
-
- public void addScopedAspect(String name, String scopePattern) {
- scopedAspects.put(name, scopePattern);
- }
-
- public String getScopeForAspect(String name) {
- return scopedAspects.get(name);
- }
-
- public void setAspectRequires(String name, String requiredType) {
- requiredTypesForAspects.put(name, requiredType);
- }
-
- public String getAspectRequires(String name) {
- return requiredTypesForAspects.get(name);
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java b/weaver/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java
deleted file mode 100644
index 7ff275fd7..000000000
--- a/weaver/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/*******************************************************************************
- * 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:
- * Alexandre Vasseur initial implementation
- * Abraham Nevado - Lucierna simple caching strategy
- *******************************************************************************/
-package org.aspectj.weaver.loadtime.definition;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Hashtable;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.aspectj.util.LangUtil;
-import org.aspectj.weaver.loadtime.definition.Definition.AdviceKind;
-import org.aspectj.weaver.loadtime.definition.Definition.DeclareAnnotation;
-import org.aspectj.weaver.loadtime.definition.Definition.DeclareAnnotationKind;
-import org.xml.sax.Attributes;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.DefaultHandler;
-import org.xml.sax.helpers.XMLReaderFactory;
-
-/**
- *
- * @author Alexandre Vasseur
- * @author A. Nevado
- * @author Andy Clement
- */
-public class DocumentParser extends DefaultHandler {
- /**
- * The current DTD public id. The matching dtd will be searched as a resource.
- */
- private final static String DTD_PUBLIC_ID = "-//AspectJ//DTD 1.5.0//EN";
-
- /**
- * The DTD alias, for better user experience.
- */
- private final static String DTD_PUBLIC_ID_ALIAS = "-//AspectJ//DTD//EN";
-
- private final static String ASPECTJ_ELEMENT = "aspectj";
- private final static String WEAVER_ELEMENT = "weaver";
- private final static String DUMP_ELEMENT = "dump";
- private final static String DUMP_BEFOREANDAFTER_ATTRIBUTE = "beforeandafter";
- private final static String DUMP_PERCLASSLOADERDIR_ATTRIBUTE = "perclassloaderdumpdir";
- private final static String INCLUDE_ELEMENT = "include";
- private final static String EXCLUDE_ELEMENT = "exclude";
- private final static String OPTIONS_ATTRIBUTE = "options";
- private final static String ASPECTS_ELEMENT = "aspects";
- private final static String ASPECT_ELEMENT = "aspect";
- private final static String CONCRETE_ASPECT_ELEMENT = "concrete-aspect";
- private final static String NAME_ATTRIBUTE = "name";
- private final static String SCOPE_ATTRIBUTE = "scope";
- private final static String REQUIRES_ATTRIBUTE = "requires";
- private final static String EXTEND_ATTRIBUTE = "extends";
- private final static String PRECEDENCE_ATTRIBUTE = "precedence";
- private final static String PERCLAUSE_ATTRIBUTE = "perclause";
- private final static String POINTCUT_ELEMENT = "pointcut";
- private final static String BEFORE_ELEMENT = "before";
- private final static String AFTER_ELEMENT = "after";
- private final static String AFTER_RETURNING_ELEMENT = "after-returning";
- private final static String AFTER_THROWING_ELEMENT = "after-throwing";
- private final static String AROUND_ELEMENT = "around";
- private final static String WITHIN_ATTRIBUTE = "within";
- private final static String EXPRESSION_ATTRIBUTE = "expression";
- private final static String DECLARE_ANNOTATION_ELEMENT = "declare-annotation";
-
- private final Definition definition;
-
- private boolean inAspectJ;
- private boolean inWeaver;
- private boolean inAspects;
-
- private Definition.ConcreteAspect activeConcreteAspectDefinition;
-
- private static Hashtable<String, Definition> parsedFiles = new Hashtable<String, Definition>();
- private static boolean CACHE;
- private static final boolean LIGHTPARSER;
-
- static {
- boolean value = false;
- try {
- value = System.getProperty("org.aspectj.weaver.loadtime.configuration.cache", "true").equalsIgnoreCase("true");
- } catch (Throwable t) {
- t.printStackTrace();
- }
- CACHE = value;
-
- value = false;
- try {
- value = System.getProperty("org.aspectj.weaver.loadtime.configuration.lightxmlparser", "false")
- .equalsIgnoreCase("true");
- } catch (Throwable t) {
- t.printStackTrace();
- }
- LIGHTPARSER = value;
- }
-
- private DocumentParser() {
- definition = new Definition();
- }
-
- public static Definition parse(final URL url) throws Exception {
- if (CACHE && parsedFiles.containsKey(url.toString())) {
- return parsedFiles.get(url.toString());
- }
- Definition def = null;
-
- if (LIGHTPARSER) {
- def = SimpleAOPParser.parse(url);
- } else {
- def = saxParsing(url);
- }
-
- if (CACHE && def.getAspectClassNames().size() > 0) {
- parsedFiles.put(url.toString(), def);
- }
-
- return def;
- }
-
- private static Definition saxParsing(URL url) throws SAXException, ParserConfigurationException, IOException {
- DocumentParser parser = new DocumentParser();
-
- XMLReader xmlReader = getXMLReader();
- xmlReader.setContentHandler(parser);
- xmlReader.setErrorHandler(parser);
-
- try {
- xmlReader.setFeature("http://xml.org/sax/features/validation", false);
- } catch (SAXException e) {
- // fine, the parser don't do validation
- }
- try {
- xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
- } catch (SAXException e) {
- // fine, the parser don't do validation
- }
- try {
- xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
- } catch (SAXException e) {
- // fine, the parser don't do validation
- }
-
- xmlReader.setEntityResolver(parser);
- InputStream in = url.openStream();
- xmlReader.parse(new InputSource(in));
- return parser.definition;
- }
-
- private static XMLReader getXMLReader() throws SAXException, ParserConfigurationException {
- XMLReader xmlReader = null;
- /* Try this first for Java 5 */
- try {
- xmlReader = XMLReaderFactory.createXMLReader();
- }
-
- /* .. and ignore "System property ... not set" and then try this instead */
- catch (SAXException ex) {
- xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
- }
- return xmlReader;
- }
-
- public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
- if (publicId.equals(DTD_PUBLIC_ID) || publicId.equals(DTD_PUBLIC_ID_ALIAS)) {
- InputStream in = DocumentParser.class.getResourceAsStream("/aspectj_1_5_0.dtd");
- if (in == null) {
- System.err.println("AspectJ - WARN - could not read DTD " + publicId);
- return null;
- } else {
- return new InputSource(in);
- }
- } else {
- System.err.println("AspectJ - WARN - unknown DTD " + publicId + " - consider using " + DTD_PUBLIC_ID);
- return null;
- }
- }
-
- public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
- if (ASPECT_ELEMENT.equals(qName)) {
- String name = attributes.getValue(NAME_ATTRIBUTE);
- String scopePattern = replaceXmlAnd(attributes.getValue(SCOPE_ATTRIBUTE));
- String requiredType = attributes.getValue(REQUIRES_ATTRIBUTE);
- if (!isNull(name)) {
- definition.getAspectClassNames().add(name);
- if (scopePattern != null) {
- definition.addScopedAspect(name, scopePattern);
- }
- if (requiredType != null) {
- definition.setAspectRequires(name, requiredType);
- }
- }
- } else if (WEAVER_ELEMENT.equals(qName)) {
- String options = attributes.getValue(OPTIONS_ATTRIBUTE);
- if (!isNull(options)) {
- definition.appendWeaverOptions(options);
- }
- inWeaver = true;
- } else if (CONCRETE_ASPECT_ELEMENT.equals(qName)) {
- String name = attributes.getValue(NAME_ATTRIBUTE);
- String extend = attributes.getValue(EXTEND_ATTRIBUTE);
- String precedence = attributes.getValue(PRECEDENCE_ATTRIBUTE);
- String perclause = attributes.getValue(PERCLAUSE_ATTRIBUTE);
- if (!isNull(name)) {
- activeConcreteAspectDefinition = new Definition.ConcreteAspect(name, extend, precedence, perclause);
- // if (isNull(precedence) && !isNull(extend)) {// if no precedence, then extends must be there
- // m_lastConcreteAspect = new Definition.ConcreteAspect(name, extend);
- // } else if (!isNull(precedence)) {
- // // wether a pure precedence def, or an extendsANDprecedence def.
- // m_lastConcreteAspect = new Definition.ConcreteAspect(name, extend, precedence, perclause);
- // }
- definition.getConcreteAspects().add(activeConcreteAspectDefinition);
- }
- } else if (POINTCUT_ELEMENT.equals(qName) && activeConcreteAspectDefinition != null) {
- String name = attributes.getValue(NAME_ATTRIBUTE);
- String expression = attributes.getValue(EXPRESSION_ATTRIBUTE);
- if (!isNull(name) && !isNull(expression)) {
- activeConcreteAspectDefinition.pointcuts.add(new Definition.Pointcut(name, replaceXmlAnd(expression)));
- }
- } else if (DECLARE_ANNOTATION_ELEMENT.equals(qName) && activeConcreteAspectDefinition!=null) {
- String methodSig = attributes.getValue("method");
- String fieldSig = attributes.getValue("field");
- String typePat = attributes.getValue("type");
- String anno = attributes.getValue("annotation");
- if (isNull(anno)) {
- throw new SAXException("Badly formed <declare-annotation> element, 'annotation' value is missing");
- }
- if (isNull(methodSig) && isNull(fieldSig) && isNull(typePat)) {
- throw new SAXException("Badly formed <declare-annotation> element, need one of 'method'/'field'/'type' specified");
- }
- if (!isNull(methodSig)) {
- // declare @method
- activeConcreteAspectDefinition.declareAnnotations.add(new Definition.DeclareAnnotation(DeclareAnnotationKind.Method,
- methodSig, anno));
- } else if (!isNull(fieldSig)) {
- // declare @field
- activeConcreteAspectDefinition.declareAnnotations.add(new Definition.DeclareAnnotation(DeclareAnnotationKind.Field,
- fieldSig, anno));
- } else if (!isNull(typePat)) {
- // declare @type
- activeConcreteAspectDefinition.declareAnnotations.add(new Definition.DeclareAnnotation(DeclareAnnotationKind.Type,
- typePat, anno));
- }
- } else if (BEFORE_ELEMENT.equals(qName) && activeConcreteAspectDefinition != null) {
- String pointcut = attributes.getValue(POINTCUT_ELEMENT);
- String adviceClass = attributes.getValue("invokeClass");
- String adviceMethod = attributes.getValue("invokeMethod");
- if (!isNull(pointcut) && !isNull(adviceClass) && !isNull(adviceMethod)) {
- activeConcreteAspectDefinition.pointcutsAndAdvice.add(new Definition.PointcutAndAdvice(AdviceKind.Before,
- replaceXmlAnd(pointcut), adviceClass, adviceMethod));
- } else {
- throw new SAXException("Badly formed <before> element");
- }
- } else if (AFTER_ELEMENT.equals(qName) && activeConcreteAspectDefinition != null) {
- String pointcut = attributes.getValue(POINTCUT_ELEMENT);
- String adviceClass = attributes.getValue("invokeClass");
- String adviceMethod = attributes.getValue("invokeMethod");
- if (!isNull(pointcut) && !isNull(adviceClass) && !isNull(adviceMethod)) {
- activeConcreteAspectDefinition.pointcutsAndAdvice.add(new Definition.PointcutAndAdvice(AdviceKind.After,
- replaceXmlAnd(pointcut), adviceClass, adviceMethod));
- } else {
- throw new SAXException("Badly formed <after> element");
- }
- } else if (AROUND_ELEMENT.equals(qName) && activeConcreteAspectDefinition != null) {
- String pointcut = attributes.getValue(POINTCUT_ELEMENT);
- String adviceClass = attributes.getValue("invokeClass");
- String adviceMethod = attributes.getValue("invokeMethod");
- if (!isNull(pointcut) && !isNull(adviceClass) && !isNull(adviceMethod)) {
- activeConcreteAspectDefinition.pointcutsAndAdvice.add(new Definition.PointcutAndAdvice(AdviceKind.Around,
- replaceXmlAnd(pointcut), adviceClass, adviceMethod));
- } else {
- throw new SAXException("Badly formed <before> element");
- }
- } else if (ASPECTJ_ELEMENT.equals(qName)) {
- if (inAspectJ) {
- throw new SAXException("Found nested <aspectj> element");
- }
- inAspectJ = true;
- } else if (ASPECTS_ELEMENT.equals(qName)) {
- inAspects = true;
- } else if (INCLUDE_ELEMENT.equals(qName) && inWeaver) {
- String typePattern = getWithinAttribute(attributes);
- if (!isNull(typePattern)) {
- definition.getIncludePatterns().add(typePattern);
- }
- } else if (EXCLUDE_ELEMENT.equals(qName) && inWeaver) {
- String typePattern = getWithinAttribute(attributes);
- if (!isNull(typePattern)) {
- definition.getExcludePatterns().add(typePattern);
- }
- } else if (DUMP_ELEMENT.equals(qName) && inWeaver) {
- String typePattern = getWithinAttribute(attributes);
- if (!isNull(typePattern)) {
- definition.getDumpPatterns().add(typePattern);
- }
- String beforeAndAfter = attributes.getValue(DUMP_BEFOREANDAFTER_ATTRIBUTE);
- if (isTrue(beforeAndAfter)) {
- definition.setDumpBefore(true);
- }
- String perWeaverDumpDir = attributes.getValue(DUMP_PERCLASSLOADERDIR_ATTRIBUTE);
- if (isTrue(perWeaverDumpDir)) {
- definition.setCreateDumpDirPerClassloader(true);
- }
- } else if (EXCLUDE_ELEMENT.equals(qName) && inAspects) {
- String typePattern = getWithinAttribute(attributes);
- if (!isNull(typePattern)) {
- definition.getAspectExcludePatterns().add(typePattern);
- }
- } else if (INCLUDE_ELEMENT.equals(qName) && inAspects) {
- String typePattern = getWithinAttribute(attributes);
- if (!isNull(typePattern)) {
- definition.getAspectIncludePatterns().add(typePattern);
- }
- } else {
- throw new SAXException("Unknown element while parsing <aspectj> element: " + qName);
- }
- super.startElement(uri, localName, qName, attributes);
- }
-
- private String getWithinAttribute(Attributes attributes) {
- return replaceXmlAnd(attributes.getValue(WITHIN_ATTRIBUTE));
- }
-
- public void endElement(String uri, String localName, String qName) throws SAXException {
- if (CONCRETE_ASPECT_ELEMENT.equals(qName)) {
- activeConcreteAspectDefinition = null;
- } else if (ASPECTJ_ELEMENT.equals(qName)) {
- inAspectJ = false;
- } else if (WEAVER_ELEMENT.equals(qName)) {
- inWeaver = false;
- } else if (ASPECTS_ELEMENT.equals(qName)) {
- inAspects = false;
- }
- super.endElement(uri, localName, qName);
- }
-
- // TODO AV - define what we want for XML parser error - for now stderr
- public void warning(SAXParseException e) throws SAXException {
- super.warning(e);
- }
-
- public void error(SAXParseException e) throws SAXException {
- super.error(e);
- }
-
- public void fatalError(SAXParseException e) throws SAXException {
- super.fatalError(e);
- }
-
- private static String replaceXmlAnd(String expression) {
- // TODO AV do we need to handle "..)AND" or "AND(.." ?
- return LangUtil.replace(expression, " AND ", " && ");
- }
-
- private boolean isNull(String s) {
- return (s == null || s.length() <= 0);
- }
-
- private boolean isTrue(String s) {
- return (s != null && s.equals("true"));
- }
-
- /**
- * Turn off caching
- */
- public static void deactivateCaching() {
- CACHE = false;
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/loadtime/definition/LightXMLParser.java b/weaver/src/org/aspectj/weaver/loadtime/definition/LightXMLParser.java
deleted file mode 100644
index 09a9df96f..000000000
--- a/weaver/src/org/aspectj/weaver/loadtime/definition/LightXMLParser.java
+++ /dev/null
@@ -1,471 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011 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:
- * Abraham Nevado - Lucierna initial implementation
- *******************************************************************************/
-package org.aspectj.weaver.loadtime.definition;
-
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-public class LightXMLParser {
-
- private final static char NULL_CHAR = '\0';
- private Map<String, Object> attributes;
- private ArrayList children;
- private String name;
- private char pushedBackChar;
- private Reader reader;
-
- private static Map<String, char[]> entities = new HashMap<String, char[]>();
-
- static {
- entities.put("amp", new char[] { '&' });
- entities.put("quot", new char[] { '"' });
- entities.put("apos", new char[] { '\'' });
- entities.put("lt", new char[] { '<' });
- entities.put("gt", new char[] { '>' });
- }
-
- public LightXMLParser() {
- this.name = null;
- this.attributes = new HashMap<String, Object>();
- this.children = new ArrayList();
- }
-
- public ArrayList getChildrens() {
- return this.children;
- }
-
- public String getName() {
- return this.name;
- }
-
- public void parseFromReader(Reader reader) throws Exception {
- this.pushedBackChar = NULL_CHAR;
- this.attributes = new HashMap<String, Object>();
- this.name = null;
- this.children = new ArrayList();
- this.reader = reader;
-
- while (true) {
- // Skips whiteSpaces, blanks, \r\n..
- char c = this.skipBlanks();
-
- // All xml should start by <xml, a <!-- or <nodeName, if not throw
- // exception
- if (c != '<') {
- throw new Exception("LightParser Exception: Expected < but got: " + c);
- }
-
- // read next character
- c = this.getNextChar();
-
- // if starts with ! or ? it is <?xml or a comment: skip
- if ((c == '!') || (c == '?')) {
- this.skipCommentOrXmlTag(0);
- } else {
- // it is a node, pusch character back
- this.pushBackChar(c);
- // parse node
- this.parseNode(this);
- // Only one root node, so finsh.
- return;
- }
- }
- }
-
- private char skipBlanks() throws Exception {
- while (true) {
- char c = this.getNextChar();
- switch (c) {
- case '\n':
- case '\r':
- case ' ':
- case '\t':
- break;
- default:
- return c;
- }
- }
- }
-
- private char getWhitespaces(StringBuffer result) throws Exception {
- while (true) {
- char c = this.getNextChar();
- switch (c) {
- case ' ':
- case '\t':
- case '\n':
- result.append(c);
- case '\r':
- break;
- default:
- return c;
- }
- }
- }
-
- private void getNodeName(StringBuffer result) throws Exception {
- char c;
- while (true) {
- // Iterate while next character is not [a-z] [A-Z] [0-9] [ .:_-] not
- // null
- c = this.getNextChar();
- if (((c < 'a') || (c > 'z')) && ((c > 'Z') || (c < 'A')) && ((c > '9') || (c < '0')) && (c != '_') && (c != '-')
- && (c != '.') && (c != ':')) {
- this.pushBackChar(c);
- return;
- }
- result.append(c);
- }
- }
-
- private void getString(StringBuffer string) throws Exception {
- char delimiter = this.getNextChar();
- if ((delimiter != '\'') && (delimiter != '"')) {
- throw new Exception("Parsing error. Expected ' or \" but got: " + delimiter);
-
- }
-
- while (true) {
- char c = this.getNextChar();
- if (c == delimiter) {
- return;
- } else if (c == '&') {
- this.mapEntity(string);
- } else {
- string.append(c);
- }
- }
- }
-
- private void getPCData(StringBuffer data) throws Exception {
- while (true) {
- char c = this.getNextChar();
- if (c == '<') {
- c = this.getNextChar();
- if (c == '!') {
- this.checkCDATA(data);
- } else {
- this.pushBackChar(c);
- return;
- }
- } else {
- data.append(c);
- }
- }
- }
-
- private boolean checkCDATA(StringBuffer buf) throws Exception {
- char c = this.getNextChar();
- if (c != '[') {
- this.pushBackChar(c);
- this.skipCommentOrXmlTag(0);
- return false;
- } else if (!this.checkLiteral("CDATA[")) {
- this.skipCommentOrXmlTag(1); // one [ has already been read
- return false;
- } else {
- int delimiterCharsSkipped = 0;
- while (delimiterCharsSkipped < 3) {
- c = this.getNextChar();
- switch (c) {
- case ']':
- if (delimiterCharsSkipped < 2) {
- delimiterCharsSkipped++;
- } else {
- buf.append(']');
- buf.append(']');
- delimiterCharsSkipped = 0;
- }
- break;
- case '>':
- if (delimiterCharsSkipped < 2) {
- for (int i = 0; i < delimiterCharsSkipped; i++) {
- buf.append(']');
- }
- delimiterCharsSkipped = 0;
- buf.append('>');
- } else {
- delimiterCharsSkipped = 3;
- }
- break;
- default:
- for (int i = 0; i < delimiterCharsSkipped; i++) {
- buf.append(']');
- }
- buf.append(c);
- delimiterCharsSkipped = 0;
- }
- }
- return true;
- }
- }
-
- private void skipCommentOrXmlTag(int bracketLevel) throws Exception {
- char delim = NULL_CHAR;
- int level = 1;
- char c;
- if (bracketLevel == 0) {
- c = this.getNextChar();
- if (c == '-') {
- c = this.getNextChar();
- if (c == ']') {
- bracketLevel--;
- } else if (c == '[') {
- bracketLevel++;
- } else if (c == '-') {
- this.skipComment();
- return;
- }
- } else if (c == '[') {
- bracketLevel++;
- }
- }
- while (level > 0) {
- c = this.getNextChar();
- if (delim == NULL_CHAR) {
- if ((c == '"') || (c == '\'')) {
- delim = c;
- } else if (bracketLevel <= 0) {
- if (c == '<') {
- level++;
- } else if (c == '>') {
- level--;
- }
- }
- if (c == '[') {
- bracketLevel++;
- } else if (c == ']') {
- bracketLevel--;
- }
- } else {
- if (c == delim) {
- delim = NULL_CHAR;
- }
- }
- }
- }
-
- private void parseNode(LightXMLParser elt) throws Exception {
- // Now we are in a new node element. Get its name
- StringBuffer buf = new StringBuffer();
- this.getNodeName(buf);
- String name = buf.toString();
- elt.setName(name);
-
- char c = this.skipBlanks();
- while ((c != '>') && (c != '/')) {
- // Get attributes
- emptyBuf(buf);
- this.pushBackChar(c);
- this.getNodeName(buf);
- String key = buf.toString();
- c = this.skipBlanks();
- if (c != '=') {
- throw new Exception("Parsing error. Expected = but got: " + c);
- }
- // Go up to " character and push it back
- this.pushBackChar(this.skipBlanks());
-
- emptyBuf(buf);
- this.getString(buf);
-
- elt.setAttribute(key, buf);
-
- // Skip blanks
- c = this.skipBlanks();
- }
- if (c == '/') {
- c = this.getNextChar();
- if (c != '>') {
- throw new Exception("Parsing error. Expected > but got: " + c);
- }
- return;
- }
-
- // Now see if we got content, or CDATA, if content get it: it is free...
- emptyBuf(buf);
- c = this.getWhitespaces(buf);
- if (c != '<') {
- // It is PCDATA
- this.pushBackChar(c);
- this.getPCData(buf);
- } else {
- // It is content: get it, or CDATA.
- while (true) {
- c = this.getNextChar();
- if (c == '!') {
- if (this.checkCDATA(buf)) {
- this.getPCData(buf);
- break;
- } else {
- c = this.getWhitespaces(buf);
- if (c != '<') {
- this.pushBackChar(c);
- this.getPCData(buf);
- break;
- }
- }
- } else {
- if (c != '/') {
- emptyBuf(buf);
- }
- if (c == '/') {
- this.pushBackChar(c);
- }
- break;
- }
- }
- }
- if (buf.length() == 0) {
- // It is a comment
- while (c != '/') {
- if (c == '!') {
- for (int i = 0; i < 2; i++) {
- c = this.getNextChar();
- if (c != '-') {
- throw new Exception("Parsing error. Expected element or comment");
- }
- }
- this.skipComment();
- } else {
- // it is a new node
- this.pushBackChar(c);
- LightXMLParser child = this.createAnotherElement();
- this.parseNode(child);
- elt.addChild(child);
- }
- c = this.skipBlanks();
- if (c != '<') {
- throw new Exception("Parsing error. Expected <, but got: " + c);
- }
- c = this.getNextChar();
- }
- this.pushBackChar(c);
- } // Here content could be grabbed
-
- c = this.getNextChar();
- if (c != '/') {
- throw new Exception("Parsing error. Expected /, but got: " + c);
- }
- this.pushBackChar(this.skipBlanks());
- if (!this.checkLiteral(name)) {
- throw new Exception("Parsing error. Expected " + name);
- }
- if (this.skipBlanks() != '>') {
- throw new Exception("Parsing error. Expected >, but got: " + c);
- }
- }
-
- private void skipComment() throws Exception {
- int dashes = 2;
- while (dashes > 0) {
- char ch = this.getNextChar();
- if (ch == '-') {
- dashes -= 1;
- } else {
- dashes = 2;
- }
- }
-
- char nextChar = this.getNextChar();
- if (nextChar != '>') {
- throw new Exception("Parsing error. Expected > but got: " + nextChar);
- }
- }
-
- private boolean checkLiteral(String literal) throws Exception {
- int length = literal.length();
- for (int i = 0; i < length; i++) {
- if (this.getNextChar() != literal.charAt(i)) {
- return false;
- }
- }
- return true;
- }
-
- private char getNextChar() throws Exception {
- if (this.pushedBackChar != NULL_CHAR) {
- char c = this.pushedBackChar;
- this.pushedBackChar = NULL_CHAR;
- return c;
- } else {
- int i = this.reader.read();
- if (i < 0) {
- throw new Exception("Parsing error. Unexpected end of data");
- } else {
- return (char) i;
- }
- }
- }
-
- private void mapEntity(StringBuffer buf) throws Exception {
- char c = this.NULL_CHAR;
- StringBuffer keyBuf = new StringBuffer();
- while (true) {
- c = this.getNextChar();
- if (c == ';') {
- break;
- }
- keyBuf.append(c);
- }
- String key = keyBuf.toString();
- if (key.charAt(0) == '#') {
- try {
- if (key.charAt(1) == 'x') {
- c = (char) Integer.parseInt(key.substring(2), 16);
- } else {
- c = (char) Integer.parseInt(key.substring(1), 10);
- }
- } catch (NumberFormatException e) {
- throw new Exception("Unknown entity: " + key);
- }
- buf.append(c);
- } else {
- char[] value = (char[]) entities.get(key);
- if (value == null) {
- throw new Exception("Unknown entity: " + key);
- }
- buf.append(value);
- }
- }
-
- private void pushBackChar(char c) {
- this.pushedBackChar = c;
- }
-
- private void addChild(LightXMLParser child) {
- this.children.add(child);
- }
-
- private void setAttribute(String name, Object value) {
- this.attributes.put(name, value.toString());
- }
-
- public Map<String, Object> getAttributes() {
- return this.attributes;
- }
-
- private LightXMLParser createAnotherElement() {
- return new LightXMLParser();
- }
-
- private void setName(String name) {
- this.name = name;
- }
-
- private void emptyBuf(StringBuffer buf) {
- buf.setLength(0);
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/loadtime/definition/SimpleAOPParser.java b/weaver/src/org/aspectj/weaver/loadtime/definition/SimpleAOPParser.java
deleted file mode 100644
index bcd6ddcd0..000000000
--- a/weaver/src/org/aspectj/weaver/loadtime/definition/SimpleAOPParser.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011 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:
- * Abraham Nevado - Lucierna initial implementation
- * Just a slight variation of current DocumentParser.java from Alexandre Vasseur.
- *******************************************************************************/
-package org.aspectj.weaver.loadtime.definition;
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.Set;
-
-import org.aspectj.util.LangUtil;
-import org.aspectj.weaver.loadtime.definition.Definition.AdviceKind;
-import org.aspectj.weaver.loadtime.definition.Definition.DeclareAnnotationKind;
-import org.xml.sax.SAXException;
-
-/**
- * This class has been created to avoid deadlocks when instrumenting SAXParser.
- * So it is used as a wrapper for the ligthweigh XML parser LightXMLParser.
- *
- * @author A. Nevado
- */
-public class SimpleAOPParser {
-
- private final static String ASPECTJ_ELEMENT = "aspectj";
- private final static String WEAVER_ELEMENT = "weaver";
- private final static String DUMP_ELEMENT = "dump";
- private final static String DUMP_BEFOREANDAFTER_ATTRIBUTE = "beforeandafter";
- private final static String DUMP_PERCLASSLOADERDIR_ATTRIBUTE = "perclassloaderdumpdir";
- private final static String INCLUDE_ELEMENT = "include";
- private final static String EXCLUDE_ELEMENT = "exclude";
- private final static String OPTIONS_ATTRIBUTE = "options";
- private final static String ASPECTS_ELEMENT = "aspects";
- private final static String ASPECT_ELEMENT = "aspect";
- private final static String CONCRETE_ASPECT_ELEMENT = "concrete-aspect";
- private final static String NAME_ATTRIBUTE = "name";
- private final static String SCOPE_ATTRIBUTE = "scope";
- private final static String REQUIRES_ATTRIBUTE = "requires";
- private final static String EXTEND_ATTRIBUTE = "extends";
- private final static String PRECEDENCE_ATTRIBUTE = "precedence";
- private final static String PERCLAUSE_ATTRIBUTE = "perclause";
- private final static String POINTCUT_ELEMENT = "pointcut";
- private final static String WITHIN_ATTRIBUTE = "within";
- private final static String EXPRESSION_ATTRIBUTE = "expression";
- private static final String DECLARE_ANNOTATION = "declare-annotation";
- private static final String ANNONATION_TAG = "annotation";
- private static final String ANNO_KIND_TYPE = "type";
- private static final String ANNO_KIND_METHOD = "method";
- private static final String ANNO_KIND_FIELD = "field";
- private final static String BEFORE_ELEMENT = "before";
- private final static String AFTER_ELEMENT = "after";
- private final static String AROUND_ELEMENT = "around";
- private final Definition m_definition;
- private boolean m_inAspectJ;
- private boolean m_inWeaver;
- private boolean m_inAspects;
-
- private Definition.ConcreteAspect m_lastConcreteAspect;
-
- private SimpleAOPParser() {
- m_definition = new Definition();
- }
-
- public static Definition parse(final URL url) throws Exception {
- // FileReader freader = new FileReader("/tmp/aop.xml");
- InputStream in = url.openStream();
- LightXMLParser xml = new LightXMLParser();
- xml.parseFromReader(new InputStreamReader(in));
- SimpleAOPParser sap = new SimpleAOPParser();
- traverse(sap, xml);
- return sap.m_definition;
- }
-
- private void startElement(String qName, Map attrMap) throws Exception {
- if (ASPECT_ELEMENT.equals(qName)) {
- String name = (String) attrMap.get(NAME_ATTRIBUTE);
- String scopePattern = replaceXmlAnd((String) attrMap
- .get(SCOPE_ATTRIBUTE));
- String requiredType = (String) attrMap.get(REQUIRES_ATTRIBUTE);
- if (!isNull(name)) {
- m_definition.getAspectClassNames().add(name);
- if (scopePattern != null) {
- m_definition.addScopedAspect(name, scopePattern);
- }
- if (requiredType != null) {
- m_definition.setAspectRequires(name, requiredType);
- }
- }
- } else if (WEAVER_ELEMENT.equals(qName)) {
- String options = (String) attrMap.get(OPTIONS_ATTRIBUTE);
- if (!isNull(options)) {
- m_definition.appendWeaverOptions(options);
- }
- m_inWeaver = true;
- } else if (CONCRETE_ASPECT_ELEMENT.equals(qName)) {
- String name = (String) attrMap.get(NAME_ATTRIBUTE);
- String extend = (String) attrMap.get(EXTEND_ATTRIBUTE);
- String precedence = (String) attrMap.get(PRECEDENCE_ATTRIBUTE);
- String perclause = (String) attrMap.get(PERCLAUSE_ATTRIBUTE);
- if (!isNull(name)) {
- m_lastConcreteAspect = new Definition.ConcreteAspect(name,
- extend, precedence, perclause);
- m_definition.getConcreteAspects().add(m_lastConcreteAspect);
- }
- } else if (POINTCUT_ELEMENT.equals(qName)
- && m_lastConcreteAspect != null) {
- String name = (String) attrMap.get(NAME_ATTRIBUTE);
- String expression = (String) attrMap.get(EXPRESSION_ATTRIBUTE);
- if (!isNull(name) && !isNull(expression)) {
- m_lastConcreteAspect.pointcuts.add(new Definition.Pointcut(
- name, replaceXmlAnd(expression)));
- }
- } else if (ASPECTJ_ELEMENT.equals(qName)) {
- if (m_inAspectJ) {
- throw new Exception("Found nested <aspectj> element");
- }
- m_inAspectJ = true;
- } else if (ASPECTS_ELEMENT.equals(qName)) {
- m_inAspects = true;
- } else if (INCLUDE_ELEMENT.equals(qName) && m_inWeaver) {
- String typePattern = getWithinAttribute(attrMap);
- if (!isNull(typePattern)) {
- m_definition.getIncludePatterns().add(typePattern);
- }
- } else if (EXCLUDE_ELEMENT.equals(qName) && m_inWeaver) {
- String typePattern = getWithinAttribute(attrMap);
- if (!isNull(typePattern)) {
- m_definition.getExcludePatterns().add(typePattern);
- }
- } else if (DUMP_ELEMENT.equals(qName) && m_inWeaver) {
- String typePattern = getWithinAttribute(attrMap);
- if (!isNull(typePattern)) {
- m_definition.getDumpPatterns().add(typePattern);
- }
- String beforeAndAfter = (String) attrMap
- .get(DUMP_BEFOREANDAFTER_ATTRIBUTE);
- if (isTrue(beforeAndAfter)) {
- m_definition.setDumpBefore(true);
- }
- String perWeaverDumpDir = (String) attrMap
- .get(DUMP_PERCLASSLOADERDIR_ATTRIBUTE);
- if (isTrue(perWeaverDumpDir)) {
- m_definition.setCreateDumpDirPerClassloader(true);
- }
- } else if (EXCLUDE_ELEMENT.equals(qName) && m_inAspects) {
- String typePattern = getWithinAttribute(attrMap);
- if (!isNull(typePattern)) {
- m_definition.getAspectExcludePatterns().add(typePattern);
- }
- } else if (INCLUDE_ELEMENT.equals(qName) && m_inAspects) {
- String typePattern = getWithinAttribute(attrMap);
- if (!isNull(typePattern)) {
- m_definition.getAspectIncludePatterns().add(typePattern);
- }
- }else if (DECLARE_ANNOTATION.equals(qName) && m_inAspects) {
- String anno = (String) attrMap.get(ANNONATION_TAG);
- if (!isNull(anno)){
- String pattern = (String) attrMap.get(ANNO_KIND_FIELD);
- if (pattern != null){
- m_lastConcreteAspect.declareAnnotations.add(new Definition.DeclareAnnotation(
- DeclareAnnotationKind.Field, pattern, anno));
- }
- else{
- pattern = (String) attrMap.get(ANNO_KIND_METHOD);
- if (pattern != null){
- m_lastConcreteAspect.declareAnnotations.add(new Definition.DeclareAnnotation(
- DeclareAnnotationKind.Method, pattern, anno));
- }
- else{
- pattern = (String) attrMap.get(ANNO_KIND_TYPE);
- if (pattern != null){
- m_lastConcreteAspect.declareAnnotations.add(new Definition.DeclareAnnotation(
- DeclareAnnotationKind.Type, pattern, anno));
- }
- }
- }
-
- }
- }
- else if (BEFORE_ELEMENT.equals(qName) && m_inAspects ) {
- String pointcut = (String) attrMap.get(POINTCUT_ELEMENT);
- String adviceClass = (String) attrMap.get("invokeClass");
- String adviceMethod = (String) attrMap.get("invokeMethod");
- if (!isNull(pointcut) && !isNull(adviceClass) && !isNull(adviceMethod)) {
- m_lastConcreteAspect.pointcutsAndAdvice.add(new Definition.PointcutAndAdvice(AdviceKind.Before,
- replaceXmlAnd(pointcut), adviceClass, adviceMethod));
- } else {
- throw new SAXException("Badly formed <before> element");
- }
- } else if (AFTER_ELEMENT.equals(qName) && m_inAspects) {
- String pointcut = (String) attrMap.get(POINTCUT_ELEMENT);
- String adviceClass = (String) attrMap.get("invokeClass");
- String adviceMethod = (String) attrMap.get("invokeMethod");
- if (!isNull(pointcut) && !isNull(adviceClass) && !isNull(adviceMethod)) {
- m_lastConcreteAspect.pointcutsAndAdvice.add(new Definition.PointcutAndAdvice(AdviceKind.After,
- replaceXmlAnd(pointcut), adviceClass, adviceMethod));
- } else {
- throw new SAXException("Badly formed <after> element");
- }
- } else if (AROUND_ELEMENT.equals(qName) && m_inAspects) {
- String pointcut = (String) attrMap.get(POINTCUT_ELEMENT);
- String adviceClass = (String) attrMap.get("invokeClass");
- String adviceMethod = (String) attrMap.get("invokeMethod");
- if (!isNull(pointcut) && !isNull(adviceClass) && !isNull(adviceMethod)) {
- m_lastConcreteAspect.pointcutsAndAdvice.add(new Definition.PointcutAndAdvice(AdviceKind.Around,
- replaceXmlAnd(pointcut), adviceClass, adviceMethod));
- }
- }
- else {
- throw new Exception(
- "Unknown element while parsing <aspectj> element: " + qName);
- }
- }
-
- private void endElement(String qName) throws Exception {
- if (CONCRETE_ASPECT_ELEMENT.equals(qName)) {
- m_lastConcreteAspect = null;
- } else if (ASPECTJ_ELEMENT.equals(qName)) {
- m_inAspectJ = false;
- } else if (WEAVER_ELEMENT.equals(qName)) {
- m_inWeaver = false;
- } else if (ASPECTS_ELEMENT.equals(qName)) {
- m_inAspects = false;
- }
- }
-
- private String getWithinAttribute(Map attributes) {
- return replaceXmlAnd((String) attributes.get(WITHIN_ATTRIBUTE));
- }
-
- private static String replaceXmlAnd(String expression) {
- // TODO AV do we need to handle "..)AND" or "AND(.." ?
- return LangUtil.replace(expression, " AND ", " && ");
- }
-
- private boolean isNull(String s) {
- return (s == null || s.length() <= 0);
- }
-
- private boolean isTrue(String s) {
- return (s != null && s.equals("true"));
- }
-
- private static void traverse(SimpleAOPParser sap, LightXMLParser xml)
- throws Exception {
- sap.startElement(xml.getName(), xml.getAttributes());
- ArrayList childrens = xml.getChildrens();
- for (int i = 0; i < childrens.size(); i++) {
- LightXMLParser child = (LightXMLParser) childrens.get(i);
- traverse(sap, child);
- }
- sap.endElement(xml.getName());
-
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/ltw/LTWWorld.java b/weaver/src/org/aspectj/weaver/ltw/LTWWorld.java
deleted file mode 100644
index de5a4d854..000000000
--- a/weaver/src/org/aspectj/weaver/ltw/LTWWorld.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/* *******************************************************************
- * 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:
- * Ron Bodkin Initial implementation
- * ******************************************************************/
-package org.aspectj.weaver.ltw;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.aspectj.apache.bcel.classfile.JavaClass;
-import org.aspectj.bridge.IMessageHandler;
-import org.aspectj.util.LangUtil;
-import org.aspectj.weaver.Dump.IVisitor;
-import org.aspectj.weaver.ICrossReferenceHandler;
-import org.aspectj.weaver.ReferenceType;
-import org.aspectj.weaver.ReferenceTypeDelegate;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.bcel.BcelWorld;
-import org.aspectj.weaver.loadtime.IWeavingContext;
-import org.aspectj.weaver.reflect.AnnotationFinder;
-import org.aspectj.weaver.reflect.IReflectionWorld;
-import org.aspectj.weaver.reflect.ReflectionBasedReferenceTypeDelegateFactory;
-import org.aspectj.weaver.reflect.ReflectionWorld;
-
-/**
- * @author adrian
- * @author Ron Bodkin
- *
- * For use in LT weaving
- *
- * Backed by both a BcelWorld and a ReflectionWorld
- *
- * Needs a callback when a woven class is defined This is the trigger for us to ditch the class from Bcel and cache it in
- * the reflective world instead.
- *
- * Create by passing in a classloader, message handler
- */
-public class LTWWorld extends BcelWorld implements IReflectionWorld {
-
- private AnnotationFinder annotationFinder;
- private IWeavingContext weavingContext;
- private String classLoaderString;
-
- private String classLoaderParentString;
-
- protected final static Class concurrentMapClass;
-
- private static final boolean ShareBootstrapTypes = false;
- protected static Map/* <String, WeakReference<ReflectionBasedReferenceTypeDelegate>> */bootstrapTypes;
-
- static {
- if (ShareBootstrapTypes) {
- concurrentMapClass = makeConcurrentMapClass();
- bootstrapTypes = makeConcurrentMap();
- } else {
- concurrentMapClass = null;
- }
- }
-
- /**
- * Build a World from a ClassLoader, for LTW support
- */
- public LTWWorld(ClassLoader loader, IWeavingContext weavingContext, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
- super(loader, handler, xrefHandler);
- this.weavingContext = weavingContext;
- try {
- classLoaderString = loader.toString();
- } catch (Throwable t) {
- // Possibly some state in the loader isn't initialized but is used in the toString()
- classLoaderString = loader.getClass().getName()+":"+Integer.toString(System.identityHashCode(loader));
- }
- classLoaderParentString = (loader.getParent() == null ? "<NullParent>" : loader.getParent().toString());
- setBehaveInJava5Way(LangUtil.is15VMOrGreater());
- annotationFinder = ReflectionWorld.makeAnnotationFinderIfAny(loader, this);
- }
-
- public ClassLoader getClassLoader() {
- return weavingContext.getClassLoader();
- }
-
- // TEST
- // this is probably easier: just mark anything loaded while loading aspects as not
- // expendible... it also fixes a possible bug whereby non-rewoven aspects are deemed expendible
- // <exclude within="org.foo.aspects..*"/>
- // protected boolean isExpendable(ResolvedType type) {
- // return ((type != null) && !loadingAspects && !type.isAspect() && (!type
- // .isPrimitiveType()));
- // }
-
- /**
- * @Override
- */
- @Override
- protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) {
-
- // use reflection delegates for all bootstrap types
- ReferenceTypeDelegate bootstrapLoaderDelegate = resolveIfBootstrapDelegate(ty);
- if (bootstrapLoaderDelegate != null) {
- return bootstrapLoaderDelegate;
- }
-
- return super.resolveDelegate(ty);
- }
-
- protected ReferenceTypeDelegate resolveIfBootstrapDelegate(ReferenceType ty) {
- // first check for anything available in the bootstrap loader: these types are just defined from that without allowing
- // nondelegation
- // if (!ShareBootstrapTypes) return null;
- // String name = ty.getName();
- // Reference bootRef = (Reference) bootstrapTypes.get(name);
- // if (bootRef != null) {
- // ReferenceTypeDelegate rtd = (ReferenceTypeDelegate) bootRef.get();
- // if (rtd != null) {
- // return rtd;
- // }
- // }
- //
- // char fc = name.charAt(0);
- // if (fc == 'j' || fc == 'c' || fc == 'o' || fc == 's') { // cheaper than imminent string startsWith tests
- // if (name.startsWith("java") || name.startsWith("com.sun.") || name.startsWith("org.w3c") ||
- // name.startsWith("sun.") || name.startsWith("org.omg")) {
- // ReferenceTypeDelegate bootstrapLoaderDelegate = resolveReflectionTypeDelegate(ty, null);
- // if (bootstrapLoaderDelegate != null) {
- // // it's always fine to load these bytes: there's no weaving into them
- // // and since the class isn't initialized, all we are doing at this point is loading the bytes
- // // processedRefTypes.put(ty, this); // has no effect - and probably too aggressive if we did store
- // // these in the type map
- //
- // // should we share these, like we do the BCEL delegates?
- // bootstrapTypes.put(ty.getName(), new WeakReference(bootstrapLoaderDelegate));
- // }
- // return bootstrapLoaderDelegate;
- // }
- // }
- return null;
- }
-
- /**
- * Helper method to resolve the delegate from the reflection delegate factory.
- */
- private ReferenceTypeDelegate resolveReflectionTypeDelegate(ReferenceType ty, ClassLoader resolutionLoader) {
- ReferenceTypeDelegate res = ReflectionBasedReferenceTypeDelegateFactory.createDelegate(ty, this, resolutionLoader);
- return res;
- }
-
- /**
- * Remove this class from the typeMap. Call back to be made from a publishing class loader The class loader should, ideally,
- * make this call on each not yet working
- *
- * @param clazz
- */
- public void loadedClass(Class clazz) {
- }
-
- private static final long serialVersionUID = 1;
-
- public AnnotationFinder getAnnotationFinder() {
- return this.annotationFinder;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.aspectj.weaver.reflect.IReflectionWorld#resolve(java.lang.Class)
- */
- public ResolvedType resolve(Class aClass) {
- return ReflectionWorld.resolve(this, aClass);
- }
-
- private static Map makeConcurrentMap() {
- if (concurrentMapClass != null) {
- try {
- return (Map) concurrentMapClass.newInstance();
- } catch (InstantiationException ie) {
- } catch (IllegalAccessException iae) {
- }
- // fall through if exceptions
- }
- return Collections.synchronizedMap(new HashMap());
- }
-
- private static Class makeConcurrentMapClass() {
- String betterChoices[] = { "java.util.concurrent.ConcurrentHashMap",
- "edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap",
- "EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap" };
- for (int i = 0; i < betterChoices.length; i++) {
- try {
- return Class.forName(betterChoices[i]);
- } catch (ClassNotFoundException cnfe) {
- // try the next one
- } catch (SecurityException se) {
- // you get one of these if you dare to try to load an undefined class in a
- // package starting with java like java.util.concurrent
- }
- }
- return null;
- }
-
- @Override
- public boolean isRunMinimalMemory() {
- if (isRunMinimalMemorySet()) {
- return super.isRunMinimalMemory();
- }
- return false;
- }
-
- // One type is completed at a time, if multiple need doing then they
- // are queued up
- private boolean typeCompletionInProgress = false;
- private List/* ResolvedType */typesForCompletion = new ArrayList();
-
- @Override
- protected void completeBinaryType(ResolvedType ret) {
- if (isLocallyDefined(ret.getName())) {
- if (typeCompletionInProgress) {
- typesForCompletion.add(ret);
- } else {
- try {
- typeCompletionInProgress = true;
- completeHierarchyForType(ret);
- } finally {
- typeCompletionInProgress = false;
- }
- while (typesForCompletion.size() != 0) {
- ResolvedType rt = (ResolvedType) typesForCompletion.get(0);
- completeHierarchyForType(rt);
- typesForCompletion.remove(0);
- }
- }
- } else {
- if (!ret.needsModifiableDelegate()) {
- ret = completeNonLocalType(ret);
- }
- }
- }
-
- private void completeHierarchyForType(ResolvedType ret) {
- getLint().typeNotExposedToWeaver.setSuppressed(true);
- weaveInterTypeDeclarations(ret);
- getLint().typeNotExposedToWeaver.setSuppressed(false);
- }
-
- protected boolean needsCompletion() {
- return true;
- }
-
- @Override
- public boolean isLocallyDefined(String classname) {
- return weavingContext.isLocallyDefined(classname);
- }
-
- protected ResolvedType completeNonLocalType(ResolvedType ret) {
- if (ret.isMissing()) {
- return ret; // who knows ?!?
- }
- ResolvedType toResolve = ret;
- if (ret.isParameterizedType() || ret.isGenericType()) {
- toResolve = toResolve.getGenericType();
- }
- ReferenceTypeDelegate rtd = resolveReflectionTypeDelegate((ReferenceType) toResolve, getClassLoader());
- ((ReferenceType) ret).setDelegate(rtd);
- return ret;
- }
-
- @Override
- public void storeClass(JavaClass clazz) {
- ensureRepositorySetup();
- delegate.storeClass(clazz);
- }
-
- @Override
- public void accept(IVisitor visitor) {
- visitor.visitObject("Class loader:");
- visitor.visitObject(classLoaderString);
- visitor.visitObject("Class loader parent:");
- visitor.visitObject(classLoaderParentString);
- super.accept(visitor);
- }
-
- public boolean isLoadtimeWeaving() {
- return true;
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/model/AsmRelationshipProvider.java b/weaver/src/org/aspectj/weaver/model/AsmRelationshipProvider.java
deleted file mode 100644
index 5801397a8..000000000
--- a/weaver/src/org/aspectj/weaver/model/AsmRelationshipProvider.java
+++ /dev/null
@@ -1,1133 +0,0 @@
-/* *******************************************************************
- * 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.model;
-
-import java.io.File;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-import org.aspectj.asm.AsmManager;
-import org.aspectj.asm.IHierarchy;
-import org.aspectj.asm.IProgramElement;
-import org.aspectj.asm.IRelationship;
-import org.aspectj.asm.IRelationshipMap;
-import org.aspectj.asm.internal.HandleProviderDelimiter;
-import org.aspectj.asm.internal.ProgramElement;
-import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.bridge.SourceLocation;
-import org.aspectj.weaver.Advice;
-import org.aspectj.weaver.AdviceKind;
-import org.aspectj.weaver.Checker;
-import org.aspectj.weaver.Lint;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.NewParentTypeMunger;
-import org.aspectj.weaver.ReferenceType;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedPointcutDefinition;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.ResolvedTypeMunger;
-import org.aspectj.weaver.ResolvedTypeMunger.Kind;
-import org.aspectj.weaver.Shadow;
-import org.aspectj.weaver.ShadowMunger;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.World;
-import org.aspectj.weaver.bcel.BcelShadow;
-import org.aspectj.weaver.bcel.BcelTypeMunger;
-import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
-import org.aspectj.weaver.patterns.DeclareParents;
-import org.aspectj.weaver.patterns.Pointcut;
-import org.aspectj.weaver.patterns.TypePatternList;
-
-public class AsmRelationshipProvider {
-
- public static final String ADVISES = "advises";
- public static final String ADVISED_BY = "advised by";
- public static final String DECLARES_ON = "declares on";
- public static final String DECLAREDY_BY = "declared by";
- public static final String SOFTENS = "softens";
- public static final String SOFTENED_BY = "softened by";
- public static final String MATCHED_BY = "matched by";
- public static final String MATCHES_DECLARE = "matches declare";
- public static final String INTER_TYPE_DECLARES = "declared on";
- public static final String INTER_TYPE_DECLARED_BY = "aspect declarations";
-
- public static final String ANNOTATES = "annotates";
- public static final String ANNOTATED_BY = "annotated by";
-
- // public static final String REMOVES_ANNOTATION = "removes annotation";
- // public static final String ANNOTATION_REMOVED_BY = "annotated removed by";
-
- /**
- * Add a relationship for a declare error or declare warning
- */
- public static void addDeclareErrorOrWarningRelationship(AsmManager model, Shadow affectedShadow, Checker deow) {
- if (model == null) {
- return;
- }
- if (affectedShadow.getSourceLocation() == null || deow.getSourceLocation() == null) {
- return;
- }
-
- if (World.createInjarHierarchy) {
- createHierarchyForBinaryAspect(model, deow);
- }
-
- IProgramElement targetNode = getNode(model, affectedShadow);
- if (targetNode == null) {
- return;
- }
- String targetHandle = targetNode.getHandleIdentifier();
- if (targetHandle == null) {
- return;
- }
-
- IProgramElement sourceNode = model.getHierarchy().findElementForSourceLine(deow.getSourceLocation());
- String sourceHandle = sourceNode.getHandleIdentifier();
- if (sourceHandle == null) {
- return;
- }
-
- IRelationshipMap relmap = model.getRelationshipMap();
- IRelationship foreward = relmap.get(sourceHandle, IRelationship.Kind.DECLARE, MATCHED_BY, false, true);
- foreward.addTarget(targetHandle);
-
- IRelationship back = relmap.get(targetHandle, IRelationship.Kind.DECLARE, MATCHES_DECLARE, false, true);
- if (back != null && back.getTargets() != null) {
- back.addTarget(sourceHandle);
- }
- if (sourceNode.getSourceLocation() != null) {
- model.addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile());
- }
- }
-
- private static boolean isMixinRelated(ResolvedTypeMunger typeTransformer) {
- Kind kind = typeTransformer.getKind();
- return kind == ResolvedTypeMunger.MethodDelegate2 || kind == ResolvedTypeMunger.FieldHost
- || (kind == ResolvedTypeMunger.Parent && ((NewParentTypeMunger) typeTransformer).isMixin());
- }
-
- /**
- * Add a relationship for a type transformation (declare parents, intertype method declaration, declare annotation on type).
- */
- public static void addRelationship(AsmManager model, ResolvedType onType, ResolvedTypeMunger typeTransformer,
- ResolvedType originatingAspect) {
- if (model == null) {
- return;
- }
-
- if (World.createInjarHierarchy && isBinaryAspect(originatingAspect)) {
- createHierarchy(model, typeTransformer, originatingAspect);
- }
-
- if (originatingAspect.getSourceLocation() != null) {
- String sourceHandle = "";
- IProgramElement sourceNode = null;
- if (typeTransformer.getSourceLocation() != null && typeTransformer.getSourceLocation().getOffset() != -1
- && !isMixinRelated(typeTransformer)) {
- sourceNode = model.getHierarchy().findElementForType(originatingAspect.getPackageName(),
- originatingAspect.getClassName());
- IProgramElement closer = model.getHierarchy().findCloserMatchForLineNumber(sourceNode,
- typeTransformer.getSourceLocation().getLine());
- if (closer != null) {
- sourceNode = closer;
- }
- if (sourceNode == null) {
- // This can be caused by the aspect defining the type munger actually being on the classpath and not the
- // inpath or aspectpath. Rather than NPE at the next line, let's have another go at faulting it in.
- // This inner loop is a small duplicate of the outer loop that attempts to find something closer than
- // the type declaration
- if (World.createInjarHierarchy) {
- createHierarchy(model, typeTransformer, originatingAspect);
- if (typeTransformer.getSourceLocation() != null && typeTransformer.getSourceLocation().getOffset() != -1
- && !isMixinRelated(typeTransformer)) {
- sourceNode = model.getHierarchy().findElementForType(originatingAspect.getPackageName(),
- originatingAspect.getClassName());
- IProgramElement closer2 = model.getHierarchy().findCloserMatchForLineNumber(sourceNode,
- typeTransformer.getSourceLocation().getLine());
- if (closer2 != null) {
- sourceNode = closer2;
- }
- } else {
- sourceNode = model.getHierarchy().findElementForType(originatingAspect.getPackageName(),
- originatingAspect.getClassName());
- }
- }
- }
- sourceHandle = sourceNode.getHandleIdentifier();
- } else {
- sourceNode = model.getHierarchy().findElementForType(originatingAspect.getPackageName(),
- originatingAspect.getClassName());
- // sourceNode =
- // asm.getHierarchy().findElementForSourceLine(originatingAspect
- // .getSourceLocation());
- sourceHandle = sourceNode.getHandleIdentifier();
- }
- // sourceNode =
- // asm.getHierarchy().findElementForType(originatingAspect
- // .getPackageName(),
- // originatingAspect.getClassName());
- // // sourceNode =
- // asm.getHierarchy().findElementForSourceLine(munger
- // .getSourceLocation());
- // sourceHandle =
- // asm.getHandleProvider().createHandleIdentifier(sourceNode);
- if (sourceHandle == null) {
- return;
- }
- String targetHandle = findOrFakeUpNode(model, onType);
- if (targetHandle == null) {
- return;
- }
- IRelationshipMap mapper = model.getRelationshipMap();
- IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES, false,
- true);
- foreward.addTarget(targetHandle);
-
- IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARED_BY, false,
- true);
- back.addTarget(sourceHandle);
- if (sourceNode != null && sourceNode.getSourceLocation() != null) {
- // May have been a bug in the compiled aspect - so it didn't get put in the model
- model.addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile());
- }
- }
- }
-
- private static String findOrFakeUpNode(AsmManager model, ResolvedType onType) {
- IHierarchy hierarchy = model.getHierarchy();
- ISourceLocation sourceLocation = onType.getSourceLocation();
- String canonicalFilePath = model.getCanonicalFilePath(sourceLocation.getSourceFile());
- int lineNumber = sourceLocation.getLine();
- // Find the relevant source file node first
- IProgramElement node = hierarchy.findNodeForSourceFile(hierarchy.getRoot(), canonicalFilePath);
- if (node == null) {
- // Does not exist in the model - probably an inpath
- String bpath = onType.getBinaryPath();
- if (bpath == null) {
- return model.getHandleProvider().createHandleIdentifier(createFileStructureNode(model, canonicalFilePath));
- } else {
- IProgramElement programElement = model.getHierarchy().getRoot();
- // =Foo/,<g(G.class[G
- StringBuffer phantomHandle = new StringBuffer();
-
- // =Foo
- phantomHandle.append(programElement.getHandleIdentifier());
-
- // /, - the comma is a 'well defined char' that means inpath
- phantomHandle.append(HandleProviderDelimiter.PACKAGEFRAGMENTROOT.getDelimiter()).append(
- HandleProviderDelimiter.PHANTOM.getDelimiter());
-
- int pos = bpath.indexOf('!');
- if (pos != -1) {
- // jar or dir
- String jarPath = bpath.substring(0, pos);
- String element = model.getHandleElementForInpath(jarPath);
- if (element != null) {
- phantomHandle.append(element);
- }
- }
-
- // <g
- String packageName = onType.getPackageName();
- phantomHandle.append(HandleProviderDelimiter.PACKAGEFRAGMENT.getDelimiter()).append(packageName);
-
- // (G.class
- // could fix the binary path to only be blah.class bit
- int dotClassPosition = bpath.lastIndexOf(".class");// what to do if -1
- if (dotClassPosition == -1) {
- phantomHandle.append(HandleProviderDelimiter.CLASSFILE.getDelimiter()).append("UNKNOWN.class");
- } else {
- int startPosition = dotClassPosition;
- char ch;
- while (startPosition > 0 && ((ch = bpath.charAt(startPosition)) != '/' && ch != '\\' && ch != '!')) {
- startPosition--;
- }
- String classFile = bpath.substring(startPosition + 1, dotClassPosition + 6);
- phantomHandle.append(HandleProviderDelimiter.CLASSFILE.getDelimiter()).append(classFile);
- }
-
- // [G
- phantomHandle.append(HandleProviderDelimiter.TYPE.getDelimiter()).append(onType.getClassName());
-
- return phantomHandle.toString();
- }
- } else {
- // Check if there is a more accurate child node of that source file node:
- IProgramElement closernode = hierarchy.findCloserMatchForLineNumber(node, lineNumber);
- if (closernode == null) {
- return node.getHandleIdentifier();
- } else {
- return closernode.getHandleIdentifier();
- }
- }
-
- }
-
- public static IProgramElement createFileStructureNode(AsmManager asm, String sourceFilePath) {
- // SourceFilePath might have originated on windows on linux...
- int lastSlash = sourceFilePath.lastIndexOf('\\');
- if (lastSlash == -1) {
- lastSlash = sourceFilePath.lastIndexOf('/');
- }
- // '!' is used like in URLs "c:/blahblah/X.jar!a/b.class"
- int i = sourceFilePath.lastIndexOf('!');
- int j = sourceFilePath.indexOf(".class");
- if (i > lastSlash && i != -1 && j != -1) {
- // we are a binary aspect in the default package
- lastSlash = i;
- }
- String fileName = sourceFilePath.substring(lastSlash + 1);
- IProgramElement fileNode = new ProgramElement(asm, fileName, IProgramElement.Kind.FILE_JAVA, new SourceLocation(new File(
- sourceFilePath), 1, 1), 0, null, null);
- // fileNode.setSourceLocation();
- fileNode.addChild(IHierarchy.NO_STRUCTURE);
- return fileNode;
- }
-
- private static boolean isBinaryAspect(ResolvedType aspect) {
- return aspect.getBinaryPath() != null;
- }
-
- /**
- * Returns the binarySourceLocation for the given sourcelocation. This isn't cached because it's used when faulting in the
- * binary nodes and is called with ISourceLocations for all advice, pointcuts and deows contained within the
- * resolvedDeclaringAspect.
- */
- private static ISourceLocation getBinarySourceLocation(ResolvedType aspect, ISourceLocation sl) {
- if (sl == null) {
- return null;
- }
- String sourceFileName = null;
- if (aspect instanceof ReferenceType) {
- String s = ((ReferenceType) aspect).getDelegate().getSourcefilename();
- int i = s.lastIndexOf('/');
- if (i != -1) {
- sourceFileName = s.substring(i + 1);
- } else {
- sourceFileName = s;
- }
- }
- ISourceLocation sLoc = new SourceLocation(getBinaryFile(aspect), sl.getLine(), sl.getEndLine(),
- ((sl.getColumn() == 0) ? ISourceLocation.NO_COLUMN : sl.getColumn()), sl.getContext(), sourceFileName);
- return sLoc;
- }
-
- private static ISourceLocation createSourceLocation(String sourcefilename, ResolvedType aspect, ISourceLocation sl) {
- ISourceLocation sLoc = new SourceLocation(getBinaryFile(aspect), sl.getLine(), sl.getEndLine(),
- ((sl.getColumn() == 0) ? ISourceLocation.NO_COLUMN : sl.getColumn()), sl.getContext(), sourcefilename);
- return sLoc;
- }
-
- private static String getSourceFileName(ResolvedType aspect) {
- String sourceFileName = null;
- if (aspect instanceof ReferenceType) {
- String s = ((ReferenceType) aspect).getDelegate().getSourcefilename();
- int i = s.lastIndexOf('/');
- if (i != -1) {
- sourceFileName = s.substring(i + 1);
- } else {
- sourceFileName = s;
- }
- }
- return sourceFileName;
- }
-
- /**
- * Returns the File with pathname to the class file, for example either C:\temp
- * \ajcSandbox\workspace\ajcTest16957.tmp\simple.jar!pkg\BinaryAspect.class if the class file is in a jar file, or
- * C:\temp\ajcSandbox\workspace\ajcTest16957.tmp!pkg\BinaryAspect.class if the class file is in a directory
- */
- private static File getBinaryFile(ResolvedType aspect) {
- String s = aspect.getBinaryPath();
- File f = aspect.getSourceLocation().getSourceFile();
- // Replace the source file suffix with .class
- int i = f.getPath().lastIndexOf('.');
- String path = null;
- if (i != -1) {
- path = f.getPath().substring(0, i) + ".class";
- } else {
- path = f.getPath() + ".class";
- }
- return new File(s + "!" + path);
- }
-
- /**
- * Create a basic hierarchy to represent an aspect only available in binary (from the aspectpath).
- */
- private static void createHierarchy(AsmManager model, ResolvedTypeMunger typeTransformer, ResolvedType aspect) {
- // assert aspect != null;
-
- // Check if already defined in the model
- // IProgramElement filenode =
- // model.getHierarchy().findElementForType(aspect.getPackageName(),
- // aspect.getClassName());
- // SourceLine(typeTransformer.getSourceLocation());
- IProgramElement filenode = model.getHierarchy().findElementForSourceLine(typeTransformer.getSourceLocation());
- if (filenode == null) {
- if (typeTransformer.getKind() == ResolvedTypeMunger.MethodDelegate2
- || typeTransformer.getKind() == ResolvedTypeMunger.FieldHost) {
- // not yet faulting these in
- return;
- }
- }
- // the call to findElementForSourceLine(ISourceLocation) returns a file
- // node
- // if it can't find a node in the hierarchy for the given
- // sourcelocation.
- // Therefore, if this is returned, we know we can't find one and have to
- // // continue to fault in the model.
- // if (filenode != null) { //
- if (!filenode.getKind().equals(IProgramElement.Kind.FILE_JAVA)) {
- return;
- }
-
- // create the class file node
- ISourceLocation binLocation = getBinarySourceLocation(aspect, aspect.getSourceLocation());
- String f = getBinaryFile(aspect).getName();
- IProgramElement classFileNode = new ProgramElement(model, f, IProgramElement.Kind.FILE, binLocation, 0, null, null);
-
- // create package ipe if one exists....
- IProgramElement root = model.getHierarchy().getRoot();
- IProgramElement binaries = model.getHierarchy().findElementForLabel(root, IProgramElement.Kind.SOURCE_FOLDER, "binaries");
- if (binaries == null) {
- binaries = new ProgramElement(model, "binaries", IProgramElement.Kind.SOURCE_FOLDER, new ArrayList<IProgramElement>());
- root.addChild(binaries);
- }
- // if (aspect.getPackageName() != null) {
- String packagename = aspect.getPackageName() == null ? "" : aspect.getPackageName();
- // check that there doesn't already exist a node with this name
- IProgramElement pkgNode = model.getHierarchy().findElementForLabel(binaries, IProgramElement.Kind.PACKAGE, packagename);
- // note packages themselves have no source location
- if (pkgNode == null) {
- pkgNode = new ProgramElement(model, packagename, IProgramElement.Kind.PACKAGE, new ArrayList<IProgramElement>());
- binaries.addChild(pkgNode);
- pkgNode.addChild(classFileNode);
- } else {
- // need to add it first otherwise the handle for classFileNode
- // may not be generated correctly if it uses information from
- // it's parent node
- pkgNode.addChild(classFileNode);
- for (IProgramElement element: pkgNode.getChildren()) {
- if (!element.equals(classFileNode) && element.getHandleIdentifier().equals(classFileNode.getHandleIdentifier())) {
- // already added the classfile so have already
- // added the structure for this aspect
- pkgNode.removeChild(classFileNode);
- return;
- }
- }
- }
- // } else {
- // // need to add it first otherwise the handle for classFileNode
- // // may not be generated correctly if it uses information from
- // // it's parent node
- // root.addChild(classFileNode);
- // for (Iterator iter = root.getChildren().iterator(); iter.hasNext();)
- // {
- // IProgramElement element = (IProgramElement) iter.next();
- // if (!element.equals(classFileNode) &&
- // element.getHandleIdentifier().equals
- // (classFileNode.getHandleIdentifier())) {
- // // already added the sourcefile so have already
- // // added the structure for this aspect
- // root.removeChild(classFileNode);
- // return;
- // }
- // }
- // }
-
- // add and create empty import declaration ipe
- // no import container for binary type - 265693
- // classFileNode.addChild(new ProgramElement(model, "import declarations", IProgramElement.Kind.IMPORT_REFERENCE, null, 0,
- // null, null));
-
- // add and create aspect ipe
- IProgramElement aspectNode = new ProgramElement(model, aspect.getSimpleName(), IProgramElement.Kind.ASPECT,
- getBinarySourceLocation(aspect, aspect.getSourceLocation()), aspect.getModifiers(), null, null);
- classFileNode.addChild(aspectNode);
-
- addChildNodes(model, aspect, aspectNode, aspect.getDeclaredPointcuts());
-
- addChildNodes(model, aspect, aspectNode, aspect.getDeclaredAdvice());
- addChildNodes(model, aspect, aspectNode, aspect.getDeclares());
- addChildNodes(model, aspect, aspectNode, aspect.getTypeMungers());
- }
-
- /**
- * Adds a declare annotation relationship, sometimes entities don't have source locs (methods/fields) so use other variants of
- * this method if that is the case as they will look the entities up in the structure model.
- */
- public static void addDeclareAnnotationRelationship(AsmManager model, ISourceLocation declareAnnotationLocation,
- ISourceLocation annotatedLocation, boolean isRemove) {
- if (model == null) {
- return;
- }
-
- IProgramElement sourceNode = model.getHierarchy().findElementForSourceLine(declareAnnotationLocation);
- String sourceHandle = sourceNode.getHandleIdentifier();
- if (sourceHandle == null) {
- return;
- }
-
- IProgramElement targetNode = model.getHierarchy().findElementForSourceLine(annotatedLocation);
- String targetHandle = targetNode.getHandleIdentifier();
- if (targetHandle == null) {
- return;
- }
-
- IRelationshipMap mapper = model.getRelationshipMap();
- // if (isRemove) {
- // IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, REMOVES_ANNOTATION, false,
- // true);
- // foreward.addTarget(targetHandle);
- //
- // IRelationship back = mapper
- // .get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATION_REMOVED_BY, false, true);
- // back.addTarget(sourceHandle);
- // if (sourceNode.getSourceLocation() != null) {
- // model.addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile());
- // }
- // } else {
- IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true);
- foreward.addTarget(targetHandle);
-
- IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, true);
- back.addTarget(sourceHandle);
- if (sourceNode.getSourceLocation() != null) {
- model.addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile());
- }
- // }
- }
-
- /**
- * Creates the hierarchy for binary aspects
- */
- public static void createHierarchyForBinaryAspect(AsmManager asm, ShadowMunger munger) {
- if (!munger.isBinary()) {
- return;
- }
-
- IProgramElement sourceFileNode = asm.getHierarchy().findElementForSourceLine(munger.getSourceLocation());
- // the call to findElementForSourceLine(ISourceLocation) returns a file
- // node if it can't find a node in the hierarchy for the given sourcelocation.
- // Therefore, if this is returned, we know we can't find one and have to
- // continue to fault in the model.
- if (!sourceFileNode.getKind().equals(IProgramElement.Kind.FILE_JAVA)) {
- return;
- }
-
- ResolvedType aspect = munger.getDeclaringType();
-
- // create the class file node
- IProgramElement classFileNode = new ProgramElement(asm, sourceFileNode.getName(), IProgramElement.Kind.FILE,
- munger.getBinarySourceLocation(aspect.getSourceLocation()), 0, null, null);
-
- // create package ipe if one exists....
- IProgramElement root = asm.getHierarchy().getRoot();
- IProgramElement binaries = asm.getHierarchy().findElementForLabel(root, IProgramElement.Kind.SOURCE_FOLDER, "binaries");
- if (binaries == null) {
- binaries = new ProgramElement(asm, "binaries", IProgramElement.Kind.SOURCE_FOLDER, new ArrayList<IProgramElement>());
- root.addChild(binaries);
- }
- // if (aspect.getPackageName() != null) {
- String packagename = aspect.getPackageName() == null ? "" : aspect.getPackageName();
- // check that there doesn't already exist a node with this name
- IProgramElement pkgNode = asm.getHierarchy().findElementForLabel(binaries, IProgramElement.Kind.PACKAGE, packagename);
- // note packages themselves have no source location
- if (pkgNode == null) {
- pkgNode = new ProgramElement(asm, packagename, IProgramElement.Kind.PACKAGE, new ArrayList<IProgramElement>());
- binaries.addChild(pkgNode);
- pkgNode.addChild(classFileNode);
- } else {
- // need to add it first otherwise the handle for classFileNode
- // may not be generated correctly if it uses information from
- // it's parent node
- pkgNode.addChild(classFileNode);
- for (IProgramElement element: pkgNode.getChildren()) {
- if (!element.equals(classFileNode) && element.getHandleIdentifier().equals(classFileNode.getHandleIdentifier())) {
- // already added the classfile so have already
- // added the structure for this aspect
- pkgNode.removeChild(classFileNode);
- return;
- }
- }
- }
- // } else {
- // // need to add it first otherwise the handle for classFileNode
- // // may not be generated correctly if it uses information from
- // // it's parent node
- // root.addChild(classFileNode);
- // for (Iterator iter = root.getChildren().iterator(); iter.hasNext();)
- // {
- // IProgramElement element = (IProgramElement) iter.next();
- // if (!element.equals(classFileNode) &&
- // element.getHandleIdentifier().equals
- // (classFileNode.getHandleIdentifier())) {
- // // already added the sourcefile so have already
- // // added the structure for this aspect
- // root.removeChild(classFileNode);
- // return;
- // }
- // }
- // }
-
- // add and create empty import declaration ipe
- // classFileNode.addChild(new ProgramElement(asm, "import declarations", IProgramElement.Kind.IMPORT_REFERENCE, null, 0,
- // null,
- // null));
-
- // add and create aspect ipe
- IProgramElement aspectNode = new ProgramElement(asm, aspect.getSimpleName(), IProgramElement.Kind.ASPECT,
- munger.getBinarySourceLocation(aspect.getSourceLocation()), aspect.getModifiers(), null, null);
- classFileNode.addChild(aspectNode);
-
- String sourcefilename = getSourceFileName(aspect);
- addPointcuts(asm, sourcefilename, aspect, aspectNode, aspect.getDeclaredPointcuts());
- addChildNodes(asm, aspect, aspectNode, aspect.getDeclaredAdvice());
- addChildNodes(asm, aspect, aspectNode, aspect.getDeclares());
- addChildNodes(asm, aspect, aspectNode, aspect.getTypeMungers());
-
- }
-
- private static void addPointcuts(AsmManager model, String sourcefilename, ResolvedType aspect,
- IProgramElement containingAspect, ResolvedMember[] pointcuts) {
- for (int i = 0; i < pointcuts.length; i++) {
- ResolvedMember pointcut = pointcuts[i];
- if (pointcut instanceof ResolvedPointcutDefinition) {
- ResolvedPointcutDefinition rpcd = (ResolvedPointcutDefinition) pointcut;
- Pointcut p = rpcd.getPointcut();
- ISourceLocation sLoc = (p == null ? null : p.getSourceLocation());
- if (sLoc == null) {
- sLoc = rpcd.getSourceLocation();
- }
- ISourceLocation pointcutLocation = (sLoc == null ? null : createSourceLocation(sourcefilename, aspect, sLoc));
- ProgramElement pointcutElement = new ProgramElement(model, pointcut.getName(), IProgramElement.Kind.POINTCUT,
- pointcutLocation, pointcut.getModifiers(), NO_COMMENT, Collections.<IProgramElement>emptyList());
- containingAspect.addChild(pointcutElement);
- }
- }
- }
-
- private static final String NO_COMMENT = null;
-
- private static void addChildNodes(AsmManager asm, ResolvedType aspect, IProgramElement parent, ResolvedMember[] children) {
- for (int i = 0; i < children.length; i++) {
- ResolvedMember pcd = children[i];
- if (pcd instanceof ResolvedPointcutDefinition) {
- ResolvedPointcutDefinition rpcd = (ResolvedPointcutDefinition) pcd;
- Pointcut p = rpcd.getPointcut();
- ISourceLocation sLoc = (p == null ? null : p.getSourceLocation());
- if (sLoc == null) {
- sLoc = rpcd.getSourceLocation();
- }
- parent.addChild(new ProgramElement(asm, pcd.getName(), IProgramElement.Kind.POINTCUT, getBinarySourceLocation(
- aspect, sLoc), pcd.getModifiers(), null, Collections.<IProgramElement>emptyList()));
- }
- }
- }
-
- private static void addChildNodes(AsmManager asm, ResolvedType aspect, IProgramElement parent, Collection<?> children) {
- int deCtr = 1;
- int dwCtr = 1;
- for (Object element: children) {
- if (element instanceof DeclareErrorOrWarning) {
- DeclareErrorOrWarning decl = (DeclareErrorOrWarning) element;
- int counter = 0;
- if (decl.isError()) {
- counter = deCtr++;
- } else {
- counter = dwCtr++;
- }
- parent.addChild(createDeclareErrorOrWarningChild(asm, aspect, decl, counter));
- } else if (element instanceof Advice) {
- Advice advice = (Advice) element;
- parent.addChild(createAdviceChild(asm, advice));
- } else if (element instanceof DeclareParents) {
- parent.addChild(createDeclareParentsChild(asm, (DeclareParents) element));
- } else if (element instanceof BcelTypeMunger) {
- IProgramElement newChild = createIntertypeDeclaredChild(asm, aspect, (BcelTypeMunger) element);
- // newChild==null means it is something that could not be handled by createIntertypeDeclaredChild()
- if (newChild != null) {
- parent.addChild(newChild);
- }
- }
- }
- }
-
- // private static IProgramElement
- // createDeclareErrorOrWarningChild(AsmManager asm, ShadowMunger munger,
- // DeclareErrorOrWarning decl, int count) {
- // IProgramElement deowNode = new ProgramElement(asm, decl.getName(),
- // decl.isError() ? IProgramElement.Kind.DECLARE_ERROR
- // : IProgramElement.Kind.DECLARE_WARNING,
- // munger.getBinarySourceLocation(decl.getSourceLocation()), decl
- // .getDeclaringType().getModifiers(), null, null);
- // deowNode.setDetails("\"" +
- // AsmRelationshipUtils.genDeclareMessage(decl.getMessage()) + "\"");
- // if (count != -1) {
- // deowNode.setBytecodeName(decl.getName() + "_" + count);
- // }
- // return deowNode;
- // }
-
- private static IProgramElement createDeclareErrorOrWarningChild(AsmManager model, ResolvedType aspect,
- DeclareErrorOrWarning decl, int count) {
- IProgramElement deowNode = new ProgramElement(model, decl.getName(), decl.isError() ? IProgramElement.Kind.DECLARE_ERROR
- : IProgramElement.Kind.DECLARE_WARNING, getBinarySourceLocation(aspect, decl.getSourceLocation()), decl
- .getDeclaringType().getModifiers(), null, null);
- deowNode.setDetails("\"" + AsmRelationshipUtils.genDeclareMessage(decl.getMessage()) + "\"");
- if (count != -1) {
- deowNode.setBytecodeName(decl.getName() + "_" + count);
- }
- return deowNode;
- }
-
- private static IProgramElement createAdviceChild(AsmManager model, Advice advice) {
- IProgramElement adviceNode = new ProgramElement(model, advice.getKind().getName(), IProgramElement.Kind.ADVICE,
- advice.getBinarySourceLocation(advice.getSourceLocation()), advice.getSignature().getModifiers(), null,
- Collections.<IProgramElement>emptyList());
- adviceNode.setDetails(AsmRelationshipUtils.genPointcutDetails(advice.getPointcut()));
- adviceNode.setBytecodeName(advice.getSignature().getName());
- return adviceNode;
- }
-
- /**
- * Half baked implementation - will need completing if we go down this route rather than replacing it all for binary aspects.
- * Doesn't attempt to get parameter names correct - they may have been lost during (de)serialization of the munger, but the
- * member could still be located so they might be retrievable.
- */
- private static IProgramElement createIntertypeDeclaredChild(AsmManager model, ResolvedType aspect, BcelTypeMunger itd) {
- ResolvedTypeMunger rtMunger = itd.getMunger();
-
- ResolvedMember sig = rtMunger.getSignature();
- Kind kind = rtMunger.getKind();
- if (kind == ResolvedTypeMunger.Field) { // ITD FIELD
- // String name = rtMunger.getSignature().toString();
- String name = sig.getDeclaringType().getClassName() + "." + sig.getName();
- if (name.indexOf("$") != -1) {
- name = name.substring(name.indexOf("$") + 1);
- }
- IProgramElement pe = new ProgramElement(model, name, IProgramElement.Kind.INTER_TYPE_FIELD, getBinarySourceLocation(
- aspect, itd.getSourceLocation()), rtMunger.getSignature().getModifiers(), null, Collections.<IProgramElement>emptyList());
- pe.setCorrespondingType(sig.getReturnType().getName());
- return pe;
- } else if (kind == ResolvedTypeMunger.Method) { // ITD
- // METHOD
- String name = sig.getDeclaringType().getClassName() + "." + sig.getName();
- if (name.indexOf("$") != -1) {
- name = name.substring(name.indexOf("$") + 1);
- }
- IProgramElement pe = new ProgramElement(model, name, IProgramElement.Kind.INTER_TYPE_METHOD, getBinarySourceLocation(
- aspect, itd.getSourceLocation()), rtMunger.getSignature().getModifiers(), null, Collections.<IProgramElement>emptyList());
- setParams(pe, sig);
- return pe;
- } else if (kind == ResolvedTypeMunger.Constructor) {
- String name = sig.getDeclaringType().getClassName() + "." + sig.getDeclaringType().getClassName();
- if (name.indexOf("$") != -1) {
- name = name.substring(name.indexOf("$") + 1);
- }
- IProgramElement pe = new ProgramElement(model, name, IProgramElement.Kind.INTER_TYPE_CONSTRUCTOR,
- getBinarySourceLocation(aspect, itd.getSourceLocation()), rtMunger.getSignature().getModifiers(), null,
- Collections.<IProgramElement>emptyList());
- setParams(pe, sig);
- return pe;
- // } else if (kind == ResolvedTypeMunger.MethodDelegate2) {
- // String name = sig.getDeclaringType().getClassName() + "." + sig.getName();
- // if (name.indexOf("$") != -1) {
- // name = name.substring(name.indexOf("$") + 1);
- // }
- // IProgramElement pe = new ProgramElement(model, name, IProgramElement.Kind.INTER_TYPE_METHOD, getBinarySourceLocation(
- // aspect, itd.getSourceLocation()), rtMunger.getSignature().getModifiers(), null, Collections.EMPTY_LIST);
- // setParams(pe, sig);
- // return pe;
- }
- // other cases ignored for now
- return null;
- }
-
- private static void setParams(IProgramElement pe, ResolvedMember sig) {
- // do it for itds too
- UnresolvedType[] ts = sig.getParameterTypes();
- pe.setParameterNames(Collections.<String>emptyList());
- // TODO should be doing param names?
- if (ts == null) {
- pe.setParameterSignatures(Collections.<char[]>emptyList(), Collections.<String>emptyList());
- } else {
- List<char[]> paramSigs = new ArrayList<char[]>();
- for (int i = 0; i < ts.length; i++) {
- paramSigs.add(ts[i].getSignature().toCharArray());
- }
- pe.setParameterSignatures(paramSigs, Collections.<String>emptyList());
- }
- pe.setCorrespondingType(sig.getReturnType().getName());
- }
-
- private static IProgramElement createDeclareParentsChild(AsmManager model, DeclareParents decp) {
- IProgramElement decpElement = new ProgramElement(model, "declare parents", IProgramElement.Kind.DECLARE_PARENTS,
- getBinarySourceLocation(decp.getDeclaringType(), decp.getSourceLocation()), Modifier.PUBLIC, null,
- Collections.<IProgramElement>emptyList());
- setParentTypesOnDeclareParentsNode(decp, decpElement);
- return decpElement;
- }
-
- private static void setParentTypesOnDeclareParentsNode(DeclareParents decp, IProgramElement decpElement) {
- TypePatternList tpl = decp.getParents();
- List<String> parents = new ArrayList<String>();
- for (int i = 0; i < tpl.size(); i++) {
- parents.add(tpl.get(i).getExactType().getName().replaceAll("\\$", "."));
- }
- decpElement.setParentTypes(parents);
- }
-
- public static String getHandle(AsmManager asm, Advice advice) {
- if (null == advice.handle) {
- ISourceLocation sl = advice.getSourceLocation();
- if (sl != null) {
- IProgramElement ipe = asm.getHierarchy().findElementForSourceLine(sl);
- advice.handle = ipe.getHandleIdentifier();
- }
- }
- return advice.handle;
- }
-
- public static void addAdvisedRelationship(AsmManager model, Shadow matchedShadow, ShadowMunger munger) {
- if (model == null) {
- return;
- }
-
- if (munger instanceof Advice) {
- Advice advice = (Advice) munger;
-
- if (advice.getKind().isPerEntry() || advice.getKind().isCflow()) {
- // TODO: might want to show these in the future
- return;
- }
-
- if (World.createInjarHierarchy) {
- createHierarchyForBinaryAspect(model, advice);
- }
-
- IRelationshipMap mapper = model.getRelationshipMap();
- IProgramElement targetNode = getNode(model, matchedShadow);
- if (targetNode == null) {
- return;
- }
- boolean runtimeTest = advice.hasDynamicTests();
-
- IProgramElement.ExtraInformation extra = new IProgramElement.ExtraInformation();
-
- String adviceHandle = getHandle(model, advice);
- if (adviceHandle == null) {
- return;
- }
-
- extra.setExtraAdviceInformation(advice.getKind().getName());
- IProgramElement adviceElement = model.getHierarchy().findElementForHandle(adviceHandle);
- if (adviceElement != null) {
- adviceElement.setExtraInfo(extra);
- }
- String targetHandle = targetNode.getHandleIdentifier();
- if (advice.getKind().equals(AdviceKind.Softener)) {
- IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.DECLARE_SOFT, SOFTENS, runtimeTest, true);
- if (foreward != null) {
- foreward.addTarget(targetHandle);
- }
-
- IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE, SOFTENED_BY, runtimeTest, true);
- if (back != null) {
- back.addTarget(adviceHandle);
- }
- } else {
- IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.ADVICE, ADVISES, runtimeTest, true);
- if (foreward != null) {
- foreward.addTarget(targetHandle);
- }
-
- IRelationship back = mapper.get(targetHandle, IRelationship.Kind.ADVICE, ADVISED_BY, runtimeTest, true);
- if (back != null) {
- back.addTarget(adviceHandle);
- }
- }
- if (adviceElement.getSourceLocation() != null) {
- model.addAspectInEffectThisBuild(adviceElement.getSourceLocation().getSourceFile());
- }
- }
- }
-
- protected static IProgramElement getNode(AsmManager model, Shadow shadow) {
- Member enclosingMember = shadow.getEnclosingCodeSignature();
- // This variant will not be tricked by ITDs that would report they are
- // in the target type already.
- // This enables us to discover the ITD declaration (in the aspect) and
- // advise it appropriately.
-
- // Have to be smart here, for a code node within an ITD we want to
- // lookup the declaration of the
- // ITD in the aspect in order to add the code node at the right place -
- // and not lookup the
- // ITD as it applies in some target type. Due to the use of
- // effectiveSignature we will find
- // that shadow.getEnclosingCodeSignature() will return a member
- // representing the ITD as it will
- // appear in the target type. So here, we do an extra bit of analysis to
- // make sure we
- // do the right thing in the ITD case.
- IProgramElement enclosingNode = null;
- if (shadow instanceof BcelShadow) {
- Member actualEnclosingMember = ((BcelShadow) shadow).getRealEnclosingCodeSignature();
-
- if (actualEnclosingMember == null) {
- enclosingNode = lookupMember(model.getHierarchy(), shadow.getEnclosingType(), enclosingMember);
- } else {
- UnresolvedType type = enclosingMember.getDeclaringType();
- UnresolvedType actualType = actualEnclosingMember.getDeclaringType();
-
- // if these are not the same, it is an ITD and we need to use
- // the latter to lookup
- if (type.equals(actualType)) {
- enclosingNode = lookupMember(model.getHierarchy(), shadow.getEnclosingType(), enclosingMember);
- } else {
- enclosingNode = lookupMember(model.getHierarchy(), shadow.getEnclosingType(), actualEnclosingMember);
- }
- }
- } else {
- enclosingNode = lookupMember(model.getHierarchy(), shadow.getEnclosingType(), enclosingMember);
- }
-
- if (enclosingNode == null) {
- Lint.Kind err = shadow.getIWorld().getLint().shadowNotInStructure;
- if (err.isEnabled()) {
- err.signal(shadow.toString(), shadow.getSourceLocation());
- }
- return null;
- }
-
- Member shadowSig = shadow.getSignature();
- // pr235204
- if (shadow.getKind() == Shadow.MethodCall || shadow.getKind() == Shadow.ConstructorCall
- || !shadowSig.equals(enclosingMember)) {
- IProgramElement bodyNode = findOrCreateCodeNode(model, enclosingNode, shadowSig, shadow);
- return bodyNode;
- } else {
- return enclosingNode;
- }
- }
-
- private static boolean sourceLinesMatch(ISourceLocation location1, ISourceLocation location2) {
- return (location1.getLine() == location2.getLine());
- }
-
- /**
- * Finds or creates a code IProgramElement for the given shadow.
- *
- * The byteCodeName of the created node is set to 'shadowSig.getName() + "!" + counter', eg "println!3". The counter is the
- * occurence count of children within the enclosingNode which have the same name. So, for example, if a method contains two
- * System.out.println statements, the first one will have byteCodeName 'println!1' and the second will have byteCodeName
- * 'println!2'. This is to ensure the two nodes have unique handles when the handles do not depend on sourcelocations.
- *
- * Currently the shadows are examined in the sequence they appear in the source file. This means that the counters are
- * consistent over incremental builds. All aspects are compiled up front and any new aspect created will force a full build.
- * Moreover, if the body of the enclosingShadow is changed, then the model for this is rebuilt from scratch.
- */
- private static IProgramElement findOrCreateCodeNode(AsmManager asm, IProgramElement enclosingNode, Member shadowSig,
- Shadow shadow) {
- for (Iterator it = enclosingNode.getChildren().iterator(); it.hasNext();) {
- IProgramElement node = (IProgramElement) it.next();
- int excl = node.getBytecodeName().lastIndexOf('!');
- if (((excl != -1 && shadowSig.getName().equals(node.getBytecodeName().substring(0, excl))) || shadowSig.getName()
- .equals(node.getBytecodeName()))
- && shadowSig.getSignature().equals(node.getBytecodeSignature())
- && sourceLinesMatch(node.getSourceLocation(), shadow.getSourceLocation())) {
- return node;
- }
- }
-
- ISourceLocation sl = shadow.getSourceLocation();
-
- // XXX why not use shadow file? new SourceLocation(sl.getSourceFile(),
- // sl.getLine()),
- SourceLocation peLoc = new SourceLocation(enclosingNode.getSourceLocation().getSourceFile(), sl.getLine());
- peLoc.setOffset(sl.getOffset());
- IProgramElement peNode = new ProgramElement(asm, shadow.toString(), IProgramElement.Kind.CODE, peLoc, 0, null, null);
-
- // check to see if the enclosing shadow already has children with the
- // same name. If so we want to add a counter to the byteCodeName
- // otherwise
- // we wont get unique handles
- int numberOfChildrenWithThisName = 0;
- for (IProgramElement child: enclosingNode.getChildren()) {
- if (child.getName().equals(shadow.toString())) {
- numberOfChildrenWithThisName++;
- }
- }
- peNode.setBytecodeName(shadowSig.getName() + "!" + String.valueOf(numberOfChildrenWithThisName + 1));
- peNode.setBytecodeSignature(shadowSig.getSignature());
- enclosingNode.addChild(peNode);
- return peNode;
- }
-
- private static IProgramElement lookupMember(IHierarchy model, UnresolvedType declaringType, Member member) {
- IProgramElement typeElement = model.findElementForType(declaringType.getPackageName(), declaringType.getClassName());
- if (typeElement == null) {
- return null;
- }
- for (Iterator it = typeElement.getChildren().iterator(); it.hasNext();) {
- IProgramElement element = (IProgramElement) it.next();
- if (member.getName().equals(element.getBytecodeName()) && member.getSignature().equals(element.getBytecodeSignature())) {
- return element;
- }
- }
- // if we can't find the member, we'll just put it in the class
- return typeElement;
- }
-
- /**
- * Add a relationship for a matching declare annotation method or declare annotation constructor. Locating the method is a messy
- * (for messy read 'fragile') bit of code that could break at any moment but it's working for my simple testcase.
- */
- public static void addDeclareAnnotationMethodRelationship(ISourceLocation sourceLocation, String affectedTypeName,
- ResolvedMember affectedMethod, AsmManager model) {
- if (model == null) {
- return;
- }
-
- String pkg = null;
- String type = affectedTypeName;
- int packageSeparator = affectedTypeName.lastIndexOf(".");
- if (packageSeparator != -1) {
- pkg = affectedTypeName.substring(0, packageSeparator);
- type = affectedTypeName.substring(packageSeparator + 1);
- }
-
- IHierarchy hierarchy = model.getHierarchy();
-
- IProgramElement typeElem = hierarchy.findElementForType(pkg, type);
- if (typeElem == null) {
- return;
- }
- if (!typeElem.getKind().isType()) {
- throw new IllegalStateException("Did not find a type element, found a "+typeElem.getKind()+" element");
- }
-
- StringBuilder parmString = new StringBuilder("(");
- UnresolvedType[] args = affectedMethod.getParameterTypes();
- for (int i = 0; i < args.length; i++) {
- parmString.append(args[i].getName());
- if ((i + 1) < args.length) {
- parmString.append(",");
- }
- }
- parmString.append(")");
- IProgramElement methodElem = null;
-
- if (affectedMethod.getName().startsWith("<init>")) {
- // its a ctor
- methodElem = hierarchy.findElementForSignature(typeElem, IProgramElement.Kind.CONSTRUCTOR, type + parmString);
- if (methodElem == null && args.length == 0) {
- methodElem = typeElem; // assume default ctor
- }
- } else {
- // its a method
- methodElem = hierarchy.findElementForSignature(typeElem, IProgramElement.Kind.METHOD, affectedMethod.getName()
- + parmString);
- }
-
- if (methodElem == null) {
- return;
- }
-
- try {
- String targetHandle = methodElem.getHandleIdentifier();
- if (targetHandle == null) {
- return;
- }
-
- IProgramElement sourceNode = hierarchy.findElementForSourceLine(sourceLocation);
- String sourceHandle = sourceNode.getHandleIdentifier();
- if (sourceHandle == null) {
- return;
- }
-
- IRelationshipMap mapper = model.getRelationshipMap();
- IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true);
- foreward.addTarget(targetHandle);
-
- IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, true);
- back.addTarget(sourceHandle);
- } catch (Throwable t) { // I'm worried about that code above, this will
- // make sure we don't explode if it plays up
- t.printStackTrace(); // I know I know .. but I don't want to lose
- // it!
- }
- }
-
- /**
- * Add a relationship for a matching declare ATfield. Locating the field is trickier than it might seem since we have no line
- * number info for it, we have to dig through the structure model under the fields' type in order to locate it.
- */
- public static void addDeclareAnnotationFieldRelationship(AsmManager model, ISourceLocation declareLocation,
- String affectedTypeName, ResolvedMember affectedFieldName, boolean isRemove) {
- if (model == null) {
- return;
- }
-
- String pkg = null;
- String type = affectedTypeName;
- int packageSeparator = affectedTypeName.lastIndexOf(".");
- if (packageSeparator != -1) {
- pkg = affectedTypeName.substring(0, packageSeparator);
- type = affectedTypeName.substring(packageSeparator + 1);
- }
- IHierarchy hierarchy = model.getHierarchy();
- IProgramElement typeElem = hierarchy.findElementForType(pkg, type);
- if (typeElem == null) {
- return;
- }
-
- IProgramElement fieldElem = hierarchy.findElementForSignature(typeElem, IProgramElement.Kind.FIELD,
- affectedFieldName.getName());
- if (fieldElem == null) {
- return;
- }
-
- String targetHandle = fieldElem.getHandleIdentifier();
- if (targetHandle == null) {
- return;
- }
-
- IProgramElement sourceNode = hierarchy.findElementForSourceLine(declareLocation);
- String sourceHandle = sourceNode.getHandleIdentifier();
- if (sourceHandle == null) {
- return;
- }
-
- IRelationshipMap relmap = model.getRelationshipMap();
- // if (isRemove) {
- // IRelationship foreward = relmap.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, REMOVES_ANNOTATION, false,
- // true);
- // foreward.addTarget(targetHandle);
- // IRelationship back = relmap
- // .get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATION_REMOVED_BY, false, true);
- // back.addTarget(sourceHandle);
- // } else {
- IRelationship foreward = relmap.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true);
- foreward.addTarget(targetHandle);
- IRelationship back = relmap.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, true);
- back.addTarget(sourceHandle);
- // }
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/model/AsmRelationshipUtils.java b/weaver/src/org/aspectj/weaver/model/AsmRelationshipUtils.java
deleted file mode 100644
index f9c9f6ae2..000000000
--- a/weaver/src/org/aspectj/weaver/model/AsmRelationshipUtils.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/********************************************************************
- * Copyright (c) 2006 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: IBM Corporation - initial API and implementation
- * Helen Hawkins - initial version
- *******************************************************************/
-package org.aspectj.weaver.model;
-
-import org.aspectj.weaver.patterns.AndPointcut;
-import org.aspectj.weaver.patterns.OrPointcut;
-import org.aspectj.weaver.patterns.Pointcut;
-import org.aspectj.weaver.patterns.ReferencePointcut;
-
-/**
- * Provides utility methods for generating details for IProgramElements used when creating the model both from source (via
- * AsmElementFormatter.visit(..)) and when filling in the model for binary aspects (via AsmRelationshipProvider bug 145963)
- */
-public class AsmRelationshipUtils {
-
- // public static final String UNDEFINED="<undefined>";
- public static final String DECLARE_PRECEDENCE = "precedence";
- public static final String DECLARE_SOFT = "soft";
- public static final String DECLARE_PARENTS = "parents";
- public static final String DECLARE_WARNING = "warning";
- public static final String DECLARE_ERROR = "error";
- public static final String DECLARE_UNKNONWN = "<unknown declare>";
- public static final String POINTCUT_ABSTRACT = "<abstract pointcut>";
- public static final String POINTCUT_ANONYMOUS = "<anonymous pointcut>";
- public static final String DOUBLE_DOTS = "..";
- public static final int MAX_MESSAGE_LENGTH = 18;
- public static final String DEC_LABEL = "declare";
-
- /**
- * Generates the declare message used in the details, for example if the declare warning statement has message
- * "There should be no printlns" will return 'declare warning: "There should be n.."'
- */
- public static String genDeclareMessage(String message) {
- int length = message.length();
- if (length < MAX_MESSAGE_LENGTH) {
- return message;
- } else {
- return message.substring(0, MAX_MESSAGE_LENGTH - 1) + DOUBLE_DOTS;
- }
- }
-
- /**
- * Generates the pointcut details for the given pointcut, for example an anonymous pointcut will return '<anonymous pointcut>'
- * and a named pointcut called p() will return 'p()..'
- */
- public static String genPointcutDetails(Pointcut pcd) {
- StringBuffer details = new StringBuffer();
- if (pcd instanceof ReferencePointcut) {
- ReferencePointcut rp = (ReferencePointcut) pcd;
- details.append(rp.name).append(DOUBLE_DOTS);
- } else if (pcd instanceof AndPointcut) {
- AndPointcut ap = (AndPointcut) pcd;
- if (ap.getLeft() instanceof ReferencePointcut) {
- details.append(ap.getLeft().toString()).append(DOUBLE_DOTS);
- } else {
- details.append(POINTCUT_ANONYMOUS).append(DOUBLE_DOTS);
- }
- } else if (pcd instanceof OrPointcut) {
- OrPointcut op = (OrPointcut) pcd;
- if (op.getLeft() instanceof ReferencePointcut) {
- details.append(op.getLeft().toString()).append(DOUBLE_DOTS);
- } else {
- details.append(POINTCUT_ANONYMOUS).append(DOUBLE_DOTS);
- }
- } else {
- details.append(POINTCUT_ANONYMOUS);
- }
- return details.toString();
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java b/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java
deleted file mode 100644
index a02400fb0..000000000
--- a/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java
+++ /dev/null
@@ -1,951 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2004 IBM Corporation
- * 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:
- * Matthew Webster, Adrian Colyer, John Kew + Lyor Goldstein (caching)
- * Martin Lippert initial implementation
- * ******************************************************************/
-
-package org.aspectj.weaver.tools;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-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.bridge.AbortException;
-import org.aspectj.bridge.IMessage;
-import org.aspectj.bridge.IMessage.Kind;
-import org.aspectj.bridge.IMessageContext;
-import org.aspectj.bridge.IMessageHandler;
-import org.aspectj.bridge.IMessageHolder;
-import org.aspectj.bridge.Message;
-import org.aspectj.bridge.MessageHandler;
-import org.aspectj.bridge.MessageUtil;
-import org.aspectj.bridge.MessageWriter;
-import org.aspectj.bridge.Version;
-import org.aspectj.bridge.WeaveMessage;
-import org.aspectj.util.FileUtil;
-import org.aspectj.util.LangUtil;
-import org.aspectj.weaver.IClassFileProvider;
-import org.aspectj.weaver.IUnwovenClassFile;
-import org.aspectj.weaver.IWeaveRequestor;
-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.tools.cache.CachedClassEntry;
-import org.aspectj.weaver.tools.cache.CachedClassReference;
-import org.aspectj.weaver.tools.cache.SimpleCache;
-import org.aspectj.weaver.tools.cache.SimpleCacheFactory;
-import org.aspectj.weaver.tools.cache.WeavedClassCache;
-
-// 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 weaving class loader to provide a classpath to be woven by a set of aspects. A callback is supplied to allow a
- * class loader to define classes generated by the compiler during the weaving process.
- * <p>
- * A weaving class loader should create a <code>WeavingAdaptor</code> before any classes are defined, typically during construction.
- * The set of aspects passed to the adaptor is fixed for the lifetime of the adaptor although the classpath can be augmented. A
- * system property can be set to allow verbose weaving messages to be written to the console.
- *
- */
-public class WeavingAdaptor implements IMessageContext {
-
- /**
- * System property used to turn on verbose weaving messages
- */
- public static final String WEAVING_ADAPTOR_VERBOSE = "aj.weaving.verbose";
- public static final String SHOW_WEAVE_INFO_PROPERTY = "org.aspectj.weaver.showWeaveInfo";
- public static final String TRACE_MESSAGES_PROPERTY = "org.aspectj.tracing.messages";
-
- private final static String ASPECTJ_BASE_PACKAGE = "org.aspectj.";
- private final static String PACKAGE_INITIAL_CHARS = ASPECTJ_BASE_PACKAGE.charAt(0) + "sj";
-
- private boolean enabled = false;
- protected boolean verbose = getVerbose();
- protected BcelWorld bcelWorld;
- protected BcelWeaver weaver;
- private IMessageHandler messageHandler;
- private WeavingAdaptorMessageHolder messageHolder;
- private boolean abortOnError = false;
- protected GeneratedClassHandler generatedClassHandler;
- protected Map<String, IUnwovenClassFile> generatedClasses = new HashMap<String, IUnwovenClassFile>();
- public BcelObjectType delegateForCurrentClass; // lazily initialized, should be used to prevent parsing bytecode multiple
- // times
- protected ProtectionDomain activeProtectionDomain;
-
- private boolean haveWarnedOnJavax = false;
- protected WeavedClassCache cache;
-
- 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() {
- }
-
- /**
- * Construct a WeavingAdaptor with a reference to a weaving class loader. The adaptor will automatically search the class loader
- * hierarchy to resolve classes. The adaptor will also search the hierarchy for WeavingClassLoader instances to determine the
- * set of aspects to be used for weaving.
- *
- * @param loader instance of <code>ClassLoader</code>
- */
- public WeavingAdaptor(WeavingClassLoader loader) {
- // System.err.println("? WeavingAdaptor.<init>(" + loader +"," + aspectURLs.length + ")");
- generatedClassHandler = loader;
- init((ClassLoader)loader, getFullClassPath((ClassLoader) loader), getFullAspectPath((ClassLoader) loader/* ,aspectURLs */));
- }
-
- /**
- * Construct a WeavingAdaptor with a reference to a <code>GeneratedClassHandler</code>, a full search path for resolving classes
- * and a complete set of aspects. The search path must include classes loaded by the class loader constructing the
- * WeavingAdaptor and all its parents in the hierarchy.
- *
- * @param handler <code>GeneratedClassHandler</code>
- * @param classURLs the URLs from which to resolve classes
- * @param aspectURLs the aspects used to weave classes defined by this class loader
- */
- public WeavingAdaptor(GeneratedClassHandler handler, URL[] classURLs, URL[] aspectURLs) {
- // System.err.println("? WeavingAdaptor.<init>()");
- generatedClassHandler = handler;
- init(null, FileUtil.makeClasspath(classURLs), FileUtil.makeClasspath(aspectURLs));
- }
-
- protected List<String> getFullClassPath(ClassLoader loader) {
- List<String> list = new LinkedList<String>();
- for (; loader != null; loader = loader.getParent()) {
- if (loader instanceof URLClassLoader) {
- URL[] urls = ((URLClassLoader) loader).getURLs();
- list.addAll(0, FileUtil.makeClasspath(urls));
- } else {
- warn("cannot determine classpath");
- }
- }
- // On Java9 it is possible to fail to find a URLClassLoader from which to derive a suitable classpath
- // For now we can determine it from the java.class.path:
- if (LangUtil.is19VMOrGreater()) {
- list.add(0, LangUtil.getJrtFsFilePath());
- List<String> javaClassPathEntries = makeClasspath(System.getProperty("java.class.path"));
- for (int i=javaClassPathEntries.size()-1;i>=0;i--) {
- String javaClassPathEntry = javaClassPathEntries.get(i);
- if (!list.contains(javaClassPathEntry)) {
- list.add(0,javaClassPathEntry);
- }
- }
- }
- // On Java9 the sun.boot.class.path won't be set. System classes accessible through JRT filesystem
- list.addAll(0, makeClasspath(System.getProperty("sun.boot.class.path")));
- return list;
- }
-
- private List<String> getFullAspectPath(ClassLoader loader) {
- List<String> list = new LinkedList<String>();
- for (; loader != null; loader = loader.getParent()) {
- if (loader instanceof WeavingClassLoader) {
- URL[] urls = ((WeavingClassLoader) loader).getAspectURLs();
- list.addAll(0, FileUtil.makeClasspath(urls));
- }
- }
- return list;
- }
-
- private static boolean getVerbose() {
- try {
- return Boolean.getBoolean(WEAVING_ADAPTOR_VERBOSE);
- } catch (Throwable t) {
- // security exception
- return false;
- }
- }
-
- /**
- * Initialize the WeavingAdapter
- * @param loader ClassLoader used by this adapter; which can be null
- * @param classPath classpath of this adapter
- * @param aspectPath list of aspect paths
- */
- private void init(ClassLoader loader, List<String> classPath, List<String> aspectPath) {
- abortOnError = true;
- createMessageHandler();
-
- info("using classpath: " + classPath);
- info("using aspectpath: " + aspectPath);
-
- bcelWorld = new BcelWorld(classPath, messageHandler, null);
- bcelWorld.setXnoInline(false);
- bcelWorld.getLint().loadDefaultProperties();
- if (LangUtil.is15VMOrGreater()) {
- bcelWorld.setBehaveInJava5Way(true);
- }
-
- weaver = new BcelWeaver(bcelWorld);
- registerAspectLibraries(aspectPath);
- initializeCache(loader, aspectPath, null, getMessageHandler());
- enabled = true;
- }
-
- /**
- * If the cache is enabled, initialize it and swap out the existing classhandler
- * for the caching one -
- *
- * @param loader classloader for this adapter, may be null
- * @param aspects List of strings representing aspects managed by the adapter; these could be urls or classnames
- * @param existingClassHandler current class handler
- * @param myMessageHandler current message handler
- */
- protected void initializeCache(ClassLoader loader, List<String> aspects, GeneratedClassHandler existingClassHandler, IMessageHandler myMessageHandler) {
- if (WeavedClassCache.isEnabled()) {
- cache = WeavedClassCache.createCache(loader, aspects, existingClassHandler, myMessageHandler);
- // Wrap the existing class handler so that any generated classes are also cached
- if (cache != null) {
- this.generatedClassHandler = cache.getCachingClassHandler();
- }
- }
- }
-
-
- protected void createMessageHandler() {
- messageHolder = new WeavingAdaptorMessageHolder(new PrintWriter(System.err));
- messageHandler = messageHolder;
- if (verbose) {
- messageHandler.dontIgnore(IMessage.INFO);
- }
- if (Boolean.getBoolean(SHOW_WEAVE_INFO_PROPERTY)) {
- messageHandler.dontIgnore(IMessage.WEAVEINFO);
- }
- info("AspectJ Weaver Version " + Version.text + " built on " + Version.time_text); //$NON-NLS-1$
- }
-
- protected IMessageHandler getMessageHandler() {
- return messageHandler;
- }
-
- public IMessageHolder getMessageHolder() {
- return messageHolder;
- }
-
- protected void setMessageHandler(IMessageHandler mh) {
- if (mh instanceof ISupportsMessageContext) {
- ISupportsMessageContext smc = (ISupportsMessageContext) mh;
- smc.setMessageContext(this);
- }
- if (mh != messageHolder) {
- messageHolder.setDelegate(mh);
- }
- messageHolder.flushMessages();
- }
-
- protected void disable() {
- if (trace.isTraceEnabled()) {
- trace.enter("disable", this);
- }
-
- enabled = false;
- messageHolder.flushMessages();
-
- if (trace.isTraceEnabled()) {
- trace.exit("disable");
- }
- }
-
- protected void enable() {
- enabled = true;
- messageHolder.flushMessages();
- }
-
- protected boolean isEnabled() {
- return enabled;
- }
-
- /**
- * Appends URL to path used by the WeavingAdptor to resolve classes
- *
- * @param url to be appended to search path
- */
- public void addURL(URL url) {
- File libFile = new File(url.getPath());
- try {
- weaver.addLibraryJarFile(libFile);
- } catch (IOException ex) {
- 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
- * @return the woven bytes
- * @exception IOException weave failed
- */
- public byte[] weaveClass(String name, byte[] bytes) throws IOException {
- return weaveClass(name, bytes, false);
- }
-
- // Track if the weaver is already running on this thread - don't allow re-entrant calls
- private ThreadLocal<Boolean> weaverRunning = new ThreadLocal<Boolean>() {
- @Override
- protected Boolean initialValue() {
- return Boolean.FALSE;
- }
- };
-
- /**
- * 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, boolean mustWeave) throws IOException {
- if (trace == null) {
- // Pr231945: we are likely to be under tomcat and ENABLE_CLEAR_REFERENCES hasn't been set
- System.err
- .println("AspectJ Weaver cannot continue to weave, static state has been cleared. Are you under Tomcat? In order to weave '"
- + name
- + "' during shutdown, 'org.apache.catalina.loader.WebappClassLoader.ENABLE_CLEAR_REFERENCES=false' must be set (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=231945).");
- return bytes;
- }
- if (weaverRunning.get()) {
- // System.out.println("AJC: avoiding re-entrant call to transform " + name);
- return bytes;
- }
- try {
- weaverRunning.set(true);
- if (trace.isTraceEnabled()) {
- trace.enter("weaveClass", this, new Object[] { name, bytes });
- }
-
- if (!enabled) {
- if (trace.isTraceEnabled()) {
- trace.exit("weaveClass", false);
- }
- return bytes;
- }
-
- boolean debugOn = !messageHandler.isIgnoring(Message.DEBUG);
-
- try {
- delegateForCurrentClass = null;
- name = name.replace('/', '.');
- if (couldWeave(name, bytes)) {
- if (accept(name, bytes)) {
-
- // Determine if we have the weaved class cached
- CachedClassReference cacheKey = null;
- final byte[] original_bytes = bytes;
- if (cache != null && !mustWeave) {
- cacheKey = cache.createCacheKey(name, original_bytes);
- CachedClassEntry entry = cache.get(cacheKey, original_bytes);
- if (entry != null) {
- // If the entry has been explicitly ignored
- // return the original bytes
- if (entry.isIgnored()) {
- return bytes;
- }
- return entry.getBytes();
- }
- }
-
- // TODO @AspectJ problem
- // Annotation style aspects need to be included regardless in order to get
- // a valid aspectOf()/hasAspect() generated in them. However - if they are excluded
- // (via include/exclude in aop.xml) they really should only get aspectOf()/hasAspect()
- // and not be included in the full set of aspects being applied by 'this' weaver
- if (debugOn) {
- debug("weaving '" + name + "'");
- }
- bytes = getWovenBytes(name, bytes);
- // temporarily out - searching for @Aspect annotated types is a slow thing to do - we should
- // expect the user to name them if they want them woven - just like code style
- // } 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
- // if (debugOn) {
- // debug("weaving '" + name + "'");
- // }
- // bytes = getAtAspectJAspectBytes(name, bytes);
-
- // Add the weaved class to the cache only if there
- // has been an actual change
- // JVK: Is there a better way to check if the class has
- // been transformed without carrying up some value
- // from the depths?
- if (cacheKey != null) {
- // If no transform has been applied, mark the class
- // as ignored.
- if (Arrays.equals(original_bytes, bytes)) {
- cache.ignore(cacheKey, original_bytes);
- } else {
- cache.put(cacheKey, original_bytes, bytes);
- }
- }
- } else if (debugOn) {
- debug("not weaving '" + name + "'");
- }
- } else if (debugOn) {
- debug("cannot weave '" + name + "'");
- }
- } finally {
- delegateForCurrentClass = null;
- }
-
- if (trace.isTraceEnabled()) {
- trace.exit("weaveClass", bytes);
- }
- return bytes;
- } finally {
- weaverRunning.set(false);
- }
- }
-
- /**
- * @param name
- * @return true if even valid to weave: either with an accept check or to munge it for @AspectJ aspectof support
- */
- private boolean couldWeave(String name, byte[] bytes) {
- return !generatedClasses.containsKey(name) && shouldWeaveName(name);
- }
-
- // ATAJ
- protected boolean accept(String name, byte[] bytes) {
- return true;
- }
-
- protected boolean shouldDump(String name, boolean before) {
- return false;
- }
-
- private boolean shouldWeaveName(String name) {
- if (PACKAGE_INITIAL_CHARS.indexOf(name.charAt(0)) != -1) {
- 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;
- }
- }
- }
- if (name.startsWith(ASPECTJ_BASE_PACKAGE)) {
- return false;
- }
- if (name.startsWith("sun.reflect.")) {// JDK reflect
- return false;
- }
- if (name.startsWith("javax.")) {
- if ((weavingSpecialTypes & WEAVE_JAVAX_PACKAGE) != 0) {
- return true;
- } else {
- if (!haveWarnedOnJavax) {
- haveWarnedOnJavax = true;
- warn("javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified");
- }
- return false;
- }
- }
- if (name.startsWith("java.")) {
- if ((weavingSpecialTypes & WEAVE_JAVA_PACKAGE) != 0) {
- return true;
- } else {
- return false;
- }
- }
- }
- // boolean should = !(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."));
- return true;
- }
-
- /**
- * We allow @AJ aspect weaving so that we can add aspectOf() as part of the weaving (and not part of the source compilation)
- *
- * @param name
- * @param bytes bytecode (from classloader), allow to NOT lookup stuff on disk again during resolve
- * @return true if @Aspect
- */
- private boolean shouldWeaveAnnotationStyleAspect(String name, byte[] bytes) {
- if (delegateForCurrentClass == null) {
- // if (weaver.getWorld().isASMAround()) return asmCheckAnnotationStyleAspect(bytes);
- // else
- ensureDelegateInitialized(name, bytes);
- }
- 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) {
- BcelWorld world = (BcelWorld) weaver.getWorld();
- delegateForCurrentClass = world.addSourceObjectType(name, bytes, false);
- }
- }
-
- /**
- * Weave a set of bytes defining a class.
- *
- * @param name the name of the class being woven
- * @param bytes the bytes that define the class
- * @return byte[] the woven bytes for the class
- * @throws IOException
- */
- private byte[] getWovenBytes(String name, byte[] bytes) throws IOException {
- WeavingClassFileProvider wcp = new WeavingClassFileProvider(name, bytes);
- weaver.weave(wcp);
- return wcp.getBytes();
- }
-
- /**
- * Weave a set of bytes defining a class for only what is needed to turn @AspectJ aspect in a usefull form ie with aspectOf
- * method - see #113587
- *
- * @param name the name of the class being woven
- * @param bytes the bytes that define the class
- * @return byte[] the woven bytes for the class
- * @throws IOException
- */
- private byte[] getAtAspectJAspectBytes(String name, byte[] bytes) throws IOException {
- WeavingClassFileProvider wcp = new WeavingClassFileProvider(name, bytes);
- wcp.setApplyAtAspectJMungersOnly();
- weaver.weave(wcp);
- return wcp.getBytes();
- }
-
- private void registerAspectLibraries(List aspectPath) {
- // System.err.println("? WeavingAdaptor.registerAspectLibraries(" + aspectPath + ")");
- for (Iterator i = aspectPath.iterator(); i.hasNext();) {
- String libName = (String) i.next();
- addAspectLibrary(libName);
- }
-
- weaver.prepareForWeave();
- }
-
- /*
- * Register an aspect library with this classloader for use during weaving. This class loader will also return (unmodified) any
- * of the classes in the library in response to a <code>findClass()</code> request. The library is not required to be on the
- * weavingClasspath given when this classloader was constructed.
- *
- * @param aspectLibraryJarFile a jar file representing an aspect library
- *
- * @throws IOException
- */
- private void addAspectLibrary(String aspectLibraryName) {
- File aspectLibrary = new File(aspectLibraryName);
- if (aspectLibrary.isDirectory() || (FileUtil.isZipFile(aspectLibrary))) {
- try {
- info("adding aspect library: '" + aspectLibrary + "'");
- weaver.addLibraryJarFile(aspectLibrary);
- } catch (IOException ex) {
- error("exception adding aspect library: '" + ex + "'");
- }
- } else {
- error("bad aspect library: '" + aspectLibrary + "'");
- }
- }
-
- private static List<String> makeClasspath(String cp) {
- List<String> ret = new ArrayList<String>();
- if (cp != null) {
- StringTokenizer tok = new StringTokenizer(cp, File.pathSeparator);
- while (tok.hasMoreTokens()) {
- ret.add(tok.nextToken());
- }
- }
- return ret;
- }
-
- protected boolean debug(String message) {
- return MessageUtil.debug(messageHandler, message);
- }
-
- protected boolean info(String message) {
- return MessageUtil.info(messageHandler, message);
- }
-
- protected boolean warn(String message) {
- return MessageUtil.warn(messageHandler, message);
- }
-
- protected boolean warn(String message, Throwable th) {
- return messageHandler.handleMessage(new Message(message, IMessage.WARNING, th, null));
- }
-
- protected boolean error(String message) {
- return MessageUtil.error(messageHandler, message);
- }
-
- protected boolean error(String message, Throwable th) {
- return messageHandler.handleMessage(new Message(message, IMessage.ERROR, th, null));
- }
-
- public String getContextId() {
- return "WeavingAdaptor";
- }
-
- /**
- * Dump the given bytcode in _dump/... (dev mode)
- *
- * @param name
- * @param b
- * @param before whether we are dumping before weaving
- * @throws Throwable
- */
- protected void dump(String name, byte[] b, boolean before) {
- String dirName = getDumpDir();
-
- if (before) {
- dirName = dirName + File.separator + "_before";
- }
-
- String className = name.replace('.', '/');
- final File dir;
- if (className.indexOf('/') > 0) {
- dir = new File(dirName + File.separator + className.substring(0, className.lastIndexOf('/')));
- } else {
- dir = new File(dirName);
- }
- dir.mkdirs();
- String fileName = dirName + File.separator + className + ".class";
- try {
- // System.out.println("WeavingAdaptor.dump() fileName=" + new File(fileName).getAbsolutePath());
- FileOutputStream os = new FileOutputStream(fileName);
- os.write(b);
- os.close();
- } catch (IOException ex) {
- warn("unable to dump class " + name + " in directory " + dirName, ex);
- }
- }
-
- /**
- * @return the directory in which to dump - default is _ajdump but it
- */
- protected String getDumpDir() {
- return "_ajdump";
- }
-
- /**
- * Processes messages arising from weaver operations. Tell weaver to abort on any message more severe than warning.
- */
- protected class WeavingAdaptorMessageHolder extends MessageHandler {
-
- private IMessageHandler delegate;
- private List<IMessage> savedMessages;
-
- protected boolean traceMessages = Boolean.getBoolean(TRACE_MESSAGES_PROPERTY);
-
- public WeavingAdaptorMessageHolder(PrintWriter writer) {
-
- this.delegate = new WeavingAdaptorMessageWriter(writer);
- super.dontIgnore(IMessage.WEAVEINFO);
- }
-
- private void traceMessage(IMessage message) {
- if (message instanceof WeaveMessage) {
- trace.debug(render(message));
- } else if (message.isDebug()) {
- trace.debug(render(message));
- } else if (message.isInfo()) {
- trace.info(render(message));
- } else if (message.isWarning()) {
- trace.warn(render(message), message.getThrown());
- } else if (message.isError()) {
- trace.error(render(message), message.getThrown());
- } else if (message.isFailed()) {
- trace.fatal(render(message), message.getThrown());
- } else if (message.isAbort()) {
- trace.fatal(render(message), message.getThrown());
- } else {
- trace.error(render(message), message.getThrown());
- }
- }
-
- protected String render(IMessage message) {
- return "[" + getContextId() + "] " + message.toString();
- }
-
- public void flushMessages() {
- if (savedMessages == null) {
- savedMessages = new ArrayList<IMessage>();
- savedMessages.addAll(super.getUnmodifiableListView());
- clearMessages();
- for (IMessage message : savedMessages) {
- delegate.handleMessage(message);
- }
- }
- // accumulating = false;
- // messages.clear();
- }
-
- public void setDelegate(IMessageHandler messageHandler) {
- delegate = messageHandler;
- }
-
- /*
- * IMessageHandler
- */
-
- @Override
- public boolean handleMessage(IMessage message) throws AbortException {
- if (traceMessages) {
- traceMessage(message);
- }
-
- super.handleMessage(message);
-
- if (abortOnError && 0 <= message.getKind().compareTo(IMessage.ERROR)) {
- throw new AbortException(message);
- }
- // if (accumulating) {
- // boolean result = addMessage(message);
- // if (abortOnError && 0 <= message.getKind().compareTo(IMessage.ERROR)) {
- // throw new AbortException(message);
- // }
- // return result;
- // }
- // else return delegate.handleMessage(message);
-
- if (savedMessages != null) {
- delegate.handleMessage(message);
- }
- return true;
- }
-
- @Override
- public boolean isIgnoring(Kind kind) {
- return delegate.isIgnoring(kind);
- }
-
- @Override
- public void dontIgnore(IMessage.Kind kind) {
- if (null != kind && delegate != null) {
- delegate.dontIgnore(kind);
- }
- }
-
- @Override
- public void ignore(Kind kind) {
- if (null != kind && delegate != null) {
- delegate.ignore(kind);
- }
- }
-
- /*
- * IMessageHolder
- */
-
- @Override
- public List<IMessage> getUnmodifiableListView() {
- // System.err.println("? WeavingAdaptorMessageHolder.getUnmodifiableListView() savedMessages=" + savedMessages);
- List<IMessage> allMessages = new ArrayList<IMessage>();
- allMessages.addAll(savedMessages);
- allMessages.addAll(super.getUnmodifiableListView());
- return allMessages;
- }
- }
-
- protected class WeavingAdaptorMessageWriter extends MessageWriter {
-
- private final Set<IMessage.Kind> ignoring = new HashSet<IMessage.Kind>();
- private final IMessage.Kind failKind;
-
- public WeavingAdaptorMessageWriter(PrintWriter writer) {
- super(writer, true);
-
- ignore(IMessage.WEAVEINFO);
- ignore(IMessage.DEBUG);
- ignore(IMessage.INFO);
- this.failKind = IMessage.ERROR;
- }
-
- @Override
- public boolean handleMessage(IMessage message) throws AbortException {
- // boolean result =
- super.handleMessage(message);
- if (abortOnError && 0 <= message.getKind().compareTo(failKind)) {
- throw new AbortException(message);
- }
- return true;
- }
-
- @Override
- public boolean isIgnoring(Kind kind) {
- return ((null != kind) && (ignoring.contains(kind)));
- }
-
- /**
- * Set a message kind to be ignored from now on
- */
- @Override
- public void ignore(IMessage.Kind kind) {
- if ((null != kind) && (!ignoring.contains(kind))) {
- ignoring.add(kind);
- }
- }
-
- /**
- * Remove a message kind from the list of those ignored from now on.
- */
- @Override
- public void dontIgnore(IMessage.Kind kind) {
- if (null != kind) {
- ignoring.remove(kind);
- }
- }
-
- @Override
- protected String render(IMessage message) {
- return "[" + getContextId() + "] " + super.render(message);
- }
- }
-
- private class WeavingClassFileProvider implements IClassFileProvider {
-
- private final UnwovenClassFile unwovenClass;
- private final List<UnwovenClassFile> unwovenClasses = new ArrayList<UnwovenClassFile>();
- private IUnwovenClassFile wovenClass;
- private boolean isApplyAtAspectJMungersOnly = false;
-
- public WeavingClassFileProvider(String name, byte[] bytes) {
- ensureDelegateInitialized(name, bytes);
- this.unwovenClass = new UnwovenClassFile(name, delegateForCurrentClass.getResolvedTypeX().getName(), bytes);
- this.unwovenClasses.add(unwovenClass);
-
- if (shouldDump(name.replace('/', '.'), true)) {
- dump(name, bytes, true);
- }
-
- }
-
- public void setApplyAtAspectJMungersOnly() {
- isApplyAtAspectJMungersOnly = true;
- }
-
- public boolean isApplyAtAspectJMungersOnly() {
- return isApplyAtAspectJMungersOnly;
- }
-
- public byte[] getBytes() {
- if (wovenClass != null) {
- return wovenClass.getBytes();
- } else {
- return unwovenClass.getBytes();
- }
- }
-
- public Iterator<UnwovenClassFile> getClassFileIterator() {
- return unwovenClasses.iterator();
- }
-
- public IWeaveRequestor getRequestor() {
- return new IWeaveRequestor() {
-
- public void acceptResult(IUnwovenClassFile result) {
- if (wovenClass == null) {
- wovenClass = result;
- String name = result.getClassName();
- if (shouldDump(name.replace('/', '.'), false)) {
- dump(name, result.getBytes(), false);
- }
- } else {
- // Classes generated by weaver e.g. around closure advice
- String className = result.getClassName();
- byte[] resultBytes = result.getBytes();
-
- if (SimpleCacheFactory.isEnabled()) {
- SimpleCache lacache=SimpleCacheFactory.createSimpleCache();
- lacache.put(result.getClassName(), wovenClass.getBytes(), result.getBytes());
- lacache.addGeneratedClassesNames(wovenClass.getClassName(), wovenClass.getBytes(), result.getClassName());
- }
-
- generatedClasses.put(className, result);
- generatedClasses.put(wovenClass.getClassName(), result);
- generatedClassHandler.acceptClass(className, null, resultBytes);
- }
- }
-
- public void processingReweavableState() {
- }
-
- public void addingTypeMungers() {
- }
-
- public void weavingAspects() {
- }
-
- public void weavingClasses() {
- }
-
- public void weaveCompleted() {
- // ResolvedType.resetPrimitives();
- if (delegateForCurrentClass != null) {
- delegateForCurrentClass.weavingCompleted();
- }
- // ResolvedType.resetPrimitives();
- // bcelWorld.discardType(typeBeingProcessed.getResolvedTypeX()); // work in progress
- }
- };
- }
- }
-
- public void setActiveProtectionDomain(ProtectionDomain protectionDomain) {
- activeProtectionDomain = protectionDomain;
- }
-} \ No newline at end of file
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/AbstractCacheBacking.java b/weaver/src/org/aspectj/weaver/tools/cache/AbstractCacheBacking.java
deleted file mode 100644
index 649e21d05..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/AbstractCacheBacking.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- * Lyor Goldstein (vmware) add support for weaved class being re-defined
- *******************************************************************************/
-package org.aspectj.weaver.tools.cache;
-
-import java.util.zip.CRC32;
-
-import org.aspectj.weaver.tools.Trace;
-import org.aspectj.weaver.tools.TraceFactory;
-
-/**
- * Basic &quot;common&quot; {@link CacheBacking} implementation
- */
-public abstract class AbstractCacheBacking implements CacheBacking {
- protected final Trace logger=TraceFactory.getTraceFactory().getTrace(getClass());
-
- protected AbstractCacheBacking () {
- super();
- }
-
- /**
- * Calculates CRC32 on the provided bytes
- * @param bytes The bytes array - ignored if <code>null</code>/empty
- * @return Calculated CRC
- * @see {@link CRC32}
- */
- public static final long crc (byte[] bytes) {
- if ((bytes == null) || (bytes.length <= 0)) {
- return 0L;
- }
-
- CRC32 crc32=new CRC32();
- crc32.update(bytes);
- return crc32.getValue();
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/AbstractFileCacheBacking.java b/weaver/src/org/aspectj/weaver/tools/cache/AbstractFileCacheBacking.java
deleted file mode 100644
index 5447c158b..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/AbstractFileCacheBacking.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- * Lyor Goldstein (vmware) add support for weaved class being re-defined
- *******************************************************************************/
-package org.aspectj.weaver.tools.cache;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Useful &quot;common&quot; functionality for caching to files
- */
-public abstract class AbstractFileCacheBacking extends AbstractCacheBacking {
- /**
- * Default property used to specify a default weaving cache dir location
- */
- public static final String WEAVED_CLASS_CACHE_DIR = "aj.weaving.cache.dir";
- private final File cacheDirectory;
-
- protected AbstractFileCacheBacking (File cacheDirectory) {
- if ((this.cacheDirectory=cacheDirectory) == null) {
- throw new IllegalStateException("No cache directory specified");
- }
- }
-
- public File getCacheDirectory () {
- return cacheDirectory;
- }
-
- protected void writeClassBytes (String key, byte[] bytes) throws Exception {
- File dir=getCacheDirectory(), file=new File(dir, key);
- FileOutputStream out=new FileOutputStream(file);
- try {
- out.write(bytes);
- } finally {
- close(out, file);
- }
- }
-
- protected void delete(File file) {
- if (file.exists() && (!file.delete())) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.error("Error deleting file " + file.getAbsolutePath());
- }
- }
- }
-
- protected void close(OutputStream out, File file) {
- if (out != null) {
- try {
- out.close();
- } catch (IOException e) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.error("Failed (" + e.getClass().getSimpleName() + ")"
- + " to close write file " + file.getAbsolutePath()
- + ": " + e.getMessage(), e);
- }
- }
- }
- }
-
- protected void close(InputStream in, File file) {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.error("Failed (" + e.getClass().getSimpleName() + ")"
- + " to close read file " + file.getAbsolutePath()
- + ": " + e.getMessage(), e);
- }
- }
- }
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/AbstractIndexedFileCacheBacking.java b/weaver/src/org/aspectj/weaver/tools/cache/AbstractIndexedFileCacheBacking.java
deleted file mode 100644
index 1580277b1..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/AbstractIndexedFileCacheBacking.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- * Lyor Goldstein (vmware) add support for weaved class being re-defined
- *******************************************************************************/
-package org.aspectj.weaver.tools.cache;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.io.StreamCorruptedException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.aspectj.util.LangUtil;
-
-/**
- * Uses an <code>index</code> file to keep track of the cached entries
- */
-public abstract class AbstractIndexedFileCacheBacking extends AbstractFileCacheBacking {
- /**
- * Default name of cache index file - assumed to contain {@link IndexEntry}-s
- */
- public static final String INDEX_FILE = "cache.idx";
- protected static final IndexEntry[] EMPTY_INDEX=new IndexEntry[0];
- protected static final String[] EMPTY_KEYS=new String[0];
-
- private final File indexFile;
-
- protected AbstractIndexedFileCacheBacking(File cacheDir) {
- super(cacheDir);
-
- indexFile = new File(cacheDir, INDEX_FILE);
- }
-
- public File getIndexFile () {
- return indexFile;
- }
-
- public String[] getKeys(String regex) {
- Map<String, IndexEntry> index=getIndex();
- if ((index == null) || index.isEmpty()) {
- return EMPTY_KEYS;
- }
-
- Collection<String> matches=new LinkedList<String>();
- synchronized(index) {
- for (String key : index.keySet()) {
- if (key.matches(regex)) {
- matches.add(key);
- }
- }
- }
-
- if (matches.isEmpty()) {
- return EMPTY_KEYS;
- } else {
- return matches.toArray(new String[matches.size()]);
- }
- }
-
- protected Map<String, IndexEntry> readIndex () {
- return readIndex(getCacheDirectory(), getIndexFile());
- }
-
- protected void writeIndex () {
- writeIndex(getIndexFile());
- }
-
- protected void writeIndex (File file) {
- try {
- writeIndex(file, getIndex());
- } catch(Exception e) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.warn("writeIndex(" + file + ") " + e.getClass().getSimpleName() + ": " + e.getMessage(), e);
- }
- }
- }
-
- protected abstract Map<String, IndexEntry> getIndex ();
-
- protected Map<String, IndexEntry> readIndex (File cacheDir, File cacheFile) {
- Map<String, IndexEntry> indexMap=new TreeMap<String, IndexEntry>();
- IndexEntry[] idxValues=readIndex(cacheFile);
- if (LangUtil.isEmpty(idxValues)) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.debug("readIndex(" + cacheFile + ") no index entries");
- }
- return indexMap;
- }
-
- for (IndexEntry ie : idxValues) {
- IndexEntry resEntry=resolveIndexMapEntry(cacheDir, ie);
- if (resEntry != null) {
- indexMap.put(resEntry.key, resEntry);
- } else if ((logger != null) && logger.isTraceEnabled()) {
- logger.debug("readIndex(" + cacheFile + ") skip " + ie.key);
- }
- }
-
- return indexMap;
- }
-
- protected IndexEntry resolveIndexMapEntry (File cacheDir, IndexEntry ie) {
- return ie;
- }
-
- public IndexEntry[] readIndex(File indexFile) {
- if (!indexFile.canRead()) {
- return EMPTY_INDEX;
- }
-
- ObjectInputStream ois = null;
- try {
- ois = new ObjectInputStream(new FileInputStream(indexFile));
- return (IndexEntry[]) ois.readObject();
- } catch (Exception e) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.error("Failed (" + e.getClass().getSimpleName() + ")"
- + " to read index from " + indexFile.getAbsolutePath()
- + " : " + e.getMessage(), e);
- }
- delete(indexFile);
- } finally {
- close(ois, indexFile);
- }
-
- return EMPTY_INDEX;
- }
-
- protected void writeIndex (File indexFile, Map<String,? extends IndexEntry> index) throws IOException {
- writeIndex(indexFile, LangUtil.isEmpty(index) ? Collections.<IndexEntry>emptyList() : index.values());
- }
-
- protected void writeIndex (File indexFile, IndexEntry ... entries) throws IOException {
- writeIndex(indexFile, LangUtil.isEmpty(entries) ? Collections.<IndexEntry>emptyList() : Arrays.asList(entries));
- }
-
- protected void writeIndex (File indexFile, Collection<? extends IndexEntry> entries) throws IOException {
- File indexDir=indexFile.getParentFile();
- if ((!indexDir.exists()) && (!indexDir.mkdirs())) {
- throw new IOException("Failed to create path to " + indexFile.getAbsolutePath());
- }
-
- int numEntries=LangUtil.isEmpty(entries) ? 0 : entries.size();
- IndexEntry[] entryValues=(numEntries <= 0) ? null : entries.toArray(new IndexEntry[numEntries]);
- // if no entries, simply delete the index file
- if (LangUtil.isEmpty(entryValues)) {
- if (indexFile.exists() && (!indexFile.delete())) {
- throw new StreamCorruptedException("Failed to clean up index file at " + indexFile.getAbsolutePath());
- }
-
- return;
- }
-
- ObjectOutputStream oos=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(indexFile), 4096));
- try {
- oos.writeObject(entryValues);
- } finally {
- close(oos, indexFile);
- }
- }
-
- public static final IndexEntry createIndexEntry (CachedClassEntry classEntry, byte[] originalBytes) {
- if (classEntry == null) {
- return null;
- }
-
- IndexEntry indexEntry = new IndexEntry();
- indexEntry.key = classEntry.getKey();
- indexEntry.generated = classEntry.isGenerated();
- indexEntry.ignored = classEntry.isIgnored();
- indexEntry.crcClass = crc(originalBytes);
- if (!classEntry.isIgnored()) {
- indexEntry.crcWeaved = crc(classEntry.getBytes());
- }
-
- return indexEntry;
- }
-
- /**
- * The default index entry in the index file
- */
- public static class IndexEntry implements Serializable, Cloneable {
- private static final long serialVersionUID = 756391290557029363L;
-
- public String key;
- public boolean generated;
- public boolean ignored;
- public long crcClass;
- public long crcWeaved;
-
- public IndexEntry () {
- super();
- }
-
- @Override
- public IndexEntry clone () {
- try {
- return getClass().cast(super.clone());
- } catch(CloneNotSupportedException e) {
- throw new RuntimeException("Failed to clone: " + toString() + ": " + e.getMessage(), e);
- }
- }
-
- @Override
- public int hashCode() {
- return (int) (key.hashCode()
- + (generated ? 1 : 0)
- + (ignored ? 1 : 0)
- + crcClass
- + crcWeaved);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null)
- return false;
- if (this == obj)
- return true;
- if (getClass() != obj.getClass())
- return false;
-
- IndexEntry other=(IndexEntry) obj;
- if (this.key.equals(other.key)
- && (this.ignored == other.ignored)
- && (this.generated == other.generated)
- && (this.crcClass == other.crcClass)
- && (this.crcWeaved == other.crcWeaved)) {
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- public String toString() {
- return key
- + "[" + (generated ? "generated" : "ignored") + "]"
- + ";crcClass=0x" + Long.toHexString(crcClass)
- + ";crcWeaved=0x" + Long.toHexString(crcWeaved)
- ;
- }
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/AsynchronousFileCacheBacking.java b/weaver/src/org/aspectj/weaver/tools/cache/AsynchronousFileCacheBacking.java
deleted file mode 100644
index 636a82a7a..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/AsynchronousFileCacheBacking.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * Lyor Goldstein (vmware) add support for weaved class being re-defined
- *******************************************************************************/
-
-package org.aspectj.weaver.tools.cache;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import org.aspectj.util.FileUtil;
-import org.aspectj.util.LangUtil;
-import org.aspectj.weaver.tools.Trace;
-import org.aspectj.weaver.tools.TraceFactory;
-
-/**
- * Uses a background thread to do the actual I/O and for caching &quot;persistence&quot;
- * so that the caching works faster on repeated activations of the application.
- * The class maintains an in-memory cache, and uses a queue of {@link AsyncCommand}s
- * to signal to a background thread various actions required to &quot;synchronize&quot;
- * the in-memory cache with the persisted copy. Whenever there is a cache miss
- * from the {@link #get(CachedClassReference)} call, the weaver issues a
- * {@link #put(CachedClassEntry)} call. This call has 2 side-effects:</BR>
- * <UL>
- * <LI>
- * The in-memory cache is updated so that subsequent calls to {@link #get(CachedClassReference)}
- * will not return the mapped value.
- * </LI>
- *
- * <LI>
- * An &quot;update index&quot {@link AsyncCommand} is posted to the background
- * thread so that the newly mapped value will be persisted (eventually)
- * </LI>
- * </UL>
- * The actual persistence is implemented by the <U>concrete</U> classes
- */
-public abstract class AsynchronousFileCacheBacking extends AbstractIndexedFileCacheBacking {
- private static final BlockingQueue<AsyncCommand> commandsQ=new LinkedBlockingQueue<AsyncCommand>();
- private static final ExecutorService execService=Executors.newSingleThreadExecutor();
- private static Future<?> commandsRunner;
-
- protected final Map<String, IndexEntry> index, exposedIndex;
- protected final Map<String, byte[]> bytesMap, exposedBytes;
-
- protected AsynchronousFileCacheBacking (File cacheDir) {
- super(cacheDir);
-
- index = readIndex(cacheDir, getIndexFile());
- exposedIndex = Collections.unmodifiableMap(index);
- bytesMap = readClassBytes(index, cacheDir);
- exposedBytes = Collections.unmodifiableMap(bytesMap);
- }
-
- @Override
- protected Map<String, IndexEntry> getIndex() {
- return index;
- }
-
- public CachedClassEntry get(CachedClassReference ref, byte[] originalBytes) {
- String key=ref.getKey();
- final IndexEntry indexEntry;
- synchronized(index) {
- if ((indexEntry=index.get(key)) == null) {
- return null;
- }
- }
-
- if (crc(originalBytes) != indexEntry.crcClass) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.debug("get(" + getCacheDirectory() + ") mismatched original class bytes CRC for " + key);
- }
-
- remove(key);
- return null;
- }
-
- if (indexEntry.ignored) {
- return new CachedClassEntry(ref, WeavedClassCache.ZERO_BYTES, CachedClassEntry.EntryType.IGNORED);
- }
-
- final byte[] bytes;
- synchronized(bytesMap) {
- /*
- * NOTE: we assume that keys represent classes so if we have their
- * bytes they will not be re-created
- */
- if ((bytes=bytesMap.remove(key)) == null) {
- return null;
- }
- }
-
- if (indexEntry.generated) {
- return new CachedClassEntry(ref, bytes, CachedClassEntry.EntryType.GENERATED);
- } else {
- return new CachedClassEntry(ref, bytes, CachedClassEntry.EntryType.WEAVED);
- }
- }
-
- public void put(CachedClassEntry entry, byte[] originalBytes) {
- String key=entry.getKey();
- byte[] bytes=entry.isIgnored() ? null : entry.getBytes();
- synchronized(index) {
- IndexEntry indexEntry=index.get(key);
- if (indexEntry != null) {
- return;
- }
-
- /*
- * Note: we do not cache the class bytes - only send them to
- * be saved. The assumption is that the 'put' call was invoked
- * because 'get' failed to return any bytes. And since we assume
- * that each class bytes are required only once, there is no
- * need to cache them
- */
- indexEntry = createIndexEntry(entry, originalBytes);
- index.put(key, indexEntry);
- }
-
- if (!postCacheCommand(new InsertCommand(this, key, bytes))) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.error("put(" + getCacheDirectory() + ") Failed to post insert command for " + key);
- }
- }
-
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.debug("put(" + getCacheDirectory() + ")[" + key + "] inserted");
- }
- }
-
- public void remove(CachedClassReference ref) {
- remove(ref.getKey());
- }
-
- protected IndexEntry remove (String key) {
- IndexEntry entry;
- synchronized(index) {
- entry = index.remove(key);
- }
-
- synchronized(bytesMap) {
- bytesMap.remove(key);
- }
-
- if (!postCacheCommand(new RemoveCommand(this, key))) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.error("remove(" + getCacheDirectory() + ") Failed to post remove command for " + key);
- }
- }
-
- if (entry != null) {
- if (!key.equals(entry.key)) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.error("remove(" + getCacheDirectory() + ") Mismatched keys: " + key + " / " + entry.key);
- }
- } else if ((logger != null) && logger.isTraceEnabled()) {
- logger.debug("remove(" + getCacheDirectory() + ")[" + key + "] removed");
- }
- }
-
- return entry;
- }
-
- public List<IndexEntry> getIndexEntries () {
- synchronized(index) {
- if (index.isEmpty()) {
- return Collections.emptyList();
- } else {
- return new ArrayList<IndexEntry>(index.values());
- }
- }
- }
-
- public Map<String, IndexEntry> getIndexMap () {
- return exposedIndex;
- }
-
- public Map<String, byte[]> getBytesMap () {
- return exposedBytes;
- }
-
- public void clear() {
- synchronized(index) {
- index.clear();
- }
-
- if (!postCacheCommand(new ClearCommand(this))) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.error("Failed to post clear command for " + getIndexFile());
- }
- }
- }
-
- protected void executeCommand (AsyncCommand cmd) throws Exception {
- if (cmd instanceof ClearCommand) {
- executeClearCommand();
- } else if (cmd instanceof UpdateIndexCommand) {
- executeUpdateIndexCommand();
- } else if (cmd instanceof InsertCommand) {
- executeInsertCommand((InsertCommand) cmd);
- } else if (cmd instanceof RemoveCommand) {
- executeRemoveCommand((RemoveCommand) cmd);
- } else {
- throw new UnsupportedOperationException("Unknown command: " + cmd);
- }
- }
-
- protected void executeClearCommand () throws Exception {
- FileUtil.deleteContents(getIndexFile());
- FileUtil.deleteContents(getCacheDirectory());
- }
-
- protected void executeUpdateIndexCommand () throws Exception {
- writeIndex(getIndexFile(), getIndexEntries());
- }
-
- protected void executeInsertCommand (InsertCommand cmd) throws Exception {
- writeIndex(getIndexFile(), getIndexEntries());
-
- byte[] bytes=cmd.getClassBytes();
- if (bytes != null) {
- writeClassBytes(cmd.getKey(), bytes);
- }
- }
-
- protected void executeRemoveCommand (RemoveCommand cmd) throws Exception {
- Exception err=null;
- try {
- removeClassBytes(cmd.getKey());
- } catch(Exception e) {
- err = e;
- }
-
- writeIndex(getIndexFile(), getIndexEntries());
-
- if (err != null) {
- throw err; // check if the class bytes remove had any problems
- }
- }
-
- /**
- * Helper for {@link #executeRemoveCommand(RemoveCommand)}
- * @param key The key representing the class whose bytes are to be removed
- * @throws Exception if failed to remove class bytes
- */
- protected abstract void removeClassBytes (String key) throws Exception;
-
- protected abstract Map<String, byte[]> readClassBytes (Map<String,IndexEntry> indexMap, File cacheDir);
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + "[" + String.valueOf(getCacheDirectory()) + "]";
- }
-
- protected static final <T extends AsynchronousFileCacheBacking> T createBacking (
- File cacheDir, AsynchronousFileCacheBackingCreator<T> creator) {
- final Trace trace=TraceFactory.getTraceFactory().getTrace(AsynchronousFileCacheBacking.class);
- if (!cacheDir.exists()) {
- if (!cacheDir.mkdirs()) {
- if ((trace != null) && trace.isTraceEnabled()) {
- trace.error("Unable to create cache directory at " + cacheDir.getAbsolutePath());
- }
- return null;
- }
- }
-
- if (!cacheDir.canWrite()) {
- if ((trace != null) && trace.isTraceEnabled()) {
- trace.error("Cache directory is not writable at " + cacheDir.getAbsolutePath());
- }
- return null;
- }
-
- // start the service (if needed) only if successfully create the backing instance
- T backing=creator.create(cacheDir);
- synchronized(execService) {
- if (commandsRunner == null) {
- commandsRunner = execService.submit(new Runnable() {
- @SuppressWarnings("synthetic-access")
- public void run() {
- for ( ; ; ) {
- try {
- AsyncCommand cmd=commandsQ.take();
- try {
- AsynchronousFileCacheBacking cache=cmd.getCache();
- cache.executeCommand(cmd);
- } catch(Exception e) {
- if ((trace != null) && trace.isTraceEnabled()) {
- trace.error("Failed (" + e.getClass().getSimpleName() + ")"
- + " to execute " + cmd + ": " + e.getMessage(), e);
- }
- }
- } catch(InterruptedException e) {
- if ((trace != null) && trace.isTraceEnabled()) {
- trace.warn("Interrupted");
- }
- Thread.currentThread().interrupt();
- break;
- }
- }
- }
- });
- }
- }
-
- // fire-up an update-index command in case index was changed by the constructor
- if (!postCacheCommand(new UpdateIndexCommand(backing))) {
- if ((trace != null) && trace.isTraceEnabled()) {
- trace.warn("Failed to offer update index command to " + cacheDir.getAbsolutePath());
- }
- }
-
- return backing;
- }
-
- public static final boolean postCacheCommand (AsyncCommand cmd) {
- return commandsQ.offer(cmd);
- }
-
- public static interface AsynchronousFileCacheBackingCreator<T extends AsynchronousFileCacheBacking> {
- T create (File cacheDir);
- }
- /**
- * Represents an asynchronous command that can be sent to the
- * {@link AsynchronousFileCacheBacking} instance to be executed
- * on it <U>asynchronously</U>
- */
- public static interface AsyncCommand {
- /**
- * @return The {@link AsynchronousFileCacheBacking} on which
- * this command is supposed to be executed
- * @see AsynchronousFileCacheBacking#executeCommand(AsyncCommand)
- */
- AsynchronousFileCacheBacking getCache ();
- }
-
- public static abstract class AbstractCommand implements AsyncCommand {
- private final AsynchronousFileCacheBacking cache;
- protected AbstractCommand (AsynchronousFileCacheBacking backing) {
- if ((cache=backing) == null) {
- throw new IllegalStateException("No backing cache specified");
- }
- }
-
- public final AsynchronousFileCacheBacking getCache () {
- return cache;
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + "[" + getCache() + "]";
- }
- }
-
- public static class ClearCommand extends AbstractCommand {
- public ClearCommand (AsynchronousFileCacheBacking cache) {
- super(cache);
- }
- }
-
- public static class UpdateIndexCommand extends AbstractCommand {
- public UpdateIndexCommand (AsynchronousFileCacheBacking cache) {
- super(cache);
- }
- }
-
- /**
- * Base class for {@link AbstractCommand}s that refer to a cache key
- */
- public static abstract class KeyedCommand extends AbstractCommand {
- private final String key;
- protected KeyedCommand (AsynchronousFileCacheBacking cache, String keyValue) {
- super(cache);
-
- if (LangUtil.isEmpty(keyValue)) {
- throw new IllegalStateException("No key value");
- }
-
- key = keyValue;
- }
-
- public final String getKey () {
- return key;
- }
-
- @Override
- public String toString() {
- return super.toString() + "[" + getKey() + "]";
- }
- }
-
- public static class RemoveCommand extends KeyedCommand {
- public RemoveCommand (AsynchronousFileCacheBacking cache, String keyValue) {
- super(cache, keyValue);
- }
- }
-
- public static class InsertCommand extends KeyedCommand {
- private final byte[] bytes;
-
- public InsertCommand (AsynchronousFileCacheBacking cache, String keyValue, byte[] classBytes) {
- super(cache, keyValue);
- bytes = classBytes;
- }
-
- public final byte[] getClassBytes () {
- return bytes;
- }
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/CacheBacking.java b/weaver/src/org/aspectj/weaver/tools/cache/CacheBacking.java
deleted file mode 100644
index bcf7c0b60..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/CacheBacking.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- * Lyor Goldstein (vmware) add support for weaved class being re-defined
- *******************************************************************************/
-package org.aspectj.weaver.tools.cache;
-
-/**
- * Interface for the backing to the cache; usually a file,
- * but could be an in-memory backing for testing.
- * <p/>
- * aspectj and jvmti provide no suitable guarantees
- * on locking for class redefinitions, so every implementation
- * must have a some locking mechanism to prevent invalid reads.
- */
-public interface CacheBacking {
- /**
- * Return a list of keys which match the given
- * regex.
- *
- * @param regex
- * @return
- */
- public String[] getKeys(String regex);
-
- /**
- * Remove an entry from the cache
- *
- * @param ref
- */
- public void remove(CachedClassReference ref);
-
- /**
- * Clear the entire cache
- */
- public void clear();
-
- /**
- * Get a cache entry
- *
- * @param ref entry to retrieve
- * @param originalBytes Pre-weaving class bytes - required in order to
- * ensure that the cached entry refers to the same original class
- * @return the cached bytes or null, if the entry does not exist
- */
- public CachedClassEntry get(CachedClassReference ref, byte[] originalBytes);
-
- /**
- * Put an entry in the cache
- *
- * @param entry key of the entry
- * @param originalBytes Pre-weaving class bytes - required in order to
- * ensure that the cached entry refers to the same original class
- */
- public void put(CachedClassEntry entry, byte[] originalBytes);
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/CacheFactory.java b/weaver/src/org/aspectj/weaver/tools/cache/CacheFactory.java
deleted file mode 100644
index 042ef61bd..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/CacheFactory.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- *******************************************************************************/
-package org.aspectj.weaver.tools.cache;
-
-/**
- * Facility for overriding the default CacheKeyResolver
- * and CacheBacking; an implementing factory must be set
- * on the {@link WeavedClassCache} before the
- * {@link org.aspectj.weaver.tools.WeavingAdaptor} is
- * configured.
- */
-public interface CacheFactory {
- CacheKeyResolver createResolver();
-
- CacheBacking createBacking(String scope);
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/CacheKeyResolver.java b/weaver/src/org/aspectj/weaver/tools/cache/CacheKeyResolver.java
deleted file mode 100644
index 8c76ad878..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/CacheKeyResolver.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- *******************************************************************************/
-
-package org.aspectj.weaver.tools.cache;
-
-import java.util.List;
-
-/**
- * Interface to allow alternate hashing schemes for weaved and
- * generated classes. While the DefaultCacheKeyResolver may be
- * a reasonable naive implementation, the management and invalidation
- * of the cache may be more usefully accomplished at the Application
- * or Container level.
- * <p/>
- * The key is not a one-way hash; it must be convertible back to a
- * className and must match the regex for the type of key it is
- * (generated or weaved).
- */
-public interface CacheKeyResolver {
- /**
- * Create a key for the given className from a class generated by
- * the weaver such that:
- * <pre>
- * className == keyToClass(generatedKey(className)) holds
- * and
- * generatedKey(className).matches(getGeneratedRegex()) == true
- * </pre>
- *
- * @param className class to create a key for
- * @return key for the class, or null if no caching should be performed
- */
- CachedClassReference generatedKey(String className);
-
- /**
- * Create a key for the given class name and byte array from the pre-weaved
- * class such that
- * <pre>
- * className == keyToClass(weavedKey(className, various_bytes)) holds
- * and
- * weavedKey(className, various_bytes).matches(getWeavedRegex()) == true
- * </pre>
- *
- * @param className class to create a key for
- * @param original_bytes bytes of the pre-weaved class
- * @return key for the class, or null if no caching should be performed
- */
- CachedClassReference weavedKey(String className, byte[] original_bytes);
-
- /**
- * Convert a key back to a className
- *
- * @param key cache key
- * @return className
- */
- String keyToClass(String key);
-
- /**
- * Create a unique string for the given classpath and aspect list
- *
- * @param loader Classloader for this adapter
- * @param aspects list of aspects; either urls or class names handled by this adapter
- * @return scope, or null, if no caching should be performed for this classloader
- */
- String createClassLoaderScope(ClassLoader loader, List<String> aspects);
-
- /**
- * Return a regex which matches all generated keys
- *
- * @return string regex
- */
- String getGeneratedRegex();
-
- /**
- * Return a regex which matches all weaved keys;
- *
- * @return string regex
- */
- String getWeavedRegex();
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/CacheStatistics.java b/weaver/src/org/aspectj/weaver/tools/cache/CacheStatistics.java
deleted file mode 100644
index 1ccacfc18..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/CacheStatistics.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- *******************************************************************************/
-
-package org.aspectj.weaver.tools.cache;
-
-/**
- * Maintains some basic statistics on the class cache.
- */
-public class CacheStatistics {
- private volatile int hits;
- private volatile int misses;
- private volatile int weaved;
- private volatile int generated;
- private volatile int ignored;
- private volatile int puts;
- private volatile int puts_ignored;
-
- public void hit() {
- hits++;
- }
-
- public void miss() {
- misses++;
- }
-
- public void weaved() {
- weaved++;
- }
-
- public void generated() {
- generated++;
- }
-
- public void ignored() {
- ignored++;
- }
-
- public void put() {
- puts++;
- }
-
- public void putIgnored() {
- puts_ignored++;
- }
-
-
- public int getHits() {
- return hits;
- }
-
- public int getMisses() {
- return misses;
- }
-
- public int getWeaved() {
- return weaved;
- }
-
- public int getGenerated() {
- return generated;
- }
-
- public int getIgnored() {
- return ignored;
- }
-
- public int getPuts() {
- return puts;
- }
-
- public int getPutsIgnored() {
- return puts_ignored;
- }
-
-
- public void reset() {
- hits = 0;
- misses = 0;
- weaved = 0;
- generated = 0;
- ignored = 0;
- puts = 0;
- puts_ignored = 0;
- }
-
- @Override
- public String toString() {
- return "CacheStatistics{" +
- "hits=" + hits +
- ", misses=" + misses +
- ", weaved=" + weaved +
- ", generated=" + generated +
- ", ignored=" + ignored +
- ", puts=" + puts +
- ", puts_ignored=" + puts_ignored +
- '}';
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/CachedClassEntry.java b/weaver/src/org/aspectj/weaver/tools/cache/CachedClassEntry.java
deleted file mode 100644
index db74e7f92..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/CachedClassEntry.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- * Lyor Goldstein (vmware) add support for weaved class being re-defined
- *******************************************************************************/
-package org.aspectj.weaver.tools.cache;
-
-/**
- * Represents a class which has been cached
- */
-public class CachedClassEntry {
- static enum EntryType {
- GENERATED,
- WEAVED,
- IGNORED,
- }
-
- private final CachedClassReference ref;
- private final byte[] weavedBytes;
- private final EntryType type;
-
- public CachedClassEntry(CachedClassReference ref, byte[] weavedBytes, EntryType type) {
- this.weavedBytes = weavedBytes;
- this.ref = ref;
- this.type = type;
- }
-
- public String getClassName() {
- return ref.getClassName();
- }
-
- public byte[] getBytes() {
- return weavedBytes;
- }
-
- public String getKey() {
- return ref.getKey();
- }
-
- public boolean isGenerated() {
- return type == EntryType.GENERATED;
- }
-
- public boolean isWeaved() {
- return type == EntryType.WEAVED;
- }
-
- public boolean isIgnored() {
- return type == EntryType.IGNORED;
- }
-
- @Override
- public int hashCode() {
- return getClassName().hashCode()
- + getKey().hashCode()
- + type.hashCode()
- ;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null)
- return false;
- if (this == obj)
- return true;
- if (getClass() != obj.getClass())
- return false;
-
- CachedClassEntry other=(CachedClassEntry) obj;
- if (getClassName().equals(other.getClassName())
- && getKey().equals(other.getKey())
- && (type == other.type)) {
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- public String toString() {
- return getClassName() + "[" + type + "]";
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/CachedClassReference.java b/weaver/src/org/aspectj/weaver/tools/cache/CachedClassReference.java
deleted file mode 100644
index 7d48ff171..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/CachedClassReference.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- * Lyor Goldstein (vmware) add support for weaved class being re-defined
- *******************************************************************************/
-
-package org.aspectj.weaver.tools.cache;
-
-/**
- * A typed reference to a cached class entry. The key to any
- * cache entry is a simple string, but that string may contain
- * some specialized encoding. This class handles all of that
- * encoding.
- * <p/>
- * External users of the cache should not be able to create these
- * objects manually.
- */
-public class CachedClassReference {
- static enum EntryType {
- GENERATED,
- WEAVED,
- IGNORED,
- }
-
- private final String key;
- private final String className;
-
- protected CachedClassReference(String key, CacheKeyResolver resolver) {
- this(key, resolver.keyToClass(key));
- }
-
- /**
- * Protected to allow only the WeavedClassCache initialization rights
- *
- * @param key encoded key of the class
- * @param className the classname
- */
- protected CachedClassReference(String key, String className) {
- this.key = key;
- this.className = className;
- }
-
- public String getKey() {
- return key;
- }
-
- public String getClassName() {
- return className;
- }
-
- @Override
- public int hashCode() {
- return getKey().hashCode() + getClassName().hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null)
- return false;
- if (this == obj)
- return true;
- if (getClass() != obj.getClass())
- return false;
-
- CachedClassReference other=(CachedClassReference) obj;
- if (getKey().equals(other.getKey())
- && getClassName().equals(other.getClassName())) {
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- public String toString() {
- return getClassName() + "[" + getKey() + "]";
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/DefaultCacheFactory.java b/weaver/src/org/aspectj/weaver/tools/cache/DefaultCacheFactory.java
deleted file mode 100644
index 7eb796e4b..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/DefaultCacheFactory.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- *******************************************************************************/
-
-package org.aspectj.weaver.tools.cache;
-
-/**
- * Default factory for creating the backing and resolving classes.
- */
-public class DefaultCacheFactory implements CacheFactory {
- public CacheKeyResolver createResolver() {
- return new DefaultCacheKeyResolver();
- }
-
- public CacheBacking createBacking(String scope) {
- return DefaultFileCacheBacking.createBacking(scope);
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/DefaultCacheKeyResolver.java b/weaver/src/org/aspectj/weaver/tools/cache/DefaultCacheKeyResolver.java
deleted file mode 100644
index 4951923d3..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/DefaultCacheKeyResolver.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- *******************************************************************************/
-
-package org.aspectj.weaver.tools.cache;
-
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.zip.CRC32;
-
-/**
- * Naive default class and classloader hashing implementation useful
- * for some multi-classloader environments.
- * <p/>
- * This implementation creates classloader scopes of the form:<br/>
- * "ExampleClassLoaderName.[crc hash]"
- * <p/>
- * And weaved class keys of the form:<br/>
- * "com.foo.BarClassName.[bytes len][crc].weaved"
- * <p/>
- * And generated class keys of the form:<br/>
- * "com.foo.BarClassName$AjClosure.generated
- */
-public class DefaultCacheKeyResolver implements CacheKeyResolver {
- public static final String GENERATED_SUFFIX = ".generated";
- public static final String WEAVED_SUFFIX = ".weaved";
-
- /**
- * Create a scope from a set of urls and aspect urls. Creates scope
- * of the form "ExampleClassLoaderName.[md5sum]" or
- * "ExampleClassLoaderName.[crc]"
- *
- * @param cl the classloader which uses the cache, can be null
- * @param aspects the aspects
- * @return a unique string for URLClassloaders, otherwise a non-unique classname
- */
- public String createClassLoaderScope(ClassLoader cl, List<String> aspects) {
- String name = cl != null ? cl.getClass().getSimpleName() : "unknown";
-
- List<String> hashableStrings = new LinkedList<String>();
- StringBuilder hashable = new StringBuilder(256);
-
- // Add the list of loader urls to the hash list
- if (cl != null && cl instanceof URLClassLoader) {
- URL[] urls = ((URLClassLoader) cl).getURLs();
- for (int i = 0; i < urls.length; i++) {
- hashableStrings.add(urls[i].toString());
- }
- }
-
- hashableStrings.addAll(aspects);
- Collections.sort(hashableStrings);
- for (Iterator<String> it = hashableStrings.iterator(); it.hasNext(); ) {
- String url = it.next();
- hashable.append(url);
- }
- String hash = null;
- byte[] bytes = hashable.toString().getBytes();
- hash = crc(bytes);
-
- return name + '.' + hash;
- }
-
- private String crc(byte[] input) {
- CRC32 crc32 = new CRC32();
- crc32.update(input);
- return String.valueOf(crc32.getValue());
- }
-
- public String getGeneratedRegex() {
- return ".*" + GENERATED_SUFFIX;
- }
-
- public String getWeavedRegex() {
- return ".*" + WEAVED_SUFFIX;
- }
-
-
- /**
- * Converts a cache key back to a className
- *
- * @param key to convert
- * @return className, e.g. "com.foo.Bar"
- */
- public String keyToClass(String key) {
- if (key.endsWith(GENERATED_SUFFIX)) {
- return key.replaceAll(GENERATED_SUFFIX + "$", "");
- }
- if (key.endsWith(WEAVED_SUFFIX)) {
- return key.replaceAll("\\.[^.]+" + WEAVED_SUFFIX, "");
- }
- return key;
- }
-
- public CachedClassReference weavedKey(String className, byte[] original_bytes) {
- String hash = crc(original_bytes);
- return new CachedClassReference(className + "." + hash + WEAVED_SUFFIX, className);
-
- }
-
- public CachedClassReference generatedKey(String className) {
- return new CachedClassReference(className + GENERATED_SUFFIX, className);
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/DefaultFileCacheBacking.java b/weaver/src/org/aspectj/weaver/tools/cache/DefaultFileCacheBacking.java
deleted file mode 100644
index 21543a80d..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/DefaultFileCacheBacking.java
+++ /dev/null
@@ -1,289 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- * Lyor Goldstein (vmware) add support for weaved class being re-defined
- *******************************************************************************/
-
-package org.aspectj.weaver.tools.cache;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FilenameFilter;
-import java.io.OutputStream;
-import java.util.Map;
-
-import org.aspectj.bridge.MessageUtil;
-import org.aspectj.util.FileUtil;
-import org.aspectj.util.LangUtil;
-
-
-/**
- * Naive File-Backed Class Cache with no expiry or application
- * centric invalidation.
- * <p/>
- * Enabled with the system property, "aj.weaving.cache.dir"
- * If this system property is not set, no caching will be
- * performed.
- * <p/>
- * A CRC checksum is stored alongside the class file to verify
- * the bytes on read. If for some reason there is an error
- * reading either the class or crc file, or if the crc does not
- * match the class data the cache entry is deleted.
- * <p/>
- * An alternate implementation of this could store the class file
- * as a jar/zip directly, which would have the required crc; as
- * a first pass however it is somewhat useful to view these files
- * in expanded form for debugging.
- */
-public class DefaultFileCacheBacking extends AbstractIndexedFileCacheBacking {
- private final Map<String, IndexEntry> index;
-
- private static final Object LOCK = new Object();
-
- protected DefaultFileCacheBacking(File cacheDir) {
- super(cacheDir);
- index = readIndex();
- }
-
- public static final DefaultFileCacheBacking createBacking(File cacheDir) {
- if (!cacheDir.exists()) {
- if (!cacheDir.mkdirs()) {
- MessageUtil.error("Unable to create cache directory at " + cacheDir.getName());
- return null;
- }
- } else if (!cacheDir.isDirectory()) {
- MessageUtil.error("Not a cache directory at " + cacheDir.getName());
- return null;
- }
-
- if (!cacheDir.canWrite()) {
- MessageUtil.error("Cache directory is not writable at " + cacheDir.getName());
- return null;
- }
- return new DefaultFileCacheBacking(cacheDir);
- }
-
- @Override
- protected Map<String, IndexEntry> getIndex() {
- return index;
- }
-
- @Override
- protected IndexEntry resolveIndexMapEntry (File cacheDir, IndexEntry ie) {
- File cacheEntry = new File(cacheDir, ie.key);
- if (ie.ignored || cacheEntry.canRead()) {
- return ie;
- } else {
- return null;
- }
- }
-
- private void removeIndexEntry(String key) {
- synchronized (LOCK) {
- index.remove(key);
- writeIndex();
- }
- }
-
- private void addIndexEntry(IndexEntry ie) {
- synchronized (LOCK) {
- index.put(ie.key, ie);
- writeIndex();
- }
- }
-
- @Override
- protected Map<String, IndexEntry> readIndex() {
- synchronized (LOCK) {
- return super.readIndex();
- }
- }
-
- @Override
- protected void writeIndex() {
- synchronized (LOCK) {
- super.writeIndex();
- }
- }
-
- public void clear() {
- File cacheDir=getCacheDirectory();
- int numDeleted=0;
- synchronized (LOCK) {
- numDeleted = FileUtil.deleteContents(cacheDir);
- }
-
- if ((numDeleted > 0) && (logger != null) && logger.isTraceEnabled()) {
- logger.info("clear(" + cacheDir + ") deleted");
- }
- }
-
- public static CacheBacking createBacking(String scope) {
- String cache = System.getProperty(WEAVED_CLASS_CACHE_DIR);
- if (cache == null) {
- return null;
- }
-
- File cacheDir = new File(cache, scope);
- return createBacking(cacheDir);
- }
-
- @Override
- public String[] getKeys(final String regex) {
- File cacheDirectory = getCacheDirectory();
- File[] files = cacheDirectory.listFiles(new FilenameFilter() {
- public boolean accept(File file, String s) {
- if (s.matches(regex)) {
- return true;
- }
- return false;
- }
- });
- if (LangUtil.isEmpty(files)) {
- return EMPTY_KEYS;
- }
- String[] keys = new String[files.length];
- for (int i = 0; i < files.length; i++) {
- keys[i] = files[i].getName();
- }
- return keys;
- }
-
- public CachedClassEntry get(CachedClassReference ref, byte[] originalBytes) {
- File cacheDirectory = getCacheDirectory();
- String refKey=ref.getKey();
- File cacheFile = new File(cacheDirectory, refKey);
- IndexEntry ie = index.get(refKey);
- if (ie == null) {
- // no index, delete
- delete(cacheFile);
- return null;
- }
-
- // check if original file changed
- if (crc(originalBytes) != ie.crcClass) {
- delete(cacheFile);
- return null;
- }
-
- if (ie.ignored) {
- return new CachedClassEntry(ref, WeavedClassCache.ZERO_BYTES, CachedClassEntry.EntryType.IGNORED);
- }
-
- if (cacheFile.canRead()) {
- byte[] bytes = read(cacheFile, ie.crcWeaved);
- if (bytes != null) {
- if (!ie.generated) {
- return new CachedClassEntry(ref, bytes, CachedClassEntry.EntryType.WEAVED);
- } else {
- return new CachedClassEntry(ref, bytes, CachedClassEntry.EntryType.GENERATED);
- }
- }
- }
-
- return null;
- }
-
- public void put(CachedClassEntry entry, byte[] originalBytes) {
- File cacheDirectory = getCacheDirectory();
- String refKey = entry.getKey();
- IndexEntry ie = index.get(refKey);
- File cacheFile = new File(cacheDirectory, refKey);
- final boolean writeEntryBytes;
- // check if original bytes changed or the ignored/generated flags
- if ((ie != null)
- && ((ie.ignored != entry.isIgnored()) || (ie.generated != entry.isGenerated()) || (crc(originalBytes) != ie.crcClass))) {
- delete(cacheFile);
- writeEntryBytes = true;
- } else {
- writeEntryBytes = !cacheFile.exists();
- }
-
- if (writeEntryBytes) {
- ie = createIndexEntry(entry, originalBytes);
- if (!entry.isIgnored()) {
- ie.crcWeaved = write(cacheFile, entry.getBytes());
- }
- addIndexEntry(ie);
- }
- }
-
- public void remove(CachedClassReference ref) {
- File cacheDirectory = getCacheDirectory();
- String refKey = ref.getKey();
- File cacheFile = new File(cacheDirectory, refKey);
- synchronized (LOCK) {
- removeIndexEntry(refKey);
- delete(cacheFile);
- }
- }
-
- @Override
- protected void delete(File file) {
- synchronized (LOCK) {
- super.delete(file);
- }
- }
-
- protected byte[] read(File file, long expectedCRC) {
- byte[] bytes=null;
- synchronized (LOCK) {
- FileInputStream fis = null;
- try {
- fis = new FileInputStream(file);
- bytes = FileUtil.readAsByteArray(fis);
- } catch (Exception e) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.warn("read(" + file.getAbsolutePath() + ")"
- + " failed (" + e.getClass().getSimpleName() + ")"
- + " to read contents: " + e.getMessage(), e);
- }
- } finally {
- close(fis, file);
- }
-
- // delete the file if there was an exception reading it or mismatched crc
- if ((bytes == null) || (crc(bytes) != expectedCRC)) {
- delete(file);
- return null;
- }
- }
-
- return bytes;
- }
-
- protected long write(File file, byte[] bytes) {
- synchronized (LOCK) {
- if (file.exists()) {
- return -1L;
- }
- OutputStream out = null;
- try {
- out = new FileOutputStream(file);
- out.write(bytes);
- } catch (Exception e) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.warn("write(" + file.getAbsolutePath() + ")"
- + " failed (" + e.getClass().getSimpleName() + ")"
- + " to write contents: " + e.getMessage(), e);
- }
- // delete the file if there was an exception writing it
- delete(file);
- return -1L;
- } finally {
- close(out, file);
- }
-
- return crc(bytes);
- }
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/FlatFileCacheBacking.java b/weaver/src/org/aspectj/weaver/tools/cache/FlatFileCacheBacking.java
deleted file mode 100644
index 6de416a80..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/FlatFileCacheBacking.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2012 VMware, Inc. custard
- *
- * 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:
- * Lyor Goldstein
- * ******************************************************************/
-
-package org.aspectj.weaver.tools.cache;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.StreamCorruptedException;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.aspectj.util.FileUtil;
-import org.aspectj.util.LangUtil;
-
-/**
- * Uses a &quot;flat&quot files model to store the cached instrumented classes
- * and aspects - i.e., each class/aspect is stored as a <U>separate</U> (binary)
- * file. This is a good mechanism when the number of instrumented class is
- * relatively small (a few 10's). The reason for it is that scanning a folder
- * that has many files in it quickly becomes an I/O bottleneck. Also, some
- * O/S-es may impose internal limits on the maximum number of &quot;children&quot;
- * a folder node may have. On the other hand, it is much faster (again, for
- * small number of instrumented classes) than the ZIP cache since each class/aspect
- * is represented by a single file - thus adding/removing/modifying it is easier.
- *
- * @author Lyor Goldstein
- */
-public class FlatFileCacheBacking extends AsynchronousFileCacheBacking {
- private static final AsynchronousFileCacheBackingCreator<FlatFileCacheBacking> defaultCreator=
- new AsynchronousFileCacheBackingCreator<FlatFileCacheBacking>() {
- public FlatFileCacheBacking create(File cacheDir) {
- return new FlatFileCacheBacking(cacheDir);
- }
- };
- public FlatFileCacheBacking(File cacheDir) {
- super(cacheDir);
- }
-
- public static final FlatFileCacheBacking createBacking (File cacheDir) {
- return createBacking(cacheDir, defaultCreator);
- }
-
- @Override
- protected Map<String, byte[]> readClassBytes(Map<String, IndexEntry> indexMap, File cacheDir) {
- return readClassBytes(indexMap, cacheDir.listFiles());
- }
-
- protected Map<String, byte[]> readClassBytes (Map<String,IndexEntry> indexMap, File[] files) {
- Map<String, byte[]> result=new TreeMap<String, byte[]>();
- if (LangUtil.isEmpty(files)) {
- return result;
- }
-
- for (File file : files) {
- if (!file.isFile()) {
- continue; // skip sub-directories - we expect flat files
- }
-
- String key=file.getName();
- if (INDEX_FILE.equalsIgnoreCase(key)) {
- continue; // skip the index itself if found
- }
-
- IndexEntry entry=indexMap.get(key);
- if ((entry == null) || entry.ignored) { // if not in index or ignored then remove it
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.info("readClassBytes(" + key + ") remove orphan/ignored: " + file.getAbsolutePath());
- }
- FileUtil.deleteContents(file);
- continue;
- }
-
- try {
- byte[] bytes=FileUtil.readAsByteArray(file);
- long crc=crc(bytes);
- if (crc != entry.crcWeaved) {
- throw new StreamCorruptedException("Mismatched CRC - expected=" + entry.crcWeaved + "/got=" + crc);
- }
-
- result.put(key, bytes);
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.debug("readClassBytes(" + key + ") cached from " + file.getAbsolutePath());
- }
- } catch(IOException e) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.error("Failed (" + e.getClass().getSimpleName() + ")"
- + " to read bytes from " + file.getAbsolutePath()
- + ": " + e.getMessage());
- }
- indexMap.remove(key); // no need for the entry if no file - force a re-write of its bytes
- FileUtil.deleteContents(file); // assume some kind of corruption
- continue;
- }
- }
-
- return result;
- }
-
- @Override
- protected IndexEntry resolveIndexMapEntry (File cacheDir, IndexEntry ie) {
- File cacheEntry = new File(cacheDir, ie.key);
- if (ie.ignored || cacheEntry.canRead()) {
- return ie;
- } else {
- return null;
- }
- }
-
- @Override
- protected void writeClassBytes (String key, byte[] bytes) throws Exception {
- File dir=getCacheDirectory(), file=new File(dir, key);
- FileOutputStream out=new FileOutputStream(file);
- try {
- out.write(bytes);
- } finally {
- out.close();
- }
- }
-
- @Override
- protected void removeClassBytes (String key) throws Exception {
- File dir=getCacheDirectory(), file=new File(dir, key);
- if (file.exists() && (!file.delete())) {
- throw new StreamCorruptedException("Failed to delete " + file.getAbsolutePath());
- }
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/GeneratedCachedClassHandler.java b/weaver/src/org/aspectj/weaver/tools/cache/GeneratedCachedClassHandler.java
deleted file mode 100644
index 91c332b6b..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/GeneratedCachedClassHandler.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- * Lyor Goldstein (vmware) add support for weaved class being re-defined
- *******************************************************************************/
-
-package org.aspectj.weaver.tools.cache;
-
-import org.aspectj.weaver.tools.GeneratedClassHandler;
-
-/**
- * Handler for generated classes; such as Shadowed closures, etc. This wraps the normal
- * generated class handler with caching
- */
-public class GeneratedCachedClassHandler implements GeneratedClassHandler {
- private final WeavedClassCache cache;
- private final GeneratedClassHandler nextGeneratedClassHandler;
-
- public GeneratedCachedClassHandler(WeavedClassCache cache, GeneratedClassHandler nextHandler) {
- this.cache = cache;
- this.nextGeneratedClassHandler = nextHandler;
- }
-
- public void acceptClass (String name, byte[] originalBytes, byte[] wovenBytes) {
- // The cache expects classNames in dot form
- CachedClassReference ref = cache.createGeneratedCacheKey(name.replace('/', '.'));
- cache.put(ref, originalBytes, wovenBytes);
- if (nextGeneratedClassHandler != null) {
- nextGeneratedClassHandler.acceptClass(name, originalBytes, wovenBytes);
- }
- }
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/SimpleCache.java b/weaver/src/org/aspectj/weaver/tools/cache/SimpleCache.java
deleted file mode 100644
index 45d718a14..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/SimpleCache.java
+++ /dev/null
@@ -1,377 +0,0 @@
-package org.aspectj.weaver.tools.cache;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.zip.CRC32;
-
-import org.aspectj.weaver.Dump;
-import org.aspectj.weaver.tools.Trace;
-import org.aspectj.weaver.tools.TraceFactory;
-
-
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * Abraham Nevado (lucierna) initial implementation
- ********************************************************************************/
-
-public class SimpleCache {
-
- private static final String SAME_BYTES_STRING = "IDEM";
- private static final byte[] SAME_BYTES = SAME_BYTES_STRING.getBytes();
-
- private Map<String, byte[]> cacheMap;
- private boolean enabled = false;
-
- // cache for generated classes
- private Map<String, byte[]> generatedCache;
- private static final String GENERATED_CACHE_SUBFOLDER = "panenka.cache";
- private static final String GENERATED_CACHE_SEPARATOR = ";";
-
- public static final String IMPL_NAME = "shared";
-
- protected SimpleCache(String folder, boolean enabled) {
- this.enabled = enabled;
-
- cacheMap = Collections.synchronizedMap(StoreableCachingMap.init(folder));
-
- if (enabled) {
- String generatedCachePath = folder + File.separator + GENERATED_CACHE_SUBFOLDER;
- File f = new File (generatedCachePath);
- if (!f.exists()){
- f.mkdir();
- }
- generatedCache = Collections.synchronizedMap(StoreableCachingMap.init(generatedCachePath,0));
- }
- }
-
- public byte[] getAndInitialize(String classname, byte[] bytes,
- ClassLoader loader, ProtectionDomain protectionDomain) {
- if (!enabled) {
- return null;
- }
- byte[] res = get(classname, bytes);
-
- if (Arrays.equals(SAME_BYTES, res)) {
- return bytes;
- } else {
- if (res != null) {
- initializeClass(classname, res, loader, protectionDomain);
- }
- return res;
- }
-
- }
-
- private byte[] get(String classname, byte bytes[]) {
- String key = generateKey(classname, bytes);
-
- byte[] res = cacheMap.get(key);
- return res;
- }
-
- public void put(String classname, byte[] origbytes, byte[] wovenbytes) {
- if (!enabled) {
- return;
- }
-
- String key = generateKey(classname, origbytes);
-
- if (Arrays.equals(origbytes, wovenbytes)) {
- cacheMap.put(key, SAME_BYTES);
- return;
- }
- cacheMap.put(key, wovenbytes);
- }
-
- private String generateKey(String classname, byte[] bytes) {
- CRC32 checksum = new CRC32();
- checksum.update(bytes);
- long crc = checksum.getValue();
- classname = classname.replace("/", ".");
- return new String(classname + "-" + crc);
-
- }
-
- private static class StoreableCachingMap extends HashMap {
- private String folder;
- private static final String CACHENAMEIDX = "cache.idx";
-
- private long lastStored = System.currentTimeMillis();
- private static int DEF_STORING_TIMER = 60000; //ms
- private int storingTimer;
-
- private transient Trace trace;
- private void initTrace(){
- trace = TraceFactory.getTraceFactory().getTrace(StoreableCachingMap.class);
- }
-
-// private StoreableCachingMap(String folder) {
-// this.folder = folder;
-// initTrace();
-// }
-
- private StoreableCachingMap(String folder, int storingTimer){
- this.folder = folder;
- initTrace();
- this.storingTimer = storingTimer;
- }
-
- public static StoreableCachingMap init(String folder) {
- return init(folder,DEF_STORING_TIMER);
-
- }
-
- public static StoreableCachingMap init(String folder, int storingTimer) {
- File file = new File(folder + File.separator + CACHENAMEIDX);
- if (file.exists()) {
- try {
- ObjectInputStream in = new ObjectInputStream(
- new FileInputStream(file));
- // Deserialize the object
- StoreableCachingMap sm = (StoreableCachingMap) in.readObject();
- sm.initTrace();
- in.close();
- return sm;
- } catch (Exception e) {
- Trace trace = TraceFactory.getTraceFactory().getTrace(StoreableCachingMap.class);
- trace.error("Error reading Storable Cache", e);
- }
- }
-
- return new StoreableCachingMap(folder,storingTimer);
-
- }
-
- @Override
- public Object get(Object obj) {
- try {
- if (super.containsKey(obj)) {
- String path = (String) super.get(obj);
- if (path.equals(SAME_BYTES_STRING)) {
- return SAME_BYTES;
- }
- return readFromPath(path);
- } else {
- return null;
- }
- } catch (IOException e) {
- trace.error("Error reading key:"+obj.toString(),e);
- Dump.dumpWithException(e);
- }
- return null;
- }
-
- @Override
- public Object put(Object key, Object value) {
- try {
- String path = null;
- byte[] valueBytes = (byte[]) value;
-
- if (Arrays.equals(valueBytes, SAME_BYTES)) {
- path = SAME_BYTES_STRING;
- } else {
- path = writeToPath((String) key, valueBytes);
- }
- Object result = super.put(key, path);
- storeMap();
- return result;
- } catch (IOException e) {
- trace.error("Error inserting in cache: key:"+key.toString() + "; value:"+value.toString(), e);
- Dump.dumpWithException(e);
- }
- return null;
- }
-
-
-
- public void storeMap() {
- long now = System.currentTimeMillis();
- if ((now - lastStored ) < storingTimer){
- return;
- }
- File file = new File(folder + File.separator + CACHENAMEIDX);;
- try {
- ObjectOutputStream out = new ObjectOutputStream(
- new FileOutputStream(file));
- // Deserialize the object
- out.writeObject(this);
- out.close();
- lastStored = now;
- } catch (Exception e) {
- trace.error("Error storing cache; cache file:"+file.getAbsolutePath(), e);
- Dump.dumpWithException(e);
- }
- }
-
- private byte[] readFromPath(String fullPath) throws IOException {
- FileInputStream is = null ;
- try{
- is = new FileInputStream(fullPath);
- }
- catch (FileNotFoundException e){
- //may be caused by a generated class that has been stored in generated cache but not saved at cache folder
- System.out.println("FileNotFoundExceptions: The aspectj cache is corrupt. Please clean it and reboot the server. Cache path:"+this.folder );
- e.printStackTrace();
- return null;
- }
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-
- int nRead;
- byte[] data = new byte[16384];
-
- while ((nRead = is.read(data, 0, data.length)) != -1) {
- buffer.write(data, 0, nRead);
- }
-
- buffer.flush();
- is.close();
- return buffer.toByteArray();
-
- }
-
- private String writeToPath(String key, byte[] bytes) throws IOException {
- String fullPath = folder + File.separator + key;
- FileOutputStream fos = new FileOutputStream(fullPath);
- fos.write(bytes);
- fos.flush();
- fos.close();
- return fullPath;
- }
-
- }
-
- private void initializeClass(String className, byte[] bytes,
- ClassLoader loader, ProtectionDomain protectionDomain) {
- String[] generatedClassesNames = getGeneratedClassesNames(className,bytes);
-
- if (generatedClassesNames == null) {
- return;
- }
- for (String generatedClassName : generatedClassesNames) {
-
- byte[] generatedBytes = get(generatedClassName, bytes);
-
- if (protectionDomain == null) {
- defineClass(loader, generatedClassName, generatedBytes);
- } else {
- defineClass(loader, generatedClassName, generatedBytes,
- protectionDomain);
- }
-
- }
-
- }
-
- private String[] getGeneratedClassesNames(String className, byte[] bytes) {
- String key = generateKey(className, bytes);
-
- byte[] readBytes = generatedCache.get(key);
- if (readBytes == null) {
- return null;
- }
- String readString = new String(readBytes);
- return readString.split(GENERATED_CACHE_SEPARATOR);
- }
-
- public void addGeneratedClassesNames(String parentClassName, byte[] parentBytes, String generatedClassName) {
- if (!enabled) {
- return;
- }
- String key = generateKey(parentClassName, parentBytes);
-
- byte[] storedBytes = generatedCache.get(key);
- if (storedBytes == null) {
- generatedCache.put(key, generatedClassName.getBytes());
- } else {
- String storedClasses = new String(storedBytes);
- storedClasses += GENERATED_CACHE_SEPARATOR + generatedClassName;
- generatedCache.put(key, storedClasses.getBytes());
- }
- }
-
- private Method defineClassMethod = null;
- private Method defineClassWithProtectionDomainMethod = null;
-
- private void defineClass(ClassLoader loader, String name, byte[] bytes) {
-
- Object clazz = null;
-
- try {
- if (defineClassMethod == null) {
- defineClassMethod = ClassLoader.class.getDeclaredMethod(
- "defineClass", new Class[] { String.class,
- bytes.getClass(), int.class, int.class });
- }
- defineClassMethod.setAccessible(true);
- clazz = defineClassMethod.invoke(loader, new Object[] { name,
- bytes, new Integer(0), new Integer(bytes.length) });
- } catch (InvocationTargetException e) {
- if (e.getTargetException() instanceof LinkageError) {
- e.printStackTrace();
- } else {
- System.out.println("define generated class failed"
- + e.getTargetException());
- }
- } catch (Exception e) {
- e.printStackTrace();
- Dump.dumpWithException(e);
- }
- }
-
- private void defineClass(ClassLoader loader, String name, byte[] bytes,
- ProtectionDomain protectionDomain) {
-
- Object clazz = null;
-
- try {
- // System.out.println(">> Defining with protection domain " + name +
- // " pd=" + protectionDomain);
- if (defineClassWithProtectionDomainMethod == null) {
- defineClassWithProtectionDomainMethod = ClassLoader.class
- .getDeclaredMethod("defineClass", new Class[] {
- String.class, bytes.getClass(), int.class,
- int.class, ProtectionDomain.class });
- }
- defineClassWithProtectionDomainMethod.setAccessible(true);
- clazz = defineClassWithProtectionDomainMethod.invoke(loader,
- new Object[] { name, bytes, Integer.valueOf(0),
- new Integer(bytes.length), protectionDomain });
- } catch (InvocationTargetException e) {
- if (e.getTargetException() instanceof LinkageError) {
- e.printStackTrace();
- // is already defined (happens for X$ajcMightHaveAspect
- // interfaces since aspects are reweaved)
- // TODO maw I don't think this is OK and
- } else {
- e.printStackTrace();
- }
- }catch (NullPointerException e) {
- System.out.println("NullPointerException loading class:"+name+". Probabily caused by a corruput cache. Please clean it and reboot the server");
- } catch (Exception e) {
- e.printStackTrace();
- Dump.dumpWithException(e);
- }
-
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/SimpleCacheFactory.java b/weaver/src/org/aspectj/weaver/tools/cache/SimpleCacheFactory.java
deleted file mode 100644
index 49569dd0e..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/SimpleCacheFactory.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * Abraham Nevado (lucierna) initial implementation
- ********************************************************************************/
-
-package org.aspectj.weaver.tools.cache;
-
-import java.io.File;
-
-import org.aspectj.weaver.Dump;
-
-public class SimpleCacheFactory {
-
- public static final String CACHE_ENABLED_PROPERTY = "aj.weaving.cache.enabled";
- public static final String CACHE_DIR = "aj.weaving.cache.dir";
- public static final String CACHE_IMPL = "aj.weaving.cache.impl";
-
- public static final String PATH_DEFAULT= "/tmp/"; // TODO windows default...?
- public static final boolean BYDEFAULT= false;
-
-
- public static String path = PATH_DEFAULT;
- public static Boolean enabled = false;
- private static boolean determinedIfEnabled = false;
- private static SimpleCache lacache=null;
-
- public static synchronized SimpleCache createSimpleCache(){
- if (lacache==null){
- if (!determinedIfEnabled) {
- determineIfEnabled();
- }
-
- if (!enabled) {
- return null;
- }
-
- try {
- path = System.getProperty(CACHE_DIR);
- if (path == null){
- path = PATH_DEFAULT;
- }
-
- } catch (Throwable t) {
- path=PATH_DEFAULT;
- t.printStackTrace();
- Dump.dumpWithException(t);
- }
- File f = new File(path);
- if (!f.exists()){
- f.mkdir();
- }
- lacache= new SimpleCache(path, enabled);
- }
- return lacache;
-
- }
-
- private static void determineIfEnabled() {
- try {
- String property = System.getProperty(CACHE_ENABLED_PROPERTY);
- if (property == null ){
- enabled = BYDEFAULT;
- }
- else if (property.equalsIgnoreCase("true")){
-
- String impl = System.getProperty(CACHE_IMPL);
- if (SimpleCache.IMPL_NAME.equals(impl)){
- enabled = true;
- }
- else{
- enabled = BYDEFAULT;
- }
- }
- else{
- enabled = BYDEFAULT;
- }
-
- } catch (Throwable t) {
- enabled=BYDEFAULT;
- System.err.println("Error creating cache");
- t.printStackTrace();
- Dump.dumpWithException(t);
- }
- determinedIfEnabled = true;
- }
-
- // Should behave ok with two threads going through here, well whoever gets there first will set determinedIfEnabled but only after
- // it has set 'enabled' to the right value.
- public static boolean isEnabled() {
- if (!determinedIfEnabled) {
- determineIfEnabled();
- }
- return enabled;
- }
-
-
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/WeavedClassCache.java b/weaver/src/org/aspectj/weaver/tools/cache/WeavedClassCache.java
deleted file mode 100644
index b281d412f..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/WeavedClassCache.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * John Kew (vmware) initial implementation
- * Lyor Goldstein (vmware) add support for weaved class being re-defined
- *******************************************************************************/
-
-package org.aspectj.weaver.tools.cache;
-
-import org.aspectj.bridge.IMessage;
-import org.aspectj.bridge.IMessageHandler;
-import org.aspectj.bridge.Message;
-import org.aspectj.bridge.MessageUtil;
-import org.aspectj.weaver.tools.GeneratedClassHandler;
-
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Manages a cache of weaved and generated classes similar to Eclipse Equinox,
- * except designed to operate across multiple restarts of the JVM and with one
- * cache per classloader; allowing URLClassLoaders with the same set of URI
- * paths to share the same cache (with the default configuration).
- * <p/>
- * To enable the default configuration two system properties must be set:
- * <pre>
- * "-Daj.weaving.cache.enabled=true"
- * "-Daj.weaving.cache.dir=/some/directory"
- * </pre>
- * <p/>
- * The class cache is often something that application developers or
- * containers would like to manage, so there are a few interfaces for overriding the
- * default behavior and performing other management functions.
- * <p/>
- * {@link CacheBacking} <br/>
- * Provides an interface for implementing a custom backing store
- * for the cache; The default implementation in {@link DefaultFileCacheBacking}
- * provides a naive file-backed cache. An alternate implementation may ignore
- * caching until signaled explicitly by the application, or only cache files
- * for a specific duration. This class delegates the locking and synchronization
- * requirements to the CacheBacking implementation.
- * <p/>
- * {@link CacheKeyResolver} <br/>
- * Provides methods for creating keys from classes to be cached and for
- * creating the "scope" of the cache itself for a given classloader and aspect
- * list. The default implementation is provided by {@link DefaultCacheKeyResolver}
- * but an alternate implementation may want to associate a cache with a particular
- * application running underneath a container.
- * <p/>
- * This naive cache does not normally invalidate *any* classes; the interfaces above
- * must be used to implement more intelligent behavior. Cache invalidation
- * problems may occur in at least three scenarios:
- * <pre>
- * 1. New aspects are added dynamically somewhere in the classloader hierarchy; affecting
- * other classes elsewhere.
- * 2. Use of declare parent in aspects to change the type hierarchy; if the cache
- * has not invalidated the right classes in the type hierarchy aspectj may not
- * be reconstruct the class incorrectly.
- * 3. Similarly to (2), the addition of fields or methods on classes which have
- * already been weaved and cached could have inter-type conflicts.
- * </pre>
- */
-public class WeavedClassCache {
- public static final String WEAVED_CLASS_CACHE_ENABLED = "aj.weaving.cache.enabled";
- public static final String CACHE_IMPL = SimpleCacheFactory.CACHE_IMPL;
- private static CacheFactory DEFAULT_FACTORY = new DefaultCacheFactory();
- public static final byte[] ZERO_BYTES = new byte[0];
- private final IMessageHandler messageHandler;
- private final GeneratedCachedClassHandler cachingClassHandler;
- private final CacheBacking backing;
- private final CacheStatistics stats;
- private final CacheKeyResolver resolver;
- private final String name;
-
- private static final List<WeavedClassCache> cacheRegistry = new LinkedList<WeavedClassCache>();
-
- protected WeavedClassCache(GeneratedClassHandler existingClassHandler,
- IMessageHandler messageHandler,
- String name,
- CacheBacking backing,
- CacheKeyResolver resolver) {
- this.resolver = resolver;
- this.name = name;
- this.backing = backing;
- this.messageHandler = messageHandler;
- // wrap the existing class handler with a caching version
- cachingClassHandler = new GeneratedCachedClassHandler(this, existingClassHandler);
- this.stats = new CacheStatistics();
- synchronized (cacheRegistry) {
- cacheRegistry.add(this);
- }
- }
-
- /**
- * Creates a new cache using the resolver and backing returned by the DefaultCacheFactory.
- *
- * @param loader classloader for this cache
- * @param aspects list of aspects used by the WeavingAdapter
- * @param existingClassHandler the existing GeneratedClassHandler used by the weaver
- * @param messageHandler the existing messageHandler used by the weaver
- * @return
- */
- public static WeavedClassCache createCache(ClassLoader loader, List<String> aspects, GeneratedClassHandler existingClassHandler, IMessageHandler messageHandler) {
- CacheKeyResolver resolver = DEFAULT_FACTORY.createResolver();
- String name = resolver.createClassLoaderScope(loader, aspects);
- if (name == null) {
- return null;
- }
- CacheBacking backing = DEFAULT_FACTORY.createBacking(name);
- if (backing != null) {
- return new WeavedClassCache(existingClassHandler, messageHandler, name, backing, resolver);
- }
- return null;
- }
-
- public String getName() {
- return name;
- }
-
- /**
- * The Cache and be extended in two ways, through a specialized CacheKeyResolver and
- * a specialized CacheBacking. The default factory used to create these classes can
- * be set with this method. Since each weaver will create a cache, this method must be
- * called before the weaver is first initialized.
- *
- * @param factory
- */
- public static void setDefaultCacheFactory(CacheFactory factory) {
- DEFAULT_FACTORY = factory;
- }
-
- /**
- * Created a key for a generated class
- *
- * @param className ClassName, e.g. "com.foo.Bar"
- * @return the cache key, or null if no caching should be performed
- */
- public CachedClassReference createGeneratedCacheKey(String className) {
- return resolver.generatedKey(className);
- }
-
- /**
- * Create a key for a normal weaved class
- *
- * @param className ClassName, e.g. "com.foo.Bar"
- * @param originalBytes Original byte array of the class
- * @return a cache key, or null if no caching should be performed
- */
- public CachedClassReference createCacheKey(String className, byte[] originalBytes) {
- return resolver.weavedKey(className, originalBytes);
- }
-
- /**
- * Returns a generated class handler which wraps the handler this cache was initialized
- * with; this handler should be used to make sure that generated classes are added
- * to the cache
- */
- public GeneratedClassHandler getCachingClassHandler() {
- return cachingClassHandler;
- }
-
- /**
- * Has caching been enabled through the System property,
- * WEAVED_CLASS_CACHE_ENABLED
- *
- * @return true if caching is enabled
- */
- public static boolean isEnabled() {
- String enabled = System.getProperty(WEAVED_CLASS_CACHE_ENABLED);
- String impl = System.getProperty(CACHE_IMPL);
- return (enabled != null && (impl == null || !SimpleCache.IMPL_NAME.equalsIgnoreCase(impl) ) );
- }
-
- /**
- * Put a class in the cache
- *
- * @param ref reference to the entry, as created through createCacheKey
- * @param classBytes pre-weaving class bytes
- * @param weavedBytes bytes to cache
- */
- public void put(CachedClassReference ref, byte[] classBytes, byte[] weavedBytes) {
- CachedClassEntry.EntryType type = CachedClassEntry.EntryType.WEAVED;
- if (ref.getKey().matches(resolver.getGeneratedRegex())) {
- type = CachedClassEntry.EntryType.GENERATED;
- }
- backing.put(new CachedClassEntry(ref, weavedBytes, type), classBytes);
- stats.put();
- }
-
- /**
- * Get a cache value
- *
- * @param ref reference to the cache entry, created through createCacheKey
- * @param classBytes Pre-weaving class bytes - required to ensure that
- * cached aspects refer to an unchanged original class
- * @return the CacheEntry, or null if no entry exists in the cache
- */
- public CachedClassEntry get(CachedClassReference ref, byte[] classBytes) {
- CachedClassEntry entry = backing.get(ref, classBytes);
- if (entry == null) {
- stats.miss();
- } else {
- stats.hit();
- if (entry.isGenerated()) stats.generated();
- if (entry.isWeaved()) stats.weaved();
- if (entry.isIgnored()) stats.ignored();
- }
- return entry;
- }
-
- /**
- * Put a cache entry to indicate that the class should not be
- * weaved; the original bytes of the class should be used.
- *
- * @param ref The cache reference
- * @param classBytes The un-weaved class bytes
- */
- public void ignore(CachedClassReference ref, byte[] classBytes) {
- stats.putIgnored();
- backing.put(new CachedClassEntry(ref, ZERO_BYTES, CachedClassEntry.EntryType.IGNORED), classBytes);
- }
-
- /**
- * Invalidate a cache entry
- *
- * @param ref
- */
- public void remove(CachedClassReference ref) {
- backing.remove(ref);
- }
-
- /**
- * Clear the entire cache
- */
- public void clear() {
- backing.clear();
- }
-
- /**
- * Get the statistics associated with this cache, or
- * null if statistics have not been enabled.
- *
- * @return
- */
- public CacheStatistics getStats() {
- return stats;
- }
-
- /**
- * Return a list of all WeavedClassCaches which have been initialized
- *
- * @return
- */
- public static List<WeavedClassCache> getCaches() {
- synchronized (cacheRegistry) {
- return new LinkedList<WeavedClassCache>(cacheRegistry);
- }
- }
-
- protected void error(String message, Throwable th) {
- messageHandler.handleMessage(new Message(message, IMessage.ERROR, th, null));
- }
-
- protected void error(String message) {
- MessageUtil.error(messageHandler, message);
- }
-
- protected void info(String message) {
- MessageUtil.info(message);
- }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/cache/ZippedFileCacheBacking.java b/weaver/src/org/aspectj/weaver/tools/cache/ZippedFileCacheBacking.java
deleted file mode 100644
index 6ee8b728c..000000000
--- a/weaver/src/org/aspectj/weaver/tools/cache/ZippedFileCacheBacking.java
+++ /dev/null
@@ -1,321 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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:
- * Lyor Goldstein (vmware) add support for weaved class being re-defined
- *******************************************************************************/
-
-package org.aspectj.weaver.tools.cache;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StreamCorruptedException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-import java.util.zip.ZipOutputStream;
-
-import org.aspectj.util.FileUtil;
-import org.aspectj.util.LangUtil;
-
-/**
- * Uses a ZIP file to store the instrumented classes/aspects - each one as a
- * <U>separate</U> {@link ZipEntry}. This mechanism is suitable for relatively
- * large numbers of instrumented classes/aspects (100's and more) since it
- * holds all of them in a single (ZIP) file. The down side is that any
- * modifications to the cache require re-writing the entire ZIP file. This
- * can cause the ZIP file to become corrupted if interrupted in mid-update,
- * thus requiring the re-population of the cache on next application activation
- * (though the overhead in this case is not prohibitvely high...)
- */
-public class ZippedFileCacheBacking extends AsynchronousFileCacheBacking {
- public static final String ZIP_FILE = "cache.zip";
- private static final AsynchronousFileCacheBackingCreator<ZippedFileCacheBacking> defaultCreator=
- new AsynchronousFileCacheBackingCreator<ZippedFileCacheBacking>() {
- public ZippedFileCacheBacking create(File cacheDir) {
- return new ZippedFileCacheBacking(cacheDir);
- }
- };
-
- private final File zipFile;
- public ZippedFileCacheBacking(File cacheDir) {
- super(cacheDir);
- zipFile = new File(cacheDir, ZIP_FILE);
- }
-
- public File getZipFile () {
- return zipFile;
- }
-
- public static final ZippedFileCacheBacking createBacking (File cacheDir) {
- return createBacking(cacheDir, defaultCreator);
- }
-
- @Override
- protected void writeClassBytes(String key, byte[] bytes) throws Exception {
- File outFile=getZipFile();
- Map<String,byte[]> entriesMap;
- try {
- entriesMap = readZipClassBytes(outFile);
- } catch(Exception e) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.warn("writeClassBytes(" + outFile + ")[" + key + "]"
- + " failed (" + e.getClass().getSimpleName() + ")"
- + " to read current data: " + e.getMessage(),
- e);
- }
-
- FileUtil.deleteContents(outFile);
- return;
- }
-
- if (entriesMap.isEmpty()) {
- entriesMap = Collections.singletonMap(key, bytes);
- } else {
- entriesMap.put(key, bytes);
- }
-
- try {
- writeZipClassBytes(outFile, entriesMap);
- } catch(Exception e) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.warn("writeClassBytes(" + outFile + ")[" + key + "]"
- + " failed (" + e.getClass().getSimpleName() + ")"
- + " to write updated data: " + e.getMessage(),
- e);
- }
-
- FileUtil.deleteContents(outFile);
- }
- }
-
- @Override
- protected void removeClassBytes(String key) throws Exception {
- File outFile=getZipFile();
- Map<String,byte[]> entriesMap;
- try {
- entriesMap = readZipClassBytes(outFile);
- } catch(Exception e) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.warn("removeClassBytes(" + outFile + ")[" + key + "]"
- + " failed (" + e.getClass().getSimpleName() + ")"
- + " to read current data: " + e.getMessage(),
- e);
- }
-
- FileUtil.deleteContents(outFile);
- return;
- }
-
- if (!entriesMap.isEmpty()) {
- if (entriesMap.remove(key) == null) {
- return; // not in the data file to begin with so nothing to update
- }
- }
-
- try {
- writeZipClassBytes(outFile, entriesMap);
- } catch(Exception e) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.warn("removeClassBytes(" + outFile + ")[" + key + "]"
- + " failed (" + e.getClass().getSimpleName() + ")"
- + " to write updated data: " + e.getMessage(),
- e);
- }
-
- FileUtil.deleteContents(outFile);
- }
- }
-
- @Override
- protected Map<String, byte[]> readClassBytes(Map<String, IndexEntry> indexMap, File cacheDir) {
- File dataFile=new File(cacheDir, ZIP_FILE);
- Map<String,byte[]> entriesMap;
- boolean okEntries=true;
- try {
- entriesMap = readZipClassBytes(dataFile);
- } catch(Exception e) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.warn("Failed (" + e.getClass().getSimpleName() + ")"
- + " to read zip entries from " + dataFile
- + ": " + e.getMessage(),
- e);
- }
-
- entriesMap = new TreeMap<String,byte[]>();
- okEntries = false;
- }
-
- if (!syncClassBytesEntries(dataFile, indexMap, entriesMap)) {
- okEntries = false;
- }
-
- if (!okEntries) {
- FileUtil.deleteContents(dataFile);
-
- if (!entriesMap.isEmpty()) {
- entriesMap.clear();
- }
- }
-
- syncIndexEntries(dataFile, indexMap, entriesMap);
-
- return entriesMap;
- }
-
- // remove all non-ignored entries that have no class bytes
- protected Collection<String> syncIndexEntries (File dataFile, Map<String, IndexEntry> indexMap, Map<String,byte[]> entriesMap) {
- Collection<String> toDelete=null;
- for (Map.Entry<String, IndexEntry> ie : indexMap.entrySet()) {
- String key=ie.getKey();
- IndexEntry indexEntry=ie.getValue();
- if (indexEntry.ignored) {
- continue; // ignored entries have no class bytes
- }
-
- if (entriesMap.containsKey(key)) {
- continue;
- }
-
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.debug("syncIndexEntries(" + dataFile + ")[" + key + "] no class bytes");
- }
-
- if (toDelete == null) {
- toDelete = new TreeSet<String>();
- }
- toDelete.add(key);
- }
-
- if (toDelete == null) {
- return Collections.emptySet();
- }
-
- for (String key : toDelete) {
- indexMap.remove(key);
- }
-
- return toDelete;
- }
-
- // check if all class bytes entries are valid
- protected boolean syncClassBytesEntries (File dataFile, Map<String, IndexEntry> indexMap, Map<String,byte[]> entriesMap) {
- boolean okEntries=true;
-
- for (Map.Entry<String,byte[]> bytesEntry : entriesMap.entrySet()) {
- String key=bytesEntry.getKey();
- IndexEntry indexEntry=indexMap.get(key);
- // ignored entries should have no bytes
- if ((indexEntry == null) || indexEntry.ignored) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.debug("syncClassBytesEntries(" + dataFile + ")[" + key + "] bad index entry");
- }
-
- okEntries = false;
- continue;
- }
-
- long crc=crc(bytesEntry.getValue());
- if (crc != indexEntry.crcWeaved) {
- if ((logger != null) && logger.isTraceEnabled()) {
- logger.debug("syncClassBytesEntries(" + dataFile + ")[" + key + "]"
- + " mismatched CRC - expected=" + indexEntry.crcWeaved + "/got=" + crc);
- }
-
- indexMap.remove(key);
- okEntries = false;
- continue;
- }
- }
-
- return okEntries;
- }
-
- @Override
- protected IndexEntry resolveIndexMapEntry(File cacheDir, IndexEntry ie) {
- if (cacheDir.exists()) {
- return ie; // we will take care of non-existing index entries in the readClassBytes method
- } else {
- return null;
- }
- }
-
- public static final Map<String,byte[]> readZipClassBytes (File file) throws IOException {
- if (!file.canRead()) {
- return Collections.emptyMap();
- }
-
- Map<String,byte[]> result=new TreeMap<String,byte[]>();
- byte[] copyBuf=new byte[4096];
- ByteArrayOutputStream out=new ByteArrayOutputStream(copyBuf.length);
- ZipFile zipFile=new ZipFile(file);
- try {
- for (Enumeration<? extends ZipEntry> entries=zipFile.entries(); (entries != null) && entries.hasMoreElements(); ) {
- ZipEntry e=entries.nextElement();
- String name=e.getName();
- if (LangUtil.isEmpty(name)) {
- continue;
- }
-
- out.reset();
-
- InputStream zipStream=zipFile.getInputStream(e);
- try {
- for (int nRead=zipStream.read(copyBuf); nRead != (-1); nRead=zipStream.read(copyBuf)) {
- out.write(copyBuf, 0, nRead);
- }
- } finally {
- zipStream.close();
- }
-
- byte[] data=out.toByteArray(), prev=result.put(name, data);
- if (prev != null) {
- throw new StreamCorruptedException("Multiple entries for " + name);
- }
- }
- } finally {
- zipFile.close();
- }
-
- return result;
- }
-
- public static final void writeZipClassBytes (File file, Map<String,byte[]> entriesMap) throws IOException {
- if (entriesMap.isEmpty()) {
- FileUtil.deleteContents(file);
- return;
- }
-
- File zipDir=file.getParentFile();
- if ((!zipDir.exists()) && (!zipDir.mkdirs())) {
- throw new IOException("Failed to create path to " + zipDir.getAbsolutePath());
- }
-
- ZipOutputStream zipOut=new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(file), 4096));
- try {
- for (Map.Entry<String,byte[]> bytesEntry : entriesMap.entrySet()) {
- String key=bytesEntry.getKey();
- byte[] bytes=bytesEntry.getValue();
- zipOut.putNextEntry(new ZipEntry(key));
- zipOut.write(bytes);
- zipOut.closeEntry();
- }
- } finally {
- zipOut.close();
- }
- }
-}