}
boolean shouldApply = munger.matches(weaver.getLazyClassGen().getType(), aspectType);
if (shouldApply) {
Type bcelReturnType = BcelWorld.makeBcelType(introduced.getReturnType());
// If no implementation class was specified, the intention was that
// the types matching the pattern
// already implemented the interface, let's check that now!
if (munger.getImplClassName() == null && !munger.specifiesDelegateFactoryMethod()) {
boolean isOK = false;
List<LazyMethodGen> existingMethods = gen.getMethodGens();
for (LazyMethodGen m : existingMethods) {
if (m.getName().equals(introduced.getName())
&& m.getParameterSignature().equals(introduced.getParameterSignature())
&& m.getReturnType().equals(bcelReturnType)) {
isOK = true;
}
}
if (!isOK) {
// the class does not implement this method, they needed to
// supply a default impl class
IMessage msg = new Message("@DeclareParents: No defaultImpl was specified but the type '" + gen.getName()
+ "' does not implement the method '" + stringifyMember(introduced) + "' defined on the interface '"
+ introduced.getDeclaringType() + "'", weaver.getLazyClassGen().getType().getSourceLocation(), true,
new ISourceLocation[] { munger.getSourceLocation() });
weaver.getWorld().getMessageHandler().handleMessage(msg);
return false;
}
return true;
}
LazyMethodGen mg = new LazyMethodGen(introduced.getModifiers() - Modifier.ABSTRACT, bcelReturnType,
introduced.getName(), BcelWorld.makeBcelTypes(introduced.getParameterTypes()),
BcelWorld.makeBcelTypesAsClassNames(introduced.getExceptions()), gen);
// annotation copy from annotation on ITD interface
if (weaver.getWorld().isInJava5Mode()) {
AnnotationAJ annotationsOnRealMember[] = null;
ResolvedType toLookOn = weaver.getWorld().lookupOrCreateName(introduced.getDeclaringType());
if (fromType.isRawType()) {
toLookOn = fromType.getGenericType();
}
// lookup the method
ResolvedMember[] ms = toLookOn.getDeclaredJavaMethods();
for (ResolvedMember m : ms) {
if (introduced.getName().equals(m.getName()) && introduced.getSignature().equals(m.getSignature())) {
annotationsOnRealMember = m.getAnnotations();
break;
}
}
if (annotationsOnRealMember != null) {
for (AnnotationAJ anno : annotationsOnRealMember) {
AnnotationGen a = ((BcelAnnotation) anno).getBcelAnnotation();
AnnotationGen ag = new AnnotationGen(a, weaver.getLazyClassGen().getConstantPool(), true);
mg.addAnnotation(new BcelAnnotation(ag, weaver.getWorld()));
}
}
}
InstructionList body = new InstructionList();
InstructionFactory fact = gen.getFactory();
// getfield
body.append(InstructionConstants.ALOAD_0);
body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
InstructionBranch ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
body.append(ifNonNull);
// Create and store a new instance
body.append(InstructionConstants.ALOAD_0); // 'this' is where we'll store the field value
// TODO for non-static case, call aspectOf() then call the factory method on the retval
// TODO decide whether the value can really be cached
// locate the aspect and call the static method in it
if (munger.specifiesDelegateFactoryMethod()) {
ResolvedMember rm = munger.getDelegateFactoryMethod(weaver.getWorld());
// Check the method parameter is compatible with the type of the instance to be passed
if (rm.getArity() != 0) {
ResolvedType parameterType = rm.getParameterTypes()[0].resolve(weaver.getWorld());
if (!parameterType.isAssignableFrom(weaver.getLazyClassGen().getType())) {
signalError("For mixin factory method '" + rm + "': Instance type '" + weaver.getLazyClassGen().getType()
+ "' is not compatible with factory parameter type '" + parameterType + "'", weaver);
return false;
}
}
if (Modifier.isStatic(rm.getModifiers())) {
if (rm.getArity() != 0) {
body.append(InstructionConstants.ALOAD_0);
}
body.append(fact.createInvoke(rm.getDeclaringType().getName(), rm.getName(), rm.getSignature(),
Constants.INVOKESTATIC));
body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
} else {
// Need to call aspectOf() to obtain the aspect instance then call the factory method upon that
UnresolvedType theAspect = munger.getAspect();
body.append(fact.createInvoke(theAspect.getName(), "aspectOf", "()" + theAspect.getSignature(),
Constants.INVOKESTATIC));
if (rm.getArity() != 0) {
body.append(InstructionConstants.ALOAD_0);
}
body.append(fact.createInvoke(rm.getDeclaringType().getName(), rm.getName(), rm.getSignature(),
Constants.INVOKEVIRTUAL));
body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
}
} else {
body.append(fact.createNew(munger.getImplClassName()));
body.append(InstructionConstants.DUP);
body.append(fact.createInvoke(munger.getImplClassName(), "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
}
// if not null use the instance we've got
InstructionHandle ifNonNullElse = body.append(InstructionConstants.ALOAD_0);
ifNonNull.setTarget(ifNonNullElse);
body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
// args
int pos = 0;
if (!Modifier.isStatic(introduced.getModifiers())) { // skip 'this' (?? can this really
// happen)
// body.append(InstructionFactory.createThis());
pos++;
}
Type[] paramTypes = BcelWorld.makeBcelTypes(introduced.getParameterTypes());
for (int i = 0, len = paramTypes.length; i < len; i++) {
Type paramType = paramTypes[i];
body.append(InstructionFactory.createLoad(paramType, pos));
pos += paramType.getSize();
}
body.append(Utility.createInvoke(fact, Constants.INVOKEINTERFACE, introduced));
body.append(InstructionFactory.createReturn(bcelReturnType));
mg.getBody().append(body);