}
}
entryBindings.copyContext(bindings);
// System.out.println(this + " bindings: " + entryBindings);
World world = inAspect.getWorld();
Pointcut concreteEntry;
ResolvedType concreteAspect = bindings.getConcreteAspect();
CrosscuttingMembers xcut = concreteAspect.crosscuttingMembers;
Collection<ShadowMunger> previousCflowEntries = xcut.getCflowEntries();
entryBindings.pushEnclosingDefinition(CFLOW_MARKER);
// This block concretizes the pointcut within the cflow pointcut
try {
concreteEntry = entry.concretize(inAspect, declaringType, entryBindings);
} finally {
entryBindings.popEnclosingDefinitition();
}
List<ShadowMunger> innerCflowEntries = new ArrayList<ShadowMunger>(xcut.getCflowEntries());
innerCflowEntries.removeAll(previousCflowEntries);
// Four routes of interest through this code (did I hear someone say
// refactor??)
// 1) no state in the cflow - we can use a counter *and* we have seen
// this pointcut
// before - so use the same counter as before.
// 2) no state in the cflow - we can use a counter, but this is the
// first time
// we have seen this pointcut, so build the infrastructure.
// 3) state in the cflow - we need to use a stack *and* we have seen
// this pointcut
// before - so share the stack.
// 4) state in the cflow - we need to use a stack, but this is the first
// time
// we have seen this pointcut, so build the infrastructure.
if (freeVars == null || freeVars.length == 0) { // No state, so don't
// use a stack, use a
// counter.
ResolvedMember localCflowField = null;
Object field = getCflowfield(xcut, concreteEntry, concreteAspect, "counter");
// Check if we have already got a counter for this cflow pointcut
if (field != null) {
localCflowField = (ResolvedMember) field; // Use the one we
// already have
} else {
// Create a counter field in the aspect
localCflowField = new ResolvedMemberImpl(Member.FIELD, concreteAspect, Modifier.STATIC | Modifier.PUBLIC
| Modifier.FINAL, NameMangler.cflowCounter(xcut), UnresolvedType.forName(NameMangler.CFLOW_COUNTER_TYPE)
.getSignature());
// Create type munger to add field to the aspect
concreteAspect.crosscuttingMembers.addTypeMunger(world.getWeavingSupport().makeCflowCounterFieldAdder(
localCflowField));
// Create shadow munger to push stuff onto the stack
concreteAspect.crosscuttingMembers.addConcreteShadowMunger(Advice.makeCflowEntry(world, concreteEntry, isBelow,
localCflowField, freeVars == null ? 0 : freeVars.length, innerCflowEntries, inAspect));
putCflowfield(xcut, concreteEntry, concreteAspect, localCflowField, "counter"); // Remember
// it
}
Pointcut ret = new ConcreteCflowPointcut(concreteAspect, localCflowField, null, true);
ret.copyLocationFrom(this);
return ret;
} else {
List slots = new ArrayList();
for (int i = 0, len = freeVars.length; i < len; i++) {
int freeVar = freeVars[i];
// we don't need to keep state that isn't actually exposed to
// advice
// ??? this means that we will store some state that we won't
// actually use, optimize this later
if (!bindings.hasKey(freeVar)) {
continue;
}
int formalIndex = bindings.get(freeVar);
// We need to look in the right place for the type of the
// formal. Suppose the advice looks like this:
// before(String s): somePointcut(*,s)
// where the first argument in somePointcut is of type Number
// for free variable 0 we want to ask the pointcut for the type
// of its first argument, if we only
// ask the advice for the type of its first argument then we'll
// get the wrong type (pr86903)
ResolvedPointcutDefinition enclosingDef = bindings.peekEnclosingDefinition();
ResolvedType formalType = null;
// Is there a useful enclosing pointcut?
if (enclosingDef != null && enclosingDef.getParameterTypes().length > 0) {
formalType = enclosingDef.getParameterTypes()[freeVar].resolve(world);
} else {
formalType = bindings.getAdviceSignature().getParameterTypes()[formalIndex].resolve(world);
}
ConcreteCflowPointcut.Slot slot = new ConcreteCflowPointcut.Slot(formalIndex, formalType, i);
slots.add(slot);
}
ResolvedMember localCflowField = null;
Object field = getCflowfield(xcut, concreteEntry, concreteAspect, "stack");
if (field != null) {
localCflowField = (ResolvedMember) field;
} else {
localCflowField = new ResolvedMemberImpl(Member.FIELD, concreteAspect, Modifier.STATIC | Modifier.PUBLIC
| Modifier.FINAL, NameMangler.cflowStack(xcut), UnresolvedType.forName(NameMangler.CFLOW_STACK_TYPE)
.getSignature());
// System.out.println("adding field to: " + inAspect + " field "
// + cflowField);
// add field and initializer to inAspect
// XXX and then that info above needs to be mapped down here to
// help with
// XXX getting the exposed state right
concreteAspect.crosscuttingMembers.addConcreteShadowMunger(Advice.makeCflowEntry(world, concreteEntry, isBelow,
localCflowField, freeVars.length, innerCflowEntries, inAspect));
concreteAspect.crosscuttingMembers.addTypeMunger(world.getWeavingSupport()
.makeCflowStackFieldAdder(localCflowField));
putCflowfield(xcut, concreteEntry, concreteAspect, localCflowField, "stack");
}
Pointcut ret = new ConcreteCflowPointcut(concreteAspect, localCflowField, slots, false);
ret.copyLocationFrom(this);