WeaverVersionInfo wvinfo = null;
for (int i = 0; i < attributes.length; i++) {
Attribute attribute = attributes[i];
if (acceptAttribute(attribute)) {
RuntimeAnnos rvs = (RuntimeAnnos) attribute;
// we don't need to look for several attribute occurrences since
// it cannot happen as per JSR175
if (!isCodeStyleAspect && !javaClass.isInterface()) {
hasAtAspectAnnotation = handleAspectAnnotation(rvs, struct);
// TODO AV - if put outside the if isCodeStyleAspect then we
// would enable mix style
hasAtPrecedenceAnnotation = handlePrecedenceAnnotation(rvs, struct);
}
// there can only be one RuntimeVisible bytecode attribute
break;
}
}
for (int i = attributes.length - 1; i >= 0; i--) {
Attribute attribute = attributes[i];
if (attribute.getName().equals(WeaverVersionInfo.AttributeName)) {
try {
VersionedDataInputStream s = new VersionedDataInputStream(new ByteArrayInputStream(
((Unknown) attribute).getBytes()), null);
wvinfo = WeaverVersionInfo.read(s);
struct.ajAttributes.add(0, wvinfo);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
if (wvinfo == null) {
// If we are in here due to a resetState() call (presumably because of reweavable state processing), the
// original type delegate will have been set with a version but that version will be missing from
// the new set of attributes (looks like a bug where the version attribute was not included in the
// data compressed into the attribute). So rather than 'defaulting' to current, we should use one
// if it set on the delegate for the type.
ReferenceTypeDelegate delegate = type.getDelegate();
if (delegate instanceof BcelObjectType) {
wvinfo = ((BcelObjectType) delegate).getWeaverVersionAttribute();
if (wvinfo != null) {
if (wvinfo.getMajorVersion() != WeaverVersionInfo.WEAVER_VERSION_MAJOR_UNKNOWN) {
// use this one
struct.ajAttributes.add(0, wvinfo);
} else {
wvinfo = null;
}
}
}
if (wvinfo == null) {
struct.ajAttributes.add(0, wvinfo = new AjAttribute.WeaverVersionInfo());
}
}
// basic semantic check
if (hasAtPrecedenceAnnotation && !hasAtAspectAnnotation) {
msgHandler.handleMessage(new Message("Found @DeclarePrecedence on a non @Aspect type '" + type.getName() + "'",
IMessage.WARNING, null, type.getSourceLocation()));
// bypass what we have read
return NO_ATTRIBUTES;
}
// the following block will not detect @Pointcut in non @Aspect types
// for optimization purpose
if (!(hasAtAspectAnnotation || isCodeStyleAspect) && !containsPointcut) {
return NO_ATTRIBUTES;
}
// FIXME AV - turn on when ajcMightHaveAspect
// if (hasAtAspectAnnotation && type.isInterface()) {
// msgHandler.handleMessage(
// new Message(
// "Found @Aspect on an interface type '" + type.getName() + "'",
// IMessage.WARNING,
// null,
// type.getSourceLocation()
// )
// );
// // bypass what we have read
// return EMPTY_LIST;
// }
// semantic check: @Aspect must be public
// FIXME AV - do we really want to enforce that?
// if (hasAtAspectAnnotation && !javaClass.isPublic()) {
// msgHandler.handleMessage(
// new Message(
// "Found @Aspect annotation on a non public class '" +
// javaClass.getClassName() + "'",
// IMessage.ERROR,
// null,
// type.getSourceLocation()
// )
// );
// return EMPTY_LIST;
// }
// code style pointcuts are class attributes
// we need to gather the @AJ pointcut right now and not at method level
// annotation extraction time
// in order to be able to resolve the pointcut references later on
// we don't need to look in super class, the pointcut reference in the
// grammar will do it
for (int i = 0; i < javaClass.getMethods().length; i++) {
Method method = javaClass.getMethods()[i];
if (method.getName().startsWith(NameMangler.PREFIX)) {
continue; // already dealt with by ajc...
}
// FIXME alex optimize, this method struct will gets recreated for
// advice extraction
AjAttributeMethodStruct mstruct = null;
boolean processedPointcut = false;
Attribute[] mattributes = method.getAttributes();
for (int j = 0; j < mattributes.length; j++) {
Attribute mattribute = mattributes[j];
if (acceptAttribute(mattribute)) {
// TODO speed all this nonsense up rather than looking
// through all the annotations every time
// same for fields
mstruct = new AjAttributeMethodStruct(method, null, type, context, msgHandler);
processedPointcut = handlePointcutAnnotation((RuntimeAnnos) mattribute, mstruct);
if (!processedPointcut) {
processedPointcut = handleDeclareMixinAnnotation((RuntimeAnnos) mattribute, mstruct);
}
// there can only be one RuntimeVisible bytecode attribute
break;
}
}
if (processedPointcut) {
struct.ajAttributes.addAll(mstruct.ajAttributes);
}
}
// code style declare error / warning / implements / parents are field
// attributes
Field[] fs = javaClass.getFields();
for (int i = 0; i < fs.length; i++) {
Field field = fs[i];
if (field.getName().startsWith(NameMangler.PREFIX)) {
continue; // already dealt with by ajc...
}
// FIXME alex optimize, this method struct will gets recreated for
// advice extraction
AjAttributeFieldStruct fstruct = new AjAttributeFieldStruct(field, null, type, context, msgHandler);
Attribute[] fattributes = field.getAttributes();
for (int j = 0; j < fattributes.length; j++) {
Attribute fattribute = fattributes[j];
if (acceptAttribute(fattribute)) {
RuntimeAnnos frvs = (RuntimeAnnos) fattribute;
if (handleDeclareErrorOrWarningAnnotation(model, frvs, fstruct)
|| handleDeclareParentsAnnotation(frvs, fstruct)) {
// semantic check - must be in an @Aspect [remove if
// previous block bypassed in advance]
if (!type.isAnnotationStyleAspect() && !isCodeStyleAspect) {