From: aclement Date: Thu, 11 Sep 2008 08:36:46 +0000 (+0000) Subject: 246918: perclause: X-Git-Tag: V1_6_2~82 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=426ca34194c1694005daf1a4c3555373b68fd0ce;p=aspectj.git 246918: perclause: --- diff --git a/weaver/src/org/aspectj/weaver/GeneratedReferenceTypeDelegate.java b/weaver/src/org/aspectj/weaver/GeneratedReferenceTypeDelegate.java new file mode 100644 index 000000000..88e8c8759 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/GeneratedReferenceTypeDelegate.java @@ -0,0 +1,158 @@ +/* ******************************************************************* + * 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://eclipse.org/legal/epl-v10.html + * + * ******************************************************************/ +package org.aspectj.weaver; + +import java.util.Collection; + +import org.aspectj.weaver.patterns.PerClause; + +/** + * A delegate that can sit in the ReferenceType instance created for an aspect generated from aop.xml. Only answers the minimal set + * of information required as the type is processed. + * + * @author Andy Clement + */ +public class GeneratedReferenceTypeDelegate extends AbstractReferenceTypeDelegate { + + private ResolvedType superclass; + + public GeneratedReferenceTypeDelegate(ReferenceType backing) { + super(backing, false); + } + + public void addAnnotation(AnnotationAJ annotationX) { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public boolean isAspect() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public boolean isAnnotationStyleAspect() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public boolean isInterface() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public boolean isEnum() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public boolean isAnnotation() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public boolean isAnnotationWithRuntimeRetention() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public boolean isAnonymous() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public boolean isNested() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public ResolvedType getOuterClass() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public String getRetentionPolicy() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public boolean canAnnotationTargetType() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public AnnotationTargetKind[] getAnnotationTargetKinds() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public boolean isGeneric() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public String getDeclaredGenericSignature() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public boolean hasAnnotation(UnresolvedType ofType) { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public AnnotationAJ[] getAnnotations() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public ResolvedType[] getAnnotationTypes() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public ResolvedMember[] getDeclaredFields() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public ResolvedType[] getDeclaredInterfaces() { + return ResolvedType.NONE; + } + + public ResolvedMember[] getDeclaredMethods() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public ResolvedMember[] getDeclaredPointcuts() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public PerClause getPerClause() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public Collection getDeclares() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public Collection getTypeMungers() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public Collection getPrivilegedAccesses() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public int getModifiers() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public void setSuperclass(ResolvedType superclass) { + this.superclass = superclass; + } + + public ResolvedType getSuperclass() { + return this.superclass; + } + + public WeaverStateInfo getWeaverState() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public TypeVariable[] getTypeVariables() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + + public void ensureDelegateConsistent() { + throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate"); + } + +} \ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java b/weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java index 2df95c53f..959016237 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java @@ -30,572 +30,539 @@ import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.patterns.PerClause; /** - * Adds aspectOf, hasAspect etc to the annotation defined aspects - * - * @author Alexandre Vasseur + * Adds aspectOf(), hasAspect() etc to the annotation defined aspects + * + * @author Alexandre Vasseur + * @author Andy Clement */ public class BcelPerClauseAspectAdder extends BcelTypeMunger { - private 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); -// } else { -// throw new Error("Should not happen - no such kind " + kind.toString()); - } - } - - 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(), "", 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(), "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); - il.append(Utility.createSet(factory, AjcMemberMaker.perSingletonField(aspectType))); - il.append(InstructionFactory.createReturn(Type.VOID)); - - // patch 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(), "", 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(), "", 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(), "", 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 = makeMethodGen(classGen, AjcMemberMaker.ajcPreClinitMethod(aspectType)); - flagAsSynthetic(method, true); - classGen.addMethodGen(method); - - InstructionList il = method.getBody(); - il.append(factory.createNew(AjcMemberMaker.CFLOW_STACK_TYPE.getName())); - il.append(InstructionConstants.DUP); - il.append(factory.createInvoke(AjcMemberMaker.CFLOW_STACK_TYPE.getName(), "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); - il.append(Utility.createSet(factory, AjcMemberMaker.perCflowField(aspectType))); - il.append(InstructionFactory.createReturn(Type.VOID)); - - // patch to delegate to ajc$preClinit at the beginning - LazyMethodGen clinit = classGen.getStaticInitializer(); - il = new InstructionList(); - il.append(factory.createInvoke(aspectType.getName(), NameMangler.AJC_PRE_CLINIT_NAME, Type.VOID, Type.NO_ARGS, Constants.INVOKESTATIC)); - clinit.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(), "", 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(), "", 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(), "", 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; - //} + 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(), "", 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(), "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); + il.append(Utility.createSet(factory, AjcMemberMaker.perSingletonField(aspectType))); + il.append(InstructionFactory.createReturn(Type.VOID)); + + // patch 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(), "", 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(), "", 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(), "", 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 = makeMethodGen(classGen, AjcMemberMaker.ajcPreClinitMethod(aspectType)); + flagAsSynthetic(method, true); + classGen.addMethodGen(method); + + InstructionList il = method.getBody(); + il.append(factory.createNew(AjcMemberMaker.CFLOW_STACK_TYPE.getName())); + il.append(InstructionConstants.DUP); + il.append(factory.createInvoke(AjcMemberMaker.CFLOW_STACK_TYPE.getName(), "", Type.VOID, Type.NO_ARGS, + Constants.INVOKESPECIAL)); + il.append(Utility.createSet(factory, AjcMemberMaker.perCflowField(aspectType))); + il.append(InstructionFactory.createReturn(Type.VOID)); + + // patch to delegate to ajc$preClinit at the beginning + LazyMethodGen clinit = classGen.getStaticInitializer(); + il = new InstructionList(); + il.append(factory.createInvoke(aspectType.getName(), NameMangler.AJC_PRE_CLINIT_NAME, Type.VOID, Type.NO_ARGS, + Constants.INVOKESTATIC)); + clinit.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(), "", 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(), "", 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(), "", 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; + // } }