}
return onType.equals(classWeaver.getLazyClassGen().getType());
}
private boolean mungeNewMethod(BcelClassWeaver classWeaver, NewMethodTypeMunger munger) {
World world = classWeaver.getWorld();
// Resolving it will sort out the tvars
ResolvedMember unMangledInterMethod = munger.getSignature().resolve(world);
// do matching on the unMangled one, but actually add them to the mangled method
ResolvedMember interMethodBody = munger.getDeclaredInterMethodBody(aspectType, world);
ResolvedMember interMethodDispatcher = munger.getDeclaredInterMethodDispatcher(aspectType, world);
ResolvedMember memberHoldingAnyAnnotations = interMethodDispatcher;
LazyClassGen classGen = classWeaver.getLazyClassGen();
ResolvedType onType = world.resolve(unMangledInterMethod.getDeclaringType(), munger.getSourceLocation());
if (onType.isRawType()) {
onType = onType.getGenericType();
}
// Simple checks, can't ITD on annotations or enums
if (onType.isAnnotation()) {
signalError(WeaverMessages.ITDM_ON_ANNOTATION_NOT_ALLOWED, classWeaver, onType);
return false;
}
if (onType.isEnum()) {
signalError(WeaverMessages.ITDM_ON_ENUM_NOT_ALLOWED, classWeaver, onType);
return false;
}
boolean mungingInterface = classGen.isInterface();
boolean onInterface = onType.isInterface();
if (onInterface
&& classGen.getLazyMethodGen(unMangledInterMethod.getName(), unMangledInterMethod.getSignature(), true) != null) {
// this is ok, we could be providing the default implementation of a
// method
// that the target has already declared
return false;
}
// If we are processing the intended ITD target type (might be an interface)
if (onType.equals(classGen.getType())) {
ResolvedMember mangledInterMethod = AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, onInterface);
LazyMethodGen newMethod = makeMethodGen(classGen, mangledInterMethod);
if (mungingInterface) {
// we want the modifiers of the ITD to be used for all *implementors* of the
// interface, but the method itself we add to the interface must be public abstract
newMethod.setAccessFlags(Modifier.PUBLIC | Modifier.ABSTRACT);
}
// pr98901
// For copying the annotations across, we have to discover the real
// member in the aspect which is holding them.
if (classWeaver.getWorld().isInJava5Mode()) {
AnnotationAJ annotationsOnRealMember[] = null;
ResolvedType toLookOn = aspectType;
if (aspectType.isRawType()) {
toLookOn = aspectType.getGenericType();
}
ResolvedMember realMember = getRealMemberForITDFromAspect(toLookOn, memberHoldingAnyAnnotations, false);
// 266602 - consider it missing to mean that the corresponding aspect had errors
if (realMember == null) {
// signalWarning("Unable to apply any annotations attached to " + munger.getSignature(), weaver);
// throw new BCException("Couldn't find ITD init member '" + interMethodBody + "' on aspect " + aspectType);
} else {
annotationsOnRealMember = realMember.getAnnotations();
}
Set<ResolvedType> addedAnnotations = new HashSet<ResolvedType>();
if (annotationsOnRealMember != null) {
for (AnnotationAJ anno : annotationsOnRealMember) {
AnnotationGen a = ((BcelAnnotation) anno).getBcelAnnotation();
AnnotationGen ag = new AnnotationGen(a, classGen.getConstantPool(), true);
newMethod.addAnnotation(new BcelAnnotation(ag, classWeaver.getWorld()));
addedAnnotations.add(anno.getType());
}
}
if (realMember != null) {
copyOverParameterAnnotations(newMethod, realMember);
}
// the code below was originally added to cope with the case where an aspect declares an annotation on an ITD
// declared within itself (an unusual situation). However, it also addresses the case where we may not find the
// annotation on the real representation of the ITD. This can happen in a load-time weaving situation where
// we couldn't add the annotation in time - and so here we recheck the declare annotations. Not quite ideal but
// works. pr288635
List<DeclareAnnotation> allDecams = world.getDeclareAnnotationOnMethods();
for (DeclareAnnotation declareAnnotationMC : allDecams) {
if (declareAnnotationMC.matches(unMangledInterMethod, world)) {
// && newMethod.getEnclosingClass().getType() == aspectType) {
AnnotationAJ annotation = declareAnnotationMC.getAnnotation();
if (!addedAnnotations.contains(annotation.getType())) {
newMethod.addAnnotation(annotation);
}
}
}
}
// If it doesn't target an interface and there is a body (i.e. it
// isnt abstract)
if (!onInterface && !Modifier.isAbstract(mangledInterMethod.getModifiers())) {
InstructionList body = newMethod.getBody();
InstructionFactory fact = classGen.getFactory();
int pos = 0;
if (!Modifier.isStatic(unMangledInterMethod.getModifiers())) {
body.append(InstructionFactory.createThis());
pos++;
}
Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes());
for (int i = 0, len = paramTypes.length; i < len; i++) {
Type paramType = paramTypes[i];
body.append(InstructionFactory.createLoad(paramType, pos));
pos += paramType.getSize();
}
body.append(Utility.createInvoke(fact, classWeaver.getWorld(), interMethodBody));
body.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(mangledInterMethod.getReturnType())));
if (classWeaver.getWorld().isInJava5Mode()) { // Don't need bridge
// methods if not in
// 1.5 mode.
createAnyBridgeMethodsForCovariance(classWeaver, munger, unMangledInterMethod, onType, classGen, paramTypes);
}
} else {
// ??? this is okay
// if (!(mg.getBody() == null)) throw new
// RuntimeException("bas");
}
if (world.isInJava5Mode()) {
String basicSignature = mangledInterMethod.getSignature();
String genericSignature = ((ResolvedMemberImpl) mangledInterMethod).getSignatureForAttribute();
if (!basicSignature.equals(genericSignature)) {
// Add a signature attribute to it
newMethod.addAttribute(createSignatureAttribute(classGen.getConstantPool(), genericSignature));
}
}
// XXX make sure to check that we set exceptions properly on this
// guy.
classWeaver.addLazyMethodGen(newMethod);
classWeaver.getLazyClassGen().warnOnAddedMethod(newMethod.getMethod(), getSignature().getSourceLocation());
addNeededSuperCallMethods(classWeaver, onType, munger.getSuperMethodsCalled());
return true;
} else if (onInterface && !Modifier.isAbstract(unMangledInterMethod.getModifiers())) {
// This means the 'gen' should be the top most implementor
// - if it is *not* then something went wrong after we worked
// out that it was the top most implementor (see pr49657)
if (!classGen.getType().isTopmostImplementor(onType)) {
ResolvedType rtx = classGen.getType().getTopmostImplementor(onType);
if (rtx == null) {
// pr302460
// null means there is something wrong with what we are looking at
ResolvedType rt = classGen.getType();
if (rt.isInterface()) {
ISourceLocation sloc = munger.getSourceLocation();
classWeaver
.getWorld()
.getMessageHandler()
.handleMessage(
MessageUtil.error(
"ITD target "
+ rt.getName()
+ " is an interface but has been incorrectly determined to be the topmost implementor of "
+ onType.getName() + ". ITD is " + this.getSignature(), sloc));
}
if (!onType.isAssignableFrom(rt)) {
ISourceLocation sloc = munger.getSourceLocation();
classWeaver
.getWorld()
.getMessageHandler()
.handleMessage(
MessageUtil.error(
"ITD target " + rt.getName() + " doesn't appear to implement " + onType.getName()
+ " why did we consider it the top most implementor? ITD is "
+ this.getSignature(), sloc));
}
} else if (!rtx.isExposedToWeaver()) {
ISourceLocation sLoc = munger.getSourceLocation();
classWeaver
.getWorld()
.getMessageHandler()
.handleMessage(
MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_NON_EXPOSED_IMPLEMENTOR, rtx,
getAspectType().getName()), (sLoc == null ? getAspectType().getSourceLocation() : sLoc)));
} else {
// XXX what does this state mean?
// We have incorrectly identified what is the top most
// implementor and its not because
// a type wasn't exposed to the weaver
}
return false;
} else {
ResolvedMember mangledInterMethod = AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, false);
LazyMethodGen mg = makeMethodGen(classGen, mangledInterMethod);
// From 98901#29 - need to copy annotations across
if (classWeaver.getWorld().isInJava5Mode()) {
AnnotationAJ annotationsOnRealMember[] = null;
ResolvedType toLookOn = aspectType;
if (aspectType.isRawType()) {
toLookOn = aspectType.getGenericType();
}
ResolvedMember realMember = getRealMemberForITDFromAspect(toLookOn, memberHoldingAnyAnnotations, false);
if (realMember == null) {
throw new BCException("Couldn't find ITD holder member '" + memberHoldingAnyAnnotations + "' on aspect "
+ aspectType);
}
annotationsOnRealMember = realMember.getAnnotations();
if (annotationsOnRealMember != null) {
for (AnnotationAJ annotationX : annotationsOnRealMember) {
AnnotationGen a = ((BcelAnnotation) annotationX).getBcelAnnotation();
AnnotationGen ag = new AnnotationGen(a, classWeaver.getLazyClassGen().getConstantPool(), true);
mg.addAnnotation(new BcelAnnotation(ag, classWeaver.getWorld()));
}
}
copyOverParameterAnnotations(mg, realMember);
}
if (mungingInterface) {
// we want the modifiers of the ITD to be used for all
// *implementors* of the
// interface, but the method itself we add to the interface
// must be public abstract
mg.setAccessFlags(Modifier.PUBLIC | Modifier.ABSTRACT);
}
Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes());
Type returnType = BcelWorld.makeBcelType(mangledInterMethod.getReturnType());
InstructionList body = mg.getBody();
InstructionFactory fact = classGen.getFactory();
int pos = 0;
if (!Modifier.isStatic(mangledInterMethod.getModifiers())) {
body.append(InstructionFactory.createThis());
pos++;
}
for (int i = 0, len = paramTypes.length; i < len; i++) {
Type paramType = paramTypes[i];
body.append(InstructionFactory.createLoad(paramType, pos));
pos += paramType.getSize();
}
body.append(Utility.createInvoke(fact, classWeaver.getWorld(), interMethodBody));
Type t = BcelWorld.makeBcelType(interMethodBody.getReturnType());
if (!t.equals(returnType)) {
body.append(fact.createCast(t, returnType));
}
body.append(InstructionFactory.createReturn(returnType));
mg.definingType = onType;
if (world.isInJava5Mode()) {
String basicSignature = mangledInterMethod.getSignature();
String genericSignature = ((ResolvedMemberImpl) mangledInterMethod).getSignatureForAttribute();
if (!basicSignature.equals(genericSignature)) {
// Add a signature attribute to it
mg.addAttribute(createSignatureAttribute(classGen.getConstantPool(), genericSignature));