123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811 |
- /* *******************************************************************
- * 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;
- }
-
- public boolean bindsProceedingJoinPoint() {
- UnresolvedType[] parameterTypes = signature.getParameterTypes();
- for (UnresolvedType parameterType : parameterTypes) {
- if (parameterType.equals(UnresolvedType.PROCEEDING_JOINPOINT)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * 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 (UnresolvedType exc : excs) {
- ResolvedType t = world.resolve(exc, true);
- if (t.isMissing()) {
- world.getLint().cantFindType
- .signal(WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_EXCEPTION_TYPE, exc.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 (LocalVariable lv : lvTable) {
- 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());
- shadow.closureVarInitialized = true;
- }
- }
- } 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
- }
-
- }
|