From: aclement Date: Mon, 19 Nov 2007 16:34:15 +0000 (+0000) Subject: 162539: NullPointerException when pointcut library missing @aspect annotion: tests... X-Git-Tag: V1_5_4rc1~23 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=915aaa9d09a7aa104c96c73739e15464616e7326;p=aspectj.git 162539: NullPointerException when pointcut library missing @aspect annotion: tests and fixes. Modified resolution of @AJ pointcuts and optimized searching for @AJ elements in all classes --- diff --git a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java index 77367d867..27b8df953 100644 --- a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java +++ b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java @@ -184,27 +184,38 @@ public class AtAjAttributes { * @return list of AjAttributes */ public static List readAj5ClassAttributes(JavaClass javaClass, ReferenceType type, ISourceContext context, IMessageHandler msgHandler, boolean isCodeStyleAspect) { + boolean containsPointcut = false; //FIXME AV - 1.5 feature limitation, kick after implemented - try { + boolean ignoreThisClass = javaClass.getClassName().charAt(0)=='o' && javaClass.getClassName().startsWith("org.aspectj.lang.annotation"); + if (ignoreThisClass) return EMPTY_LIST; + try { + boolean containsAnnotationClassReference = false; Constant[] cpool = javaClass.getConstantPool().getConstantPool(); for (int i = 0; i < cpool.length; i++) { Constant constant = cpool[i]; if (constant != null && constant.getTag() == Constants.CONSTANT_Utf8) { - if (!javaClass.getClassName().startsWith("org.aspectj.lang.annotation")) { - ConstantUtf8 constantUtf8 = (ConstantUtf8) constant; - if ("Lorg/aspectj/lang/annotation/DeclareAnnotation;".equals(constantUtf8.getBytes())) { - msgHandler.handleMessage( - new Message( - "Found @DeclareAnnotation while current release does not support it (see '" + type.getName() + "')", - IMessage.WARNING, - null, - type.getSourceLocation() - ) - ); - } + String constantValue = ((ConstantUtf8)constant).getBytes(); + if (constantValue.length()>28 && constantValue.charAt(1)=='o') { + if (constantValue.startsWith("Lorg/aspectj/lang/annotation")) { + containsAnnotationClassReference=true; + if ("Lorg/aspectj/lang/annotation/DeclareAnnotation;".equals(constantValue)) { + msgHandler.handleMessage( + new Message( + "Found @DeclareAnnotation while current release does not support it (see '" + type.getName() + "')", + IMessage.WARNING, + null, + type.getSourceLocation() + ) + ); + } + if ("Lorg/aspectj/lang/annotation/Pointcut;".equals(constantValue)) { + containsPointcut=true; + } + } } } } + if (!containsAnnotationClassReference) return EMPTY_LIST; } catch (Throwable t) { ; } @@ -245,11 +256,10 @@ public class AtAjAttributes { } // the following block will not detect @Pointcut in non @Aspect types for optimization purpose - if (!hasAtAspectAnnotation) { + if (!hasAtAspectAnnotation && !containsPointcut) { return EMPTY_LIST; } - //FIXME AV - turn on when ajcMightHaveAspect // if (hasAtAspectAnnotation && type.isInterface()) { // msgHandler.handleMessage( @@ -282,25 +292,28 @@ public class AtAjAttributes { // 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 = new AjAttributeMethodStruct(method, null, type, context, msgHandler);//FIXME AVASM + 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)) { - RuntimeAnnotations mrvs = (RuntimeAnnotations) mattribute; - handlePointcutAnnotation(mrvs, mstruct); + if (mstruct==null) mstruct = new AjAttributeMethodStruct(method, null, type, context, msgHandler);//FIXME AVASM + processedPointcut = handlePointcutAnnotation((RuntimeAnnotations) mattribute, mstruct); // there can only be one RuntimeVisible bytecode attribute break; } } - // FIXME asc should check we aren't adding multiple versions... will do once I get the tests passing again... - struct.ajAttributes.add(new AjAttribute.WeaverVersionInfo()); - struct.ajAttributes.addAll(mstruct.ajAttributes); + if (processedPointcut) { + // FIXME asc should check we aren't adding multiple versions... will do once I get the tests passing again... + struct.ajAttributes.add(new AjAttribute.WeaverVersionInfo()); + struct.ajAttributes.addAll(mstruct.ajAttributes); + } } @@ -1171,92 +1184,93 @@ public class AtAjAttributes { * * @param runtimeAnnotations * @param struct + * @return true if a pointcut was handled */ - private static void handlePointcutAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct) { + private static boolean handlePointcutAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct) { Annotation pointcut = getAnnotation(runtimeAnnotations, AjcMemberMaker.POINTCUT_ANNOTATION); - if (pointcut != null) { - ElementNameValuePair pointcutExpr = getAnnotationElement(pointcut, VALUE); - - - // semantic check: the method must return void, or be "public static boolean" for if() support - if (!(Type.VOID.equals(struct.method.getReturnType()) - || (Type.BOOLEAN.equals(struct.method.getReturnType()) && struct.method.isStatic() && struct.method.isPublic()))) { - reportWarning("Found @Pointcut on a method not returning 'void' or not 'public static boolean'", struct); - ;//no need to stop - } + if (pointcut==null) return false; + ElementNameValuePair pointcutExpr = getAnnotationElement(pointcut, VALUE); - // semantic check: the method must not throw anything - if (struct.method.getExceptionTable() != null) { - reportWarning("Found @Pointcut on a method throwing exception", struct); - ;// no need to stop - } + + // semantic check: the method must return void, or be "public static boolean" for if() support + if (!(Type.VOID.equals(struct.method.getReturnType()) + || (Type.BOOLEAN.equals(struct.method.getReturnType()) && struct.method.isStatic() && struct.method.isPublic()))) { + reportWarning("Found @Pointcut on a method not returning 'void' or not 'public static boolean'", struct); + ;//no need to stop + } - String argumentNames = getArgNamesValue(pointcut); - if (argumentNames!=null) { - struct.unparsedArgumentNames = argumentNames; - } - // this/target/args binding - final IScope binding; - try { - if (struct.method.isAbstract()) { - binding = null; - } else { - binding = new BindingScope( - struct.enclosingType, - struct.context, - extractBindings(struct) - ); - } - } catch (UnreadableDebugInfoException e) { - return; - } + // semantic check: the method must not throw anything + if (struct.method.getExceptionTable() != null) { + reportWarning("Found @Pointcut on a method throwing exception", struct); + ;// no need to stop + } - UnresolvedType[] argumentTypes = new UnresolvedType[struct.method.getArgumentTypes().length]; - for (int i = 0; i < argumentTypes.length; i++) { - argumentTypes[i] = UnresolvedType.forSignature(struct.method.getArgumentTypes()[i].getSignature()); - } + String argumentNames = getArgNamesValue(pointcut); + if (argumentNames!=null) { + struct.unparsedArgumentNames = argumentNames; + } + // this/target/args binding + final IScope binding; + try { + if (struct.method.isAbstract()) { + binding = null; + } else { + binding = new BindingScope( + struct.enclosingType, + struct.context, + extractBindings(struct) + ); + } + } catch (UnreadableDebugInfoException e) { + return false; + } - Pointcut pc = null; - if (struct.method.isAbstract()) { - if ((pointcutExpr != null && isNullOrEmpty(pointcutExpr.getValue().stringifyValue())) - || pointcutExpr == null) { - // abstract pointcut - // leave pc = null - } else { - reportError("Found defined @Pointcut on an abstract method", struct); - return;//stop - } + UnresolvedType[] argumentTypes = new UnresolvedType[struct.method.getArgumentTypes().length]; + for (int i = 0; i < argumentTypes.length; i++) { + argumentTypes[i] = UnresolvedType.forSignature(struct.method.getArgumentTypes()[i].getSignature()); + } + + Pointcut pc = null; + if (struct.method.isAbstract()) { + if ((pointcutExpr != null && isNullOrEmpty(pointcutExpr.getValue().stringifyValue())) + || pointcutExpr == null) { + // abstract pointcut + // leave pc = null } else { - if (pointcutExpr==null || (pointcutExpr != null && isNullOrEmpty(pointcutExpr.getValue().stringifyValue()))) { - // the matches nothing pointcut (125475/125480) - perhaps not as cleanly supported as it could be. - } else { - if (pointcutExpr != null) { - // use a LazyResolvedPointcutDefinition so that the pointcut is resolved lazily - // since for it to be resolved, we will need other pointcuts to be registered as well - pc = parsePointcut(pointcutExpr.getValue().stringifyValue(), struct, true); - if (pc == null) return;//parse error - pc.setLocation(struct.context, -1, -1);//FIXME AVASM !! bMethod is null here.. - } else { - reportError("Found undefined @Pointcut on a non-abstract method", struct); - return; - } - } + reportError("Found defined @Pointcut on an abstract method", struct); + return false;//stop } - // do not resolve binding now but lazily - struct.ajAttributes.add( - new AjAttribute.PointcutDeclarationAttribute( - new LazyResolvedPointcutDefinition( - struct.enclosingType, - struct.method.getModifiers(), - struct.method.getName(), - argumentTypes, - UnresolvedType.forSignature(struct.method.getReturnType().getSignature()), - pc,//can be null for abstract pointcut - binding // can be null for abstract pointcut - ) - ) - ); + } else { + if (pointcutExpr==null || (pointcutExpr != null && isNullOrEmpty(pointcutExpr.getValue().stringifyValue()))) { + // the matches nothing pointcut (125475/125480) - perhaps not as cleanly supported as it could be. + } else { + if (pointcutExpr != null) { + // use a LazyResolvedPointcutDefinition so that the pointcut is resolved lazily + // since for it to be resolved, we will need other pointcuts to be registered as well + pc = parsePointcut(pointcutExpr.getValue().stringifyValue(), struct, true); + if (pc == null) return false;//parse error + pc.setLocation(struct.context, -1, -1);//FIXME AVASM !! bMethod is null here.. + } else { + reportError("Found undefined @Pointcut on a non-abstract method", struct); + return false; + } + } } + // do not resolve binding now but lazily + struct.ajAttributes.add( + new AjAttribute.PointcutDeclarationAttribute( + new LazyResolvedPointcutDefinition( + struct.enclosingType, + struct.method.getModifiers(), + struct.method.getName(), + argumentTypes, + UnresolvedType.forSignature(struct.method.getReturnType().getSignature()), + pc,//can be null for abstract pointcut + binding // can be null for abstract pointcut + ) + ) + ); + return true; } /** @@ -1689,7 +1703,7 @@ public class AtAjAttributes { private Pointcut m_lazyPointcut = null; - public LazyResolvedPointcutDefinition(ResolvedType declaringType, int modifiers, String name, + public LazyResolvedPointcutDefinition(UnresolvedType declaringType, int modifiers, String name, UnresolvedType[] parameterTypes, UnresolvedType returnType, Pointcut pointcut, IScope binding) { super(declaringType, modifiers, name, parameterTypes, returnType, null);