]> source.dussan.org Git - aspectj.git/commitdiff
246125: the SPLIT
authoraclement <aclement>
Wed, 22 Oct 2008 05:45:52 +0000 (05:45 +0000)
committeraclement <aclement>
Wed, 22 Oct 2008 05:45:52 +0000 (05:45 +0000)
231 files changed:
org.aspectj.matcher/src/org/aspectj/weaver/AbstractAnnotationAJ.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/AbstractReferenceTypeDelegate.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/Advice.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/AdviceKind.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/AjAttribute.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/AjcMemberMaker.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/AnnotatedElement.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/AnnotationAJ.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/AnnotationAnnotationValue.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/AnnotationNameValuePair.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/AnnotationOnTypeMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/AnnotationTargetKind.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/AnnotationValue.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ArrayAnnotationValue.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ArrayReferenceType.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/BCException.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/BindingScope.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/BoundedReferenceType.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/Checker.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ClassAnnotationValue.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ConcreteTypeMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/Constants.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembers.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembersSet.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/CustomMungerFactory.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/Dump.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/EnumAnnotationValue.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ExposeTypeMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/GeneratedReferenceTypeDelegate.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/IClassFileProvider.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/IClassWeaver.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ICrossReferenceHandler.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/IEclipseSourceContext.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/IHasPosition.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/IHasSourceLocation.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ISourceContext.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/IUnwovenClassFile.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/IWeaveRequestor.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/IWeavingSupport.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/IntMap.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/Iterators.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/JoinPointSignature.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/JoinPointSignatureIterator.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/Lint.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/LintMessage.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/Member.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/MemberKind.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/MethodDelegateTypeMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/MissingResolvedTypeWithKnownSignature.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/NameMangler.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/NewConstructorTypeMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/NewFieldTypeMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/NewMethodTypeMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/NewParentTypeMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/PerObjectInterfaceTypeMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/PerTypeWithinTargetTypeMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/PoliceExtensionUse.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/Position.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/PrivilegedAccessMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ReferenceType.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ReferenceTypeDelegate.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMember.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMemberImpl.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ResolvedPointcutDefinition.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ResolvedTypeMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/Shadow.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ShadowMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/SignatureUtils.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/SimpleAnnotationValue.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/SourceContextImpl.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/StandardAnnotation.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/StaticJoinPointFactory.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/TemporaryTypeMunger.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/TypeFactory.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/TypeVariable.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/TypeVariableDeclaringElement.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/TypeVariableReference.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/TypeVariableReferenceType.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedType.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/Utils.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/VersionedDataInputStream.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/WeakClassLoaderReference.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/WeaverMessages.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/WeaverStateInfo.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/WildcardedUnresolvedType.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/World.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/XlintDefault.properties [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/ASTNode.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/And.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/Call.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/CallExpr.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/Expr.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/FieldGet.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/FieldGetCall.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/HasAnnotation.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/IExprVisitor.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/ITestVisitor.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/Instanceof.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/Literal.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/Not.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/Or.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/Test.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/ast/Var.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/MatchingContextBasedTest.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutDesignatorHandlerBasedPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/TypePatternMatcherImpl.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/AndAnnotationTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/AndPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/AndTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationPatternList.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnyAnnotationTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/BasicToken.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/BasicTokenSource.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingAnnotationFieldTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingPattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/Bindings.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/CflowPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/Declare.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareAnnotation.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareErrorOrWarning.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParents.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclarePrecedence.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareSoft.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationFieldTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExposedState.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/FastMatchInfo.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/FormalBinding.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/HandlerPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasMemberTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasMemberTypePatternFinder.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/IScope.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/IToken.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ITokenSource.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/IVerificationRequired.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/IfPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/KindedPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ModifiersPattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/NameBindingPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/NamePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/NotAnnotationTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/NotPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/NotTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/OrAnnotationTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/OrPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/OrTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ParserException.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternNode.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerCflow.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerClause.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerFromSuper.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerObject.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerSingleton.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerThisOrTargetPointcutVisitor.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerTypeWithin.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/Pointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PointcutEvaluationExpenseComparator.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PointcutRewriter.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ReferencePointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ScopeWithTypeVariables.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/SignaturePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/SimpleScope.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ThrowsPattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePatternList.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePatternQuestions.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypeVariablePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypeVariablePatternList.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildAnnotationTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildTypePattern.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/WithinPointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/patterns/WithincodePointcut.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/AnnotationFinder.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/GenericSignatureInformationProvider.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/IReflectionWorld.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/Java14GenericSignatureInformationProvider.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/JoinPointMatchImpl.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/PointcutParameterImpl.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegate.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegateFactory.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedResolvedMemberImpl.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionFastMatchInfo.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionShadow.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionVar.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionWorld.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/reflect/ShadowMatchImpl.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/AbstractTrace.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/CommonsTrace.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/CommonsTraceFactory.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/ContextBasedMatcher.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/DefaultMatchingContext.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/DefaultTrace.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/DefaultTraceFactory.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/FuzzyBoolean.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/GeneratedClassHandler.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/ISupportsMessageContext.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/JoinPointMatch.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/MatchingContext.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutDesignatorHandler.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutExpression.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutParameter.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutParser.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutPrimitive.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/ShadowMatch.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/Trace.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/TraceFactory.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/Traceable.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/TypePatternMatcher.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/UnsupportedPointcutPrimitiveException.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/tools/WeavingClassLoader.java [new file with mode: 0644]
org.aspectj.matcher/src/org/aspectj/weaver/weaver-messages.properties [new file with mode: 0644]

diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AbstractAnnotationAJ.java b/org.aspectj.matcher/src/org/aspectj/weaver/AbstractAnnotationAJ.java
new file mode 100644 (file)
index 0000000..f9922cf
--- /dev/null
@@ -0,0 +1,158 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+
+public abstract class AbstractAnnotationAJ implements AnnotationAJ {
+
+       protected final ResolvedType type;
+
+       private Set supportedTargets = null; // @target meta annotation
+
+       public AbstractAnnotationAJ(ResolvedType type) {
+               this.type = type;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public final ResolvedType getType() {
+               return type;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public final String getTypeSignature() {
+               return type.getSignature();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public final String getTypeName() {
+               return type.getName();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public final boolean allowedOnAnnotationType() {
+               ensureAtTargetInitialized();
+               if (supportedTargets.isEmpty()) {
+                       return true;
+               }
+               return supportedTargets.contains("ANNOTATION_TYPE");
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public final boolean allowedOnField() {
+               ensureAtTargetInitialized();
+               if (supportedTargets.isEmpty()) {
+                       return true;
+               }
+               return supportedTargets.contains("FIELD");
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public final boolean allowedOnRegularType() {
+               ensureAtTargetInitialized();
+               if (supportedTargets.isEmpty()) {
+                       return true;
+               }
+               return supportedTargets.contains("TYPE");
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public final void ensureAtTargetInitialized() {
+               if (supportedTargets == null) {
+                       AnnotationAJ atTargetAnnotation = retrieveAnnotationOnAnnotation(UnresolvedType.AT_TARGET);
+                       if (atTargetAnnotation == null) {
+                               supportedTargets = Collections.EMPTY_SET;
+                       } else {
+                               supportedTargets = atTargetAnnotation.getTargets();
+                       }
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public final String getValidTargets() {
+               StringBuffer sb = new StringBuffer();
+               sb.append("{");
+               for (Iterator iter = supportedTargets.iterator(); iter.hasNext();) {
+                       String evalue = (String) iter.next();
+                       sb.append(evalue);
+                       if (iter.hasNext()) {
+                               sb.append(",");
+                       }
+               }
+               sb.append("}");
+               return sb.toString();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public final boolean specifiesTarget() {
+               ensureAtTargetInitialized();
+               return !supportedTargets.isEmpty();
+       }
+
+       /**
+        * Helper method to retrieve an annotation on an annotation e.g. retrieveAnnotationOnAnnotation(UnresolvedType.AT_TARGET)
+        */
+       private final AnnotationAJ retrieveAnnotationOnAnnotation(UnresolvedType requiredAnnotationSignature) {
+               AnnotationAJ[] annos = type.getAnnotations();
+               for (int i = 0; i < annos.length; i++) {
+                       AnnotationAJ a = annos[i];
+                       if (a.getTypeSignature().equals(requiredAnnotationSignature.getSignature())) {
+                               return annos[i];
+                       }
+               }
+               return null;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public abstract boolean isRuntimeVisible();
+
+       /**
+        * {@inheritDoc}
+        */
+       public abstract Set getTargets();
+
+       /**
+        * {@inheritDoc}
+        */
+       public abstract boolean hasNameValuePair(String name, String value);
+
+       /**
+        * {@inheritDoc}
+        */
+       public abstract boolean hasNamedValue(String name);
+
+       /**
+        * {@inheritDoc}
+        */
+       public abstract String stringify();
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AbstractReferenceTypeDelegate.java b/org.aspectj.matcher/src/org/aspectj/weaver/AbstractReferenceTypeDelegate.java
new file mode 100644 (file)
index 0000000..52d0ade
--- /dev/null
@@ -0,0 +1,128 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ *     Andy Clement - June 2005 - separated out from ResolvedType
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.util.GenericSignature;
+import org.aspectj.util.GenericSignatureParser;
+import org.aspectj.util.GenericSignature.ClassSignature;
+
+public abstract class AbstractReferenceTypeDelegate implements ReferenceTypeDelegate {
+
+       private String sourcefilename = UNKNOWN_SOURCE_FILE;
+       private ISourceContext sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT;
+
+       protected boolean exposedToWeaver;
+       protected ReferenceType resolvedTypeX;
+       protected ClassSignature cachedGenericClassTypeSignature;
+
+       // Happens to match Bcel javaClass default of '<Unknown>'
+       public final static String UNKNOWN_SOURCE_FILE = "<Unknown>";
+
+       public AbstractReferenceTypeDelegate(ReferenceType resolvedTypeX, boolean exposedToWeaver) {
+               this.resolvedTypeX = resolvedTypeX;
+               this.exposedToWeaver = exposedToWeaver;
+       }
+
+       public final boolean isClass() {
+               return !isAspect() && !isInterface();
+       }
+
+       /**
+        * Designed to be overriden by EclipseType to disable collection of shadow mungers during pre-weave compilation phase
+        */
+       public boolean doesNotExposeShadowMungers() {
+               return false;
+       }
+
+       public boolean isExposedToWeaver() {
+               return exposedToWeaver;
+       }
+
+       public ReferenceType getResolvedTypeX() {
+               return resolvedTypeX;
+       }
+
+       public final String getSourcefilename() {
+               return sourcefilename;
+       }
+
+       public final void setSourcefilename(String sourceFileName) {
+               sourcefilename = sourceFileName;
+               if (sourceFileName != null && sourceFileName.equals(AbstractReferenceTypeDelegate.UNKNOWN_SOURCE_FILE)) {
+                       sourcefilename = "Type '" + getResolvedTypeX().getName() + "' (no debug info available)";
+               } else {
+                       String pname = getResolvedTypeX().getPackageName();
+                       if (pname != null) {
+                               sourcefilename = pname.replace('.', '/') + '/' + sourceFileName;
+                       }
+               }
+               if (sourcefilename != null && sourceContext instanceof SourceContextImpl) {
+                       ((SourceContextImpl) sourceContext).setSourceFileName(sourcefilename);
+               }
+       }
+
+       public ISourceLocation getSourceLocation() {
+               return getSourceContext().makeSourceLocation(0, 0);
+       }
+
+       public ISourceContext getSourceContext() {
+               return sourceContext;
+       }
+
+       public void setSourceContext(ISourceContext isc) {
+               sourceContext = isc;
+       }
+
+       public GenericSignature.ClassSignature getGenericClassTypeSignature() {
+               if (cachedGenericClassTypeSignature == null) {
+                       String sig = getDeclaredGenericSignature();
+                       if (sig != null) {
+                               GenericSignatureParser parser = new GenericSignatureParser();
+                               cachedGenericClassTypeSignature = parser.parseAsClassSignature(sig);
+                       }
+               }
+               return cachedGenericClassTypeSignature;
+       }
+
+       protected GenericSignature.FormalTypeParameter[] getFormalTypeParametersFromOuterClass() {
+               List typeParameters = new ArrayList();
+               ReferenceType outer = (ReferenceType) getOuterClass();
+               ReferenceTypeDelegate outerDelegate = outer.getDelegate();
+               AbstractReferenceTypeDelegate outerObjectType = (AbstractReferenceTypeDelegate) outerDelegate;
+               if (outerObjectType.isNested()) {
+                       GenericSignature.FormalTypeParameter[] parentParams = outerObjectType.getFormalTypeParametersFromOuterClass();
+                       for (int i = 0; i < parentParams.length; i++) {
+                               typeParameters.add(parentParams[i]);
+                       }
+               }
+               GenericSignature.ClassSignature outerSig = outerObjectType.getGenericClassTypeSignature();
+               if (outerSig != null) {
+                       for (int i = 0; i < outerSig.formalTypeParameters.length; i++) {
+                               typeParameters.add(outerSig.formalTypeParameters[i]);
+                       }
+               }
+
+               GenericSignature.FormalTypeParameter[] ret = new GenericSignature.FormalTypeParameter[typeParameters.size()];
+               typeParameters.toArray(ret);
+               return ret;
+       }
+
+       public boolean copySourceContext() {
+               return true;
+       }
+
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Advice.java b/org.aspectj.matcher/src/org/aspectj/weaver/Advice.java
new file mode 100644 (file)
index 0000000..0472b57
--- /dev/null
@@ -0,0 +1,444 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.weaver.patterns.AndPointcut;
+import org.aspectj.weaver.patterns.PerClause;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.patterns.TypePattern;
+
+public abstract class Advice extends ShadowMunger {
+
+       protected AjAttribute.AdviceAttribute attribute; // the pointcut field is
+       // ignored
+
+       protected AdviceKind kind; // alias of attribute.getKind()
+       protected Member signature;
+       protected boolean hasMatchedAtLeastOnce = false;
+
+       // not necessarily declaring aspect, this is a semantics change from 1.0
+       protected ResolvedType concreteAspect; // null until after concretize
+
+       protected List innerCflowEntries = Collections.EMPTY_LIST; // just for
+       // cflow*Entry
+       // kinds
+       protected int nFreeVars; // just for cflow*Entry kinds
+
+       protected TypePattern exceptionType; // just for Softener kind
+
+       // if we are parameterized, these type may be different to the advice
+       // signature types
+       protected UnresolvedType[] bindingParameterTypes;
+
+       protected List/* Lint.Kind */suppressedLintKinds = null; // based on
+       // annotations on
+       // this advice
+
+       public ISourceLocation lastReportedMonitorExitJoinpointLocation = null;
+
+       public static Advice makeCflowEntry(World world, Pointcut entry, boolean isBelow, Member stackField, int nFreeVars,
+                       List innerCflowEntries, ResolvedType inAspect) {
+               Advice ret = world.createAdviceMunger(isBelow ? AdviceKind.CflowBelowEntry : AdviceKind.CflowEntry, entry, stackField, 0,
+                               entry);
+               // 0);
+               ret.innerCflowEntries = innerCflowEntries;
+               ret.nFreeVars = nFreeVars;
+               ret.concreteAspect = inAspect;
+               return ret;
+       }
+
+       public static Advice makePerCflowEntry(World world, Pointcut entry, boolean isBelow, Member stackField, ResolvedType inAspect,
+                       List innerCflowEntries) {
+               Advice ret = world.createAdviceMunger(isBelow ? AdviceKind.PerCflowBelowEntry : AdviceKind.PerCflowEntry, entry,
+                               stackField, 0, entry);
+               ret.innerCflowEntries = innerCflowEntries;
+               ret.concreteAspect = inAspect;
+               return ret;
+       }
+
+       public static Advice makePerObjectEntry(World world, Pointcut entry, boolean isThis, ResolvedType inAspect) {
+               Advice ret = world.createAdviceMunger(isThis ? AdviceKind.PerThisEntry : AdviceKind.PerTargetEntry, entry, null, 0, entry);
+
+               ret.concreteAspect = inAspect;
+               return ret;
+       }
+
+       // PTWIMPL per type within entry advice is what initializes the aspect
+       // instance in the matched type
+       public static Advice makePerTypeWithinEntry(World world, Pointcut p, ResolvedType inAspect) {
+               Advice ret = world.createAdviceMunger(AdviceKind.PerTypeWithinEntry, p, null, 0, p);
+               ret.concreteAspect = inAspect;
+               return ret;
+       }
+
+       public static Advice makeSoftener(World world, Pointcut entry, TypePattern exceptionType, ResolvedType inAspect,
+                       IHasSourceLocation loc) {
+               Advice ret = world.createAdviceMunger(AdviceKind.Softener, entry, null, 0, loc);
+
+               ret.exceptionType = exceptionType;
+               ret.concreteAspect = inAspect;
+               // System.out.println("made ret: " + ret + " with " + exceptionType);
+               return ret;
+       }
+
+       public Advice(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member signature) {
+               super(pointcut, attribute.getStart(), attribute.getEnd(), attribute.getSourceContext());
+               this.attribute = attribute;
+               kind = attribute.getKind(); // alias
+               this.signature = signature;
+               if (signature != null) {
+                       bindingParameterTypes = signature.getParameterTypes();
+               } else {
+                       bindingParameterTypes = new UnresolvedType[0];
+               }
+       }
+
+       public boolean match(Shadow shadow, World world) {
+               if (super.match(shadow, world)) {
+                       if (shadow.getKind() == Shadow.ExceptionHandler) {
+                               if (kind.isAfter() || kind == AdviceKind.Around) {
+                                       world.showMessage(IMessage.WARNING, WeaverMessages.format(WeaverMessages.ONLY_BEFORE_ON_HANDLER),
+                                                       getSourceLocation(), shadow.getSourceLocation());
+                                       return false;
+                               }
+                       }
+                       if (shadow.getKind() == Shadow.SynchronizationLock || shadow.getKind() == Shadow.SynchronizationUnlock) {
+                               if (kind == AdviceKind.Around
+                               // Don't work, see comments in SynchronizationTests
+                               // && attribute.getProceedCallSignatures()!=null
+                               // && attribute.getProceedCallSignatures().length!=0
+                               ) {
+                                       world.showMessage(IMessage.WARNING, WeaverMessages.format(WeaverMessages.NO_AROUND_ON_SYNCHRONIZATION),
+                                                       getSourceLocation(), shadow.getSourceLocation());
+                                       return false;
+                               }
+                       }
+
+                       if (hasExtraParameter() && kind == AdviceKind.AfterReturning) {
+                               ResolvedType resolvedExtraParameterType = getExtraParameterType().resolve(world);
+                               ResolvedType shadowReturnType = shadow.getReturnType().resolve(world);
+                               boolean matches = (resolvedExtraParameterType.isConvertableFrom(shadowReturnType) && shadow.getKind()
+                                               .hasReturnValue());
+                               if (matches && resolvedExtraParameterType.isParameterizedType()) {
+                                       maybeIssueUncheckedMatchWarning(resolvedExtraParameterType, shadowReturnType, shadow, world);
+                               }
+                               return matches;
+                       } else if (hasExtraParameter() && kind == AdviceKind.AfterThrowing) { // pr119749
+                               ResolvedType exceptionType = getExtraParameterType().resolve(world);
+                               if (!exceptionType.isCheckedException())
+                                       return true;
+                               UnresolvedType[] shadowThrows = shadow.getSignature().getExceptions(world);
+                               boolean matches = false;
+                               for (int i = 0; i < shadowThrows.length && !matches; i++) {
+                                       ResolvedType type = shadowThrows[i].resolve(world);
+                                       if (exceptionType.isAssignableFrom(type))
+                                               matches = true;
+                               }
+                               return matches;
+                       } else if (kind == AdviceKind.PerTargetEntry) {
+                               return shadow.hasTarget();
+                       } else if (kind == AdviceKind.PerThisEntry) {
+                               return shadow.hasThis();
+                       } else if (kind == AdviceKind.Around) {
+                               if (shadow.getKind() == Shadow.PreInitialization) {
+                                       world.showMessage(IMessage.WARNING, WeaverMessages.format(WeaverMessages.AROUND_ON_PREINIT),
+                                                       getSourceLocation(), shadow.getSourceLocation());
+                                       return false;
+                               } else if (shadow.getKind() == Shadow.Initialization) {
+                                       world.showMessage(IMessage.WARNING, WeaverMessages.format(WeaverMessages.AROUND_ON_INIT), getSourceLocation(),
+                                                       shadow.getSourceLocation());
+                                       return false;
+                               } else if (shadow.getKind() == Shadow.StaticInitialization
+                                               && shadow.getEnclosingType().resolve(world).isInterface()) {
+                                       world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.AROUND_ON_INTERFACE_STATICINIT, shadow
+                                                       .getEnclosingType().getName()), getSourceLocation(), shadow.getSourceLocation());
+                                       return false;
+                               } else {
+                                       // System.err.println(getSignature().getReturnType() +
+                                       // " from " + shadow.getReturnType());
+                                       if (getSignature().getReturnType() == ResolvedType.VOID) {
+                                               if (shadow.getReturnType() != ResolvedType.VOID) {
+                                                       world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.NON_VOID_RETURN, shadow),
+                                                                       getSourceLocation(), shadow.getSourceLocation());
+                                                       return false;
+                                               }
+                                       } else if (getSignature().getReturnType().equals(UnresolvedType.OBJECT)) {
+                                               return true;
+                                       } else {
+                                               ResolvedType shadowReturnType = shadow.getReturnType().resolve(world);
+                                               ResolvedType adviceReturnType = getSignature().getGenericReturnType().resolve(world);
+
+                                               if (shadowReturnType.isParameterizedType() && adviceReturnType.isRawType()) { // Set
+                                                       // <
+                                                       // Integer
+                                                       // >
+                                                       // and
+                                                       // Set
+                                                       ResolvedType shadowReturnGenericType = shadowReturnType.getGenericType(); // Set
+                                                       ResolvedType adviceReturnGenericType = adviceReturnType.getGenericType(); // Set
+                                                       if (shadowReturnGenericType.isAssignableFrom(adviceReturnGenericType)
+                                                                       && world.getLint().uncheckedAdviceConversion.isEnabled()) {
+                                                               world.getLint().uncheckedAdviceConversion.signal(new String[] { shadow.toString(),
+                                                                               shadowReturnType.getName(), adviceReturnType.getName() }, shadow.getSourceLocation(),
+                                                                               new ISourceLocation[] { getSourceLocation() });
+                                                       }
+                                               } else if (!shadowReturnType.isAssignableFrom(adviceReturnType)) {
+                                                       // System.err.println(this + ", " + sourceContext +
+                                                       // ", " + start);
+                                                       world.showMessage(IMessage.ERROR, WeaverMessages
+                                                                       .format(WeaverMessages.INCOMPATIBLE_RETURN_TYPE, shadow), getSourceLocation(), shadow
+                                                                       .getSourceLocation());
+                                                       return false;
+                                               }
+                                       }
+                               }
+                       }
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * In after returning advice if we are binding the extra parameter to a parameterized type we may not be able to do a type-safe
+        * conversion.
+        * 
+        * @param resolvedExtraParameterType the type in the after returning declaration
+        * @param shadowReturnType the type at the shadow
+        * @param world
+        */
+       private void maybeIssueUncheckedMatchWarning(ResolvedType afterReturningType, ResolvedType shadowReturnType, Shadow shadow,
+                       World world) {
+               boolean inDoubt = !afterReturningType.isAssignableFrom(shadowReturnType);
+               if (inDoubt && world.getLint().uncheckedArgument.isEnabled()) {
+                       String uncheckedMatchWith = afterReturningType.getSimpleBaseName();
+                       if (shadowReturnType.isParameterizedType() && (shadowReturnType.getRawType() == afterReturningType.getRawType())) {
+                               uncheckedMatchWith = shadowReturnType.getSimpleName();
+                       }
+                       if (!Utils.isSuppressing(getSignature().getAnnotations(), "uncheckedArgument")) {
+                               world.getLint().uncheckedArgument.signal(new String[] { afterReturningType.getSimpleName(), uncheckedMatchWith,
+                                               afterReturningType.getSimpleBaseName(), shadow.toResolvedString(world) }, getSourceLocation(),
+                                               new ISourceLocation[] { shadow.getSourceLocation() });
+                       }
+               }
+       }
+
+       // ----
+
+       public AdviceKind getKind() {
+               return kind;
+       }
+
+       public Member getSignature() {
+               return signature;
+       }
+
+       public boolean hasExtraParameter() {
+               return (getExtraParameterFlags() & ExtraArgument) != 0;
+       }
+
+       protected int getExtraParameterFlags() {
+               return attribute.getExtraParameterFlags();
+       }
+
+       protected int getExtraParameterCount() {
+               return countOnes(getExtraParameterFlags() & ParameterMask);
+       }
+
+       public UnresolvedType[] getBindingParameterTypes() {
+               return bindingParameterTypes;
+       }
+
+       public void setBindingParameterTypes(UnresolvedType[] types) {
+               bindingParameterTypes = types;
+       }
+
+       public static int countOnes(int bits) {
+               int ret = 0;
+               while (bits != 0) {
+                       if ((bits & 1) != 0)
+                               ret += 1;
+                       bits = bits >> 1;
+               }
+               return ret;
+       }
+
+       public int getBaseParameterCount() {
+               return getSignature().getParameterTypes().length - getExtraParameterCount();
+       }
+
+       public String[] getBaseParameterNames(World world) {
+               String[] allNames = getSignature().getParameterNames(world);
+               int extras = getExtraParameterCount();
+               if (extras == 0)
+                       return allNames;
+               String[] result = new String[getBaseParameterCount()];
+               for (int i = 0; i < result.length; i++) {
+                       result[i] = allNames[i];
+               }
+               return result;
+       }
+
+       public UnresolvedType getExtraParameterType() {
+               if (!hasExtraParameter())
+                       return ResolvedType.MISSING;
+               if (signature instanceof ResolvedMember) {
+                       if (getConcreteAspect().isAnnotationStyleAspect()) {
+                               // bug 122742 - if we're an annotation style aspect then one
+                               // of the extra parameters could be JoinPoint which we want
+                               // to ignore
+                               int baseParmCnt = getBaseParameterCount();
+                               UnresolvedType[] genericParameterTypes = ((ResolvedMember) signature).getGenericParameterTypes();
+                               while ((baseParmCnt + 1 < genericParameterTypes.length)
+                                               && (genericParameterTypes[baseParmCnt].equals(AjcMemberMaker.TYPEX_JOINPOINT)
+                                                               || genericParameterTypes[baseParmCnt].equals(AjcMemberMaker.TYPEX_STATICJOINPOINT) || genericParameterTypes[baseParmCnt]
+                                                               .equals(AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT))) {
+                                       baseParmCnt++;
+                               }
+                               return ((ResolvedMember) signature).getGenericParameterTypes()[baseParmCnt];
+                       }
+                       return ((ResolvedMember) signature).getGenericParameterTypes()[getBaseParameterCount()];
+               } else {
+                       return signature.getParameterTypes()[getBaseParameterCount()];
+               }
+       }
+
+       public UnresolvedType getDeclaringAspect() {
+               return getOriginalSignature().getDeclaringType();
+       }
+
+       protected Member getOriginalSignature() {
+               return signature;
+       }
+
+       protected String extraParametersToString() {
+               if (getExtraParameterFlags() == 0) {
+                       return "";
+               } else {
+                       return "(extraFlags: " + getExtraParameterFlags() + ")";
+               }
+       }
+
+       public Pointcut getPointcut() {
+               return pointcut;
+       }
+
+       // ----
+
+       /**
+        * @param fromType is guaranteed to be a non-abstract aspect
+        * @param clause has been concretized at a higher level
+        */
+       public ShadowMunger concretize(ResolvedType fromType, World world, PerClause clause) {
+               // assert !fromType.isAbstract();
+               Pointcut p = pointcut.concretize(fromType, getDeclaringType(), signature.getArity(), this);
+               if (clause != null) {
+                       Pointcut oldP = p;
+                       p = new AndPointcut(clause, p);
+                       p.copyLocationFrom(oldP);
+                       p.state = Pointcut.CONCRETE;
+
+                       // FIXME ? ATAJ copy unbound bindings to ignore
+                       p.m_ignoreUnboundBindingForNames = oldP.m_ignoreUnboundBindingForNames;
+               }
+
+               Advice munger = world.getWeavingSupport().createAdviceMunger(attribute, p, signature);
+               munger.concreteAspect = fromType;
+               munger.bindingParameterTypes = bindingParameterTypes;
+               munger.setDeclaringType(getDeclaringType());
+               // System.err.println("concretizing here " + p + " with clause " +
+               // clause);
+               return munger;
+       }
+
+       // ---- from object
+
+       public String toString() {
+               StringBuffer sb = new StringBuffer();
+               sb.append("(").append(getKind()).append(extraParametersToString());
+               sb.append(": ").append(pointcut).append("->").append(signature).append(")");
+               return sb.toString();
+               // return "("
+               // + getKind()
+               // + extraParametersToString()
+               // + ": "
+               // + pointcut
+               // + "->"
+               // + signature
+               // + ")";
+       }
+
+       // XXX this perhaps ought to take account of the other fields in advice ...
+       public boolean equals(Object other) {
+               if (!(other instanceof Advice))
+                       return false;
+               Advice o = (Advice) other;
+               return o.kind.equals(kind) && ((o.pointcut == null) ? (pointcut == null) : o.pointcut.equals(pointcut))
+                               && ((o.signature == null) ? (signature == null) : o.signature.equals(signature));
+               // && (AsmManager.getDefault().getHandleProvider().dependsOnLocation() ? ((o.getSourceLocation() == null) ?
+               // (getSourceLocation() == null)
+               // : o.getSourceLocation().equals(getSourceLocation()))
+               // : true) // pr134471 - remove when handles are improved
+               // // to be independent of location
+               // ;
+
+       }
+
+       private volatile int hashCode = 0;
+
+       public int hashCode() {
+               if (hashCode == 0) {
+                       int result = 17;
+                       result = 37 * result + kind.hashCode();
+                       result = 37 * result + ((pointcut == null) ? 0 : pointcut.hashCode());
+                       result = 37 * result + ((signature == null) ? 0 : signature.hashCode());
+                       hashCode = result;
+               }
+               return hashCode;
+       }
+
+       // ---- fields
+
+       public static final int ExtraArgument = 1;
+       public static final int ThisJoinPoint = 2;
+       public static final int ThisJoinPointStaticPart = 4;
+       public static final int ThisEnclosingJoinPointStaticPart = 8;
+       public static final int ParameterMask = 0xf;
+
+       public static final int CanInline = 0x40;
+
+       // for testing only
+       public void setLexicalPosition(int lexicalPosition) {
+               start = lexicalPosition;
+       }
+
+       public ResolvedType getConcreteAspect() {
+               return concreteAspect;
+       }
+
+       public boolean hasMatchedSomething() {
+               return hasMatchedAtLeastOnce;
+       }
+
+       public void setHasMatchedSomething(boolean hasMatchedSomething) {
+               hasMatchedAtLeastOnce = hasMatchedSomething;
+       }
+
+       public abstract boolean hasDynamicTests();
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AdviceKind.java b/org.aspectj.matcher/src/org/aspectj/weaver/AdviceKind.java
new file mode 100644 (file)
index 0000000..7242ef6
--- /dev/null
@@ -0,0 +1,117 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.IOException;
+
+import org.aspectj.util.TypeSafeEnum;
+
+/**
+ * The five kinds of advice in AspectJ.
+ * 
+ * @author Erik Hilsdale
+ * @author Jim Hugunin
+ */
+public class AdviceKind extends TypeSafeEnum {
+       private int precedence;
+       private boolean isAfter;
+       private boolean isCflow;
+    public AdviceKind(String name, int key, int precedence, boolean isAfter, boolean isCflow) {
+       super(name, key);
+       this.precedence = precedence;
+       this.isAfter = isAfter;
+       this.isCflow = isCflow;
+    }
+    
+    public static AdviceKind read(VersionedDataInputStream s) throws IOException {
+        int key = s.readByte();
+        switch(key) {
+            case 1: return Before;
+            case 2: return After;
+            case 3: return AfterThrowing;
+            case 4: return AfterReturning;
+            case 5: return Around;
+            case 6: return CflowEntry;
+            case 7: return CflowBelowEntry;
+
+            case 8: return InterInitializer;
+            
+            case 9: return PerCflowEntry;
+            case 10: return PerCflowBelowEntry;
+            case 11: return PerThisEntry;
+            case 12: return PerTargetEntry;
+
+            case 13: return Softener;
+            
+            case 14: return PerTypeWithinEntry;
+        }
+        throw new RuntimeException("unimplemented kind: " + key);
+    }
+    
+    public static final AdviceKind Before         = new AdviceKind("before", 1, 0, false, false);
+    public static final AdviceKind After          = new AdviceKind("after", 2, 0, true, false);
+    public static final AdviceKind AfterThrowing  = new AdviceKind("afterThrowing", 3, 0, true, false);
+    public static final AdviceKind AfterReturning = new AdviceKind("afterReturning", 4, 0, true, false);
+    public static final AdviceKind Around         = new AdviceKind("around", 5, 0, false, false);
+    
+    // these kinds can't be declared, but are used by the weaver
+    public static final AdviceKind CflowEntry  = new AdviceKind("cflowEntry", 6, 1, false, true);
+    public static final AdviceKind CflowBelowEntry = new AdviceKind("cflowBelowEntry", 7, -1, false, true);  //XXX resolve precednece with the below
+    public static final AdviceKind InterInitializer   = new AdviceKind("interInitializer", 8, -2, false, false);
+
+    public static final AdviceKind PerCflowEntry         = new AdviceKind("perCflowEntry", 9, 1, false, true);
+    public static final AdviceKind PerCflowBelowEntry         = new AdviceKind("perCflowBelowEntry", 10, -1, false, true); 
+
+    public static final AdviceKind PerThisEntry         = new AdviceKind("perThisEntry", 11, 1, false, false);
+    public static final AdviceKind PerTargetEntry         = new AdviceKind("perTargetEntry", 12, 1, false, false); 
+
+    public static final AdviceKind Softener         = new AdviceKind("softener", 13, 1, false, false); 
+    
+    // PTWIMPL Advice representing when aspect should be initialized
+    public static final AdviceKind PerTypeWithinEntry   = new AdviceKind("perTypeWithinEntry",14,1,false,false);
+   
+
+    public static AdviceKind stringToKind(String s) {
+        if (s.equals(Before.getName())) return Before;
+        if (s.equals(After.getName())) return After;
+        if (s.equals(AfterThrowing.getName())) return AfterThrowing;
+        if (s.equals(AfterReturning.getName())) return AfterReturning;
+        if (s.equals(Around.getName())) return Around;
+        throw new IllegalArgumentException("unknown kind: " + "\"" + s + "\"");
+    }
+
+       public boolean isAfter() {
+               return this.isAfter;
+       }
+       
+       public boolean isCflow() {
+               return this.isCflow;
+       }
+
+       public int getPrecedence() {
+               return precedence;
+       }
+
+       public boolean isPerEntry() {
+               return 
+                   this == PerCflowEntry || this == PerCflowBelowEntry ||
+                       this == PerThisEntry || this == PerTargetEntry || 
+                       this == PerTypeWithinEntry; // PTWIMPL Allow for PTW case
+       }
+       
+       public boolean isPerObjectEntry() {
+               return this == PerThisEntry || this == PerTargetEntry;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AjAttribute.java b/org.aspectj.matcher/src/org/aspectj/weaver/AjAttribute.java
new file mode 100644 (file)
index 0000000..00ea0b0
--- /dev/null
@@ -0,0 +1,699 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.bridge.Version;
+import org.aspectj.util.FileUtil;
+import org.aspectj.weaver.patterns.Declare;
+import org.aspectj.weaver.patterns.IScope;
+import org.aspectj.weaver.patterns.PerClause;
+import org.aspectj.weaver.patterns.Pointcut;
+
+/**
+ * These attributes are written to and read from .class files (see the JVM
+ * spec).
+ * 
+ * <p>
+ * Each member or type can have a number of AjAttributes. Each such attribute is
+ * in 1-1 correspondence with an Unknown bcel attribute. Creating one of these
+ * does NOTHING to the underlying thing, so if you really want to add an
+ * attribute to a particular thing, well, you'd better actually do that.
+ * 
+ * @author Erik Hilsdale
+ * @author Jim Hugunin
+ */
+public abstract class AjAttribute {
+
+       public static final String AttributePrefix = "org.aspectj.weaver";
+
+       protected abstract void write(DataOutputStream s) throws IOException;
+
+       public abstract String getNameString();
+
+       public char[] getNameChars() {
+               return getNameString().toCharArray();
+       }
+
+       /**
+        * Just writes the contents
+        */
+       public byte[] getBytes() {
+               try {
+                       ByteArrayOutputStream b0 = new ByteArrayOutputStream();
+                       DataOutputStream s0 = new DataOutputStream(b0);
+                       write(s0);
+                       return b0.toByteArray();
+               } catch (IOException e) {
+                       // shouldn't happen with ByteArrayOutputStreams
+                       throw new RuntimeException("sanity check");
+               }
+       }
+
+       /**
+        * Writes the full attribute, i.e. name_index, length, and contents
+        */
+       public byte[] getAllBytes(short nameIndex) {
+               try {
+                       byte[] bytes = getBytes();
+
+                       ByteArrayOutputStream b0 = new ByteArrayOutputStream();
+                       DataOutputStream s0 = new DataOutputStream(b0);
+
+                       s0.writeShort(nameIndex);
+                       s0.writeInt(bytes.length);
+                       s0.write(bytes);
+                       return b0.toByteArray();
+               } catch (IOException e) {
+                       // shouldn't happen with ByteArrayOutputStreams
+                       throw new RuntimeException("sanity check");
+               }
+       }
+
+       public static AjAttribute read(AjAttribute.WeaverVersionInfo v, String name, byte[] bytes, ISourceContext context, World w) {
+               try {
+                       if (bytes == null)
+                               bytes = new byte[0];
+                       VersionedDataInputStream s = new VersionedDataInputStream(new ByteArrayInputStream(bytes));
+                       s.setVersion(v);
+                       if (name.equals(Aspect.AttributeName)) {
+                               return new Aspect(PerClause.readPerClause(s, context));
+                       } else if (name.equals(MethodDeclarationLineNumberAttribute.AttributeName)) {
+                               return MethodDeclarationLineNumberAttribute.read(s);
+                       } else if (name.equals(WeaverState.AttributeName)) {
+                               return new WeaverState(WeaverStateInfo.read(s, context));
+                       } else if (name.equals(WeaverVersionInfo.AttributeName)) {
+                               return WeaverVersionInfo.read(s);
+                       } else if (name.equals(AdviceAttribute.AttributeName)) {
+                               AdviceAttribute aa = AdviceAttribute.read(s, context);
+                               aa.getPointcut().check(context, w);
+                               return aa;
+                       } else if (name.equals(PointcutDeclarationAttribute.AttributeName)) {
+                               PointcutDeclarationAttribute pda = new PointcutDeclarationAttribute(ResolvedPointcutDefinition.read(s, context));
+                               pda.pointcutDef.getPointcut().check(context, w);
+                               return pda;
+                       } else if (name.equals(TypeMunger.AttributeName)) {
+                               return new TypeMunger(ResolvedTypeMunger.read(s, context));
+                       } else if (name.equals(AjSynthetic.AttributeName)) {
+                               return new AjSynthetic();
+                       } else if (name.equals(DeclareAttribute.AttributeName)) {
+                               return new DeclareAttribute(Declare.read(s, context));
+                       } else if (name.equals(PrivilegedAttribute.AttributeName)) {
+                               return PrivilegedAttribute.read(s, context);
+                       } else if (name.equals(SourceContextAttribute.AttributeName)) {
+                               return SourceContextAttribute.read(s);
+                       } else if (name.equals(EffectiveSignatureAttribute.AttributeName)) {
+                               return EffectiveSignatureAttribute.read(s, context);
+                       } else {
+                               // We have to tell the user about this...
+                               if (w == null || w.getMessageHandler() == null)
+                                       throw new BCException("unknown attribute" + name);
+                               w.getMessageHandler().handleMessage(MessageUtil.warn("unknown attribute encountered " + name));
+                               return null;
+                       }
+               } catch (BCException e) {
+                       throw new BCException("malformed " + name + " attribute (length:" + bytes.length + ")" + e);
+               } catch (IOException e) {
+                       throw new BCException("malformed " + name + " attribute (length:" + bytes.length + ")" + e);
+               }
+       }
+
+       // ----
+
+       /**
+        * Synthetic members should have NO advice put on them or on their contents.
+        * This attribute is currently unused as we consider all members starting
+        * with NameMangler.PREFIX to automatically be synthetic. As we use this we
+        * might find that we want multiple kinds of synthetic. In particular, if we
+        * want to treat the call to a synthetic getter (say, of an introduced
+        * field) as a field reference itself, then a method might want a particular
+        * kind of AjSynthetic attribute that also includes a signature of what it
+        * stands for.
+        */
+       public static class AjSynthetic extends AjAttribute {
+               public static final String AttributeName = "org.aspectj.weaver.AjSynthetic";
+
+               public String getNameString() {
+                       return AttributeName;
+               }
+
+               // private ResolvedTypeMunger munger;
+               public AjSynthetic() {
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+               }
+       }
+
+       public static class TypeMunger extends AjAttribute {
+               public static final String AttributeName = "org.aspectj.weaver.TypeMunger";
+
+               public String getNameString() {
+                       return AttributeName;
+               }
+
+               private final ResolvedTypeMunger munger;
+
+               public TypeMunger(ResolvedTypeMunger munger) {
+                       this.munger = munger;
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+                       munger.write(s);
+               }
+
+               public ConcreteTypeMunger reify(World world, ResolvedType aspectType) {
+                       return world.getWeavingSupport().concreteTypeMunger(munger, aspectType);
+               }
+       }
+
+       public static class WeaverState extends AjAttribute {
+               public static final String AttributeName = "org.aspectj.weaver.WeaverState";
+
+               public String getNameString() {
+                       return AttributeName;
+               }
+
+               private final WeaverStateInfo kind;
+
+               public WeaverState(WeaverStateInfo kind) {
+                       this.kind = kind;
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+                       kind.write(s);
+               }
+
+               public WeaverStateInfo reify() {
+                       return kind;
+               }
+       }
+
+       public static class WeaverVersionInfo extends AjAttribute {
+               public static final String AttributeName = "org.aspectj.weaver.WeaverVersion";
+
+               // If you change the format of an AspectJ class file, you have two
+               // options:
+               // - changing the minor version means you have not added anything that
+               // prevents
+               // previous versions of the weaver from operating (e.g.
+               // MethodDeclarationLineNumber attribute)
+               // - changing the major version means you have added something that
+               // prevents previous
+               // versions of the weaver from operating correctly.
+               //
+               // The user will get a warning for any org.aspectj.weaver attributes the
+               // weaver does
+               // not recognize.
+
+               // When we don't know ... (i.e. pre 1.2.1)
+               public final static short WEAVER_VERSION_MAJOR_UNKNOWN = 0;
+               public final static short WEAVER_VERSION_MINOR_UNKNOWN = 0;
+
+               // These are the weaver major/minor numbers for AspectJ 1.2.1
+               public final static short WEAVER_VERSION_MAJOR_AJ121 = 1;
+               public final static short WEAVER_VERSION_MINOR_AJ121 = 0;
+
+               // These are the weaver major/minor numbers for AspectJ 1.5.0
+               public final static short WEAVER_VERSION_MAJOR_AJ150M4 = 3;
+               public final static short WEAVER_VERSION_MAJOR_AJ150 = 2;
+               public final static short WEAVER_VERSION_MINOR_AJ150 = 0;
+
+               // These are the weaver major/minor numbers for AspectJ 1.6.0
+               public final static short WEAVER_VERSION_MAJOR_AJ160M2 = 5;
+               public final static short WEAVER_VERSION_MAJOR_AJ160 = 4;
+               public final static short WEAVER_VERSION_MINOR_AJ160 = 0;
+
+               // These are the weaver major/minor numbers for AspectJ 1.6.1
+               public final static short WEAVER_VERSION_MAJOR_AJ161 = 6; // annotation
+               // value
+               // binding
+               public final static short WEAVER_VERSION_MINOR_AJ161 = 0;
+
+               // These are the weaver major/minor versions for *this* weaver
+               private final static short CURRENT_VERSION_MAJOR = WEAVER_VERSION_MAJOR_AJ161;
+               private final static short CURRENT_VERSION_MINOR = WEAVER_VERSION_MINOR_AJ161;
+
+               public final static WeaverVersionInfo UNKNOWN = new WeaverVersionInfo(WEAVER_VERSION_MAJOR_UNKNOWN,
+                               WEAVER_VERSION_MINOR_UNKNOWN);
+               public final static WeaverVersionInfo CURRENT = new WeaverVersionInfo(CURRENT_VERSION_MAJOR, CURRENT_VERSION_MINOR);
+
+               // These are the versions read in from a particular class file.
+               private final short major_version;
+               private final short minor_version;
+
+               private long buildstamp = Version.NOTIME;
+
+               public String getNameString() {
+                       return AttributeName;
+               }
+
+               // Default ctor uses the current version numbers
+               public WeaverVersionInfo() {
+                       major_version = CURRENT_VERSION_MAJOR;
+                       minor_version = CURRENT_VERSION_MINOR;
+               }
+
+               public WeaverVersionInfo(short major, short minor) {
+                       major_version = major;
+                       minor_version = minor;
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+                       s.writeShort(CURRENT_VERSION_MAJOR);
+                       s.writeShort(CURRENT_VERSION_MINOR);
+                       s.writeLong(Version.getTime()); // build used to construct the
+                       // class...
+               }
+
+               public static WeaverVersionInfo read(VersionedDataInputStream s) throws IOException {
+                       short major = s.readShort();
+                       short minor = s.readShort();
+                       WeaverVersionInfo wvi = new WeaverVersionInfo(major, minor);
+                       if (s.getMajorVersion() >= WEAVER_VERSION_MAJOR_AJ150M4) {
+                               long stamp = 0;
+                               try {
+                                       stamp = s.readLong();
+                                       wvi.setBuildstamp(stamp);
+                               } catch (EOFException eof) {
+                                       // didnt find that build stamp - its not the end of the
+                                       // world
+                               }
+                       }
+                       return wvi;
+               }
+
+               public short getMajorVersion() {
+                       return major_version;
+               }
+
+               public short getMinorVersion() {
+                       return minor_version;
+               }
+
+               public static short getCurrentWeaverMajorVersion() {
+                       return CURRENT_VERSION_MAJOR;
+               }
+
+               public static short getCurrentWeaverMinorVersion() {
+                       return CURRENT_VERSION_MINOR;
+               }
+
+               public void setBuildstamp(long stamp) {
+                       buildstamp = stamp;
+               }
+
+               public long getBuildstamp() {
+                       return buildstamp;
+               }
+
+               public String toString() {
+                       return major_version + "." + minor_version;
+               }
+
+               public static String toCurrentVersionString() {
+                       return CURRENT_VERSION_MAJOR + "." + CURRENT_VERSION_MINOR;
+               }
+
+       }
+
+       public static class SourceContextAttribute extends AjAttribute {
+               public static final String AttributeName = "org.aspectj.weaver.SourceContext";
+
+               public String getNameString() {
+                       return AttributeName;
+               }
+
+               private final String sourceFileName;
+               private final int[] lineBreaks;
+
+               public SourceContextAttribute(String sourceFileName, int[] lineBreaks) {
+                       this.sourceFileName = sourceFileName;
+                       this.lineBreaks = lineBreaks;
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+                       s.writeUTF(sourceFileName);
+                       FileUtil.writeIntArray(lineBreaks, s);
+               }
+
+               public static SourceContextAttribute read(VersionedDataInputStream s) throws IOException {
+                       return new SourceContextAttribute(s.readUTF(), FileUtil.readIntArray(s));
+               }
+
+               public int[] getLineBreaks() {
+                       return lineBreaks;
+               }
+
+               public String getSourceFileName() {
+                       return sourceFileName;
+               }
+       }
+
+       public static class MethodDeclarationLineNumberAttribute extends AjAttribute {
+
+               public static final String AttributeName = "org.aspectj.weaver.MethodDeclarationLineNumber";
+
+               public String getNameString() {
+                       return AttributeName;
+               }
+
+               private final int lineNumber;
+
+               // AV: added in 1.5 M3 thus handling cases where we don't have that
+               // information
+               private final int offset;
+
+               public MethodDeclarationLineNumberAttribute(int line, int offset) {
+                       lineNumber = line;
+                       this.offset = offset;
+               }
+
+               public int getLineNumber() {
+                       return lineNumber;
+               }
+
+               public int getOffset() {
+                       return offset;
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+                       s.writeInt(lineNumber);
+                       s.writeInt(offset);
+               }
+
+               public static MethodDeclarationLineNumberAttribute read(VersionedDataInputStream s) throws IOException {
+                       int line = s.readInt();
+                       int offset = 0;
+                       if (s.available() > 0) {
+                               offset = s.readInt();
+                       }
+                       return new MethodDeclarationLineNumberAttribute(line, offset);
+               }
+
+               public String toString() {
+                       return AttributeName + ": " + lineNumber + ":" + offset;
+               }
+       }
+
+       public static class PointcutDeclarationAttribute extends AjAttribute {
+               public static final String AttributeName = "org.aspectj.weaver.PointcutDeclaration";
+
+               public String getNameString() {
+                       return AttributeName;
+               }
+
+               private final ResolvedPointcutDefinition pointcutDef;
+
+               public PointcutDeclarationAttribute(ResolvedPointcutDefinition pointcutDef) {
+                       this.pointcutDef = pointcutDef;
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+                       pointcutDef.write(s);
+               }
+
+               public ResolvedPointcutDefinition reify() {
+                       return pointcutDef;
+               }
+       }
+
+       public static class DeclareAttribute extends AjAttribute {
+               public static final String AttributeName = "org.aspectj.weaver.Declare";
+
+               public String getNameString() {
+                       return AttributeName;
+               }
+
+               private final Declare declare;
+
+               public DeclareAttribute(Declare declare) {
+                       this.declare = declare;
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+                       declare.write(s);
+               }
+
+               public Declare getDeclare() {
+                       return declare;
+               }
+       }
+
+       public static class AdviceAttribute extends AjAttribute {
+               public static final String AttributeName = "org.aspectj.weaver.Advice";
+
+               public String getNameString() {
+                       return AttributeName;
+               }
+
+               private final AdviceKind kind;
+               private final Pointcut pointcut;
+               private final int extraParameterFlags;
+               private final int start;
+               private final int end;
+               private final ISourceContext sourceContext;
+
+               // these are only used by around advice
+               private boolean proceedInInners;
+               private ResolvedMember[] proceedCallSignatures; // size == # of proceed
+               // calls in body
+               private boolean[] formalsUnchangedToProceed; // size == formals.size
+               private UnresolvedType[] declaredExceptions;
+
+               /**
+                * @param lexicalPosition must be greater than the lexicalPosition of
+                *            any advice declared before this one in an aspect,
+                *            otherwise, it can be any value.
+                */
+               public AdviceAttribute(AdviceKind kind, Pointcut pointcut, int extraArgumentFlags, int start, int end,
+                               ISourceContext sourceContext) {
+                       this.kind = kind;
+                       this.pointcut = pointcut;
+                       extraParameterFlags = extraArgumentFlags;
+                       this.start = start;
+                       this.end = end;
+                       this.sourceContext = sourceContext;
+
+                       // XXX put this back when testing works better (or fails better)
+                       // if (kind == AdviceKind.Around) throw new
+                       // IllegalArgumentException("not for around");
+               }
+
+               public AdviceAttribute(AdviceKind kind, Pointcut pointcut, int extraArgumentFlags, int start, int end,
+                               ISourceContext sourceContext, boolean proceedInInners, ResolvedMember[] proceedCallSignatures,
+                               boolean[] formalsUnchangedToProceed, UnresolvedType[] declaredExceptions) {
+                       this.kind = kind;
+                       this.pointcut = pointcut;
+                       extraParameterFlags = extraArgumentFlags;
+                       this.start = start;
+                       this.end = end;
+                       this.sourceContext = sourceContext;
+
+                       if (kind != AdviceKind.Around)
+                               throw new IllegalArgumentException("only for around");
+
+                       this.proceedInInners = proceedInInners;
+                       this.proceedCallSignatures = proceedCallSignatures;
+                       this.formalsUnchangedToProceed = formalsUnchangedToProceed;
+                       this.declaredExceptions = declaredExceptions;
+               }
+
+               public static AdviceAttribute read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+                       AdviceKind kind = AdviceKind.read(s);
+                       if (kind == AdviceKind.Around) {
+                               return new AdviceAttribute(kind, Pointcut.read(s, context), s.readByte(), s.readInt(), s.readInt(), context, s
+                                               .readBoolean(), ResolvedMemberImpl.readResolvedMemberArray(s, context), FileUtil.readBooleanArray(s),
+                                               UnresolvedType.readArray(s));
+                       } else {
+                               return new AdviceAttribute(kind, Pointcut.read(s, context), s.readByte(), s.readInt(), s.readInt(), context);
+                       }
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+                       kind.write(s);
+                       pointcut.write(s);
+                       s.writeByte(extraParameterFlags);
+                       s.writeInt(start);
+                       s.writeInt(end);
+
+                       if (kind == AdviceKind.Around) {
+                               s.writeBoolean(proceedInInners);
+                               ResolvedMemberImpl.writeArray(proceedCallSignatures, s);
+                               FileUtil.writeBooleanArray(formalsUnchangedToProceed, s);
+                               UnresolvedType.writeArray(declaredExceptions, s);
+                       }
+               }
+
+               public Advice reify(Member signature, World world) {
+                       return world.getWeavingSupport().createAdviceMunger(this, pointcut, signature);
+               }
+
+               public String toString() {
+                       return "AdviceAttribute(" + kind + ", " + pointcut + ", " + extraParameterFlags + ", " + start + ")";
+               }
+
+               public int getExtraParameterFlags() {
+                       return extraParameterFlags;
+               }
+
+               public AdviceKind getKind() {
+                       return kind;
+               }
+
+               public Pointcut getPointcut() {
+                       return pointcut;
+               }
+
+               public UnresolvedType[] getDeclaredExceptions() {
+                       return declaredExceptions;
+               }
+
+               public boolean[] getFormalsUnchangedToProceed() {
+                       return formalsUnchangedToProceed;
+               }
+
+               public ResolvedMember[] getProceedCallSignatures() {
+                       return proceedCallSignatures;
+               }
+
+               public boolean isProceedInInners() {
+                       return proceedInInners;
+               }
+
+               public int getEnd() {
+                       return end;
+               }
+
+               public ISourceContext getSourceContext() {
+                       return sourceContext;
+               }
+
+               public int getStart() {
+                       return start;
+               }
+
+       }
+
+       public static class Aspect extends AjAttribute {
+               public static final String AttributeName = "org.aspectj.weaver.Aspect";
+
+               public String getNameString() {
+                       return AttributeName;
+               }
+
+               private final PerClause perClause;
+               private IScope resolutionScope;
+
+               public Aspect(PerClause perClause) {
+                       this.perClause = perClause;
+               }
+
+               public PerClause reify(ResolvedType inAspect) {
+                       // XXXperClause.concretize(inAspect);
+                       return perClause;
+               }
+
+               public PerClause reifyFromAtAspectJ(ResolvedType inAspect) {
+                       perClause.resolve(resolutionScope);
+                       return perClause;
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+                       perClause.write(s);
+               }
+
+               public void setResolutionScope(IScope binding) {
+                       resolutionScope = binding;
+               }
+       }
+
+       public static class PrivilegedAttribute extends AjAttribute {
+               public static final String AttributeName = "org.aspectj.weaver.Privileged";
+
+               public String getNameString() {
+                       return AttributeName;
+               }
+
+               private final ResolvedMember[] accessedMembers;
+
+               public PrivilegedAttribute(ResolvedMember[] accessedMembers) {
+                       this.accessedMembers = accessedMembers;
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+                       ResolvedMemberImpl.writeArray(accessedMembers, s);
+               }
+
+               public ResolvedMember[] getAccessedMembers() {
+                       return accessedMembers;
+               }
+
+               public static PrivilegedAttribute read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+                       return new PrivilegedAttribute(ResolvedMemberImpl.readResolvedMemberArray(s, context));
+               }
+       }
+
+       public static class EffectiveSignatureAttribute extends AjAttribute {
+               public static final String AttributeName = "org.aspectj.weaver.EffectiveSignature";
+
+               public String getNameString() {
+                       return AttributeName;
+               }
+
+               private final ResolvedMember effectiveSignature;
+               private final Shadow.Kind shadowKind;
+               private final boolean weaveBody;
+
+               public EffectiveSignatureAttribute(ResolvedMember effectiveSignature, Shadow.Kind shadowKind, boolean weaveBody) {
+                       this.effectiveSignature = effectiveSignature;
+                       this.shadowKind = shadowKind;
+                       this.weaveBody = weaveBody;
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+                       effectiveSignature.write(s);
+                       shadowKind.write(s);
+                       s.writeBoolean(weaveBody);
+               }
+
+               public static EffectiveSignatureAttribute read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+                       return new EffectiveSignatureAttribute(ResolvedMemberImpl.readResolvedMember(s, context), Shadow.Kind.read(s), s
+                                       .readBoolean());
+               }
+
+               public ResolvedMember getEffectiveSignature() {
+                       return effectiveSignature;
+               }
+
+               public String toString() {
+                       return "EffectiveSignatureAttribute(" + effectiveSignature + ", " + shadowKind + ")";
+               }
+
+               public Shadow.Kind getShadowKind() {
+                       return shadowKind;
+               }
+
+               public boolean isWeaveBody() {
+                       return weaveBody;
+               }
+
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AjcMemberMaker.java b/org.aspectj.matcher/src/org/aspectj/weaver/AjcMemberMaker.java
new file mode 100644 (file)
index 0000000..e761415
--- /dev/null
@@ -0,0 +1,621 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+
+//import org.aspectj.weaver.ResolvedType.Name;
+
+public class AjcMemberMaker {
+       private static final int PUBLIC_STATIC_FINAL = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL;
+
+       private static final int PRIVATE_STATIC = Modifier.PRIVATE | Modifier.STATIC;
+
+       private static final int PUBLIC_STATIC = Modifier.PUBLIC | Modifier.STATIC;
+
+       private static final int BRIDGE = 0x0040;
+
+       private static final int VISIBILITY = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
+
+       public static final UnresolvedType CFLOW_STACK_TYPE = UnresolvedType.forName(NameMangler.CFLOW_STACK_TYPE);
+       public static final UnresolvedType AROUND_CLOSURE_TYPE = UnresolvedType
+                       .forSignature("Lorg/aspectj/runtime/internal/AroundClosure;");
+
+       public static final UnresolvedType CONVERSIONS_TYPE = UnresolvedType.forSignature("Lorg/aspectj/runtime/internal/Conversions;");
+
+       public static final UnresolvedType NO_ASPECT_BOUND_EXCEPTION = UnresolvedType
+                       .forSignature("Lorg/aspectj/lang/NoAspectBoundException;");
+
+       public static ResolvedMember ajcPreClinitMethod(UnresolvedType declaringType) {
+               return new ResolvedMemberImpl(Member.METHOD, declaringType, PRIVATE_STATIC, NameMangler.AJC_PRE_CLINIT_NAME, "()V");
+       }
+
+       public static ResolvedMember ajcPostClinitMethod(UnresolvedType declaringType) {
+               return new ResolvedMemberImpl(Member.METHOD, declaringType, PRIVATE_STATIC, NameMangler.AJC_POST_CLINIT_NAME, "()V");
+       }
+
+       public static Member noAspectBoundExceptionInit() {
+               return new ResolvedMemberImpl(Member.METHOD, NO_ASPECT_BOUND_EXCEPTION, Modifier.PUBLIC, "<init>", "()V");
+       }
+
+       public static Member noAspectBoundExceptionInit2() {
+               return new ResolvedMemberImpl(Member.METHOD, NO_ASPECT_BOUND_EXCEPTION, Modifier.PUBLIC, "<init>",
+                               "(Ljava/lang/String;Ljava/lang/Throwable;)V");
+       }
+
+       public static Member noAspectBoundExceptionInitWithCause() {
+               return new ResolvedMemberImpl(Member.METHOD, NO_ASPECT_BOUND_EXCEPTION, Modifier.PUBLIC, "<init>",
+                               "(Ljava/lang/String;Ljava/lang/Throwable;)V");
+       }
+
+       public static ResolvedMember perCflowPush(UnresolvedType declaringType) {
+               return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, NameMangler.PERCFLOW_PUSH_METHOD, "()V");
+       }
+
+       public static ResolvedMember perCflowField(UnresolvedType declaringType) {
+               return new ResolvedMemberImpl(Member.FIELD, declaringType, PUBLIC_STATIC_FINAL, NameMangler.PERCFLOW_FIELD_NAME,
+                               CFLOW_STACK_TYPE.getSignature());
+       }
+
+       public static ResolvedMember perSingletonField(UnresolvedType declaringType) {
+               return new ResolvedMemberImpl(Member.FIELD, declaringType, PUBLIC_STATIC_FINAL, NameMangler.PERSINGLETON_FIELD_NAME,
+                               declaringType.getSignature());
+       }
+
+       public static ResolvedMember initFailureCauseField(UnresolvedType declaringType) {
+               return new ResolvedMemberImpl(Member.FIELD, declaringType, PRIVATE_STATIC, NameMangler.INITFAILURECAUSE_FIELD_NAME,
+                               UnresolvedType.THROWABLE.getSignature());
+       }
+
+       public static ResolvedMember perObjectField(UnresolvedType declaringType, ResolvedType aspectType) {
+               int modifiers = Modifier.PRIVATE;
+               if (!UnresolvedType.SERIALIZABLE.resolve(aspectType.getWorld()).isAssignableFrom(aspectType)) {
+                       modifiers |= Modifier.TRANSIENT;
+               }
+               return new ResolvedMemberImpl(Member.FIELD, declaringType, modifiers, aspectType, NameMangler
+                               .perObjectInterfaceField(aspectType), UnresolvedType.NONE);
+       }
+
+       // PTWIMPL ResolvedMember for aspect instance field, declared in matched type
+       public static ResolvedMember perTypeWithinField(UnresolvedType declaringType, ResolvedType aspectType) {
+               int modifiers = Modifier.PRIVATE | Modifier.STATIC;
+               if (!isSerializableAspect(aspectType)) {
+                       modifiers |= Modifier.TRANSIENT;
+               }
+               return new ResolvedMemberImpl(Member.FIELD, declaringType, modifiers, aspectType, NameMangler
+                               .perTypeWithinFieldForTarget(aspectType), UnresolvedType.NONE);
+       }
+
+       // PTWIMPL ResolvedMember for type instance field, declared in aspect
+       // (holds typename for which aspect instance exists)
+       public static ResolvedMember perTypeWithinWithinTypeField(UnresolvedType declaringType, ResolvedType aspectType) {
+               int modifiers = Modifier.PRIVATE;
+               if (!isSerializableAspect(aspectType)) {
+                       modifiers |= Modifier.TRANSIENT;
+               }
+               return new ResolvedMemberImpl(Member.FIELD, declaringType, modifiers, UnresolvedType.JAVA_LANG_STRING,
+                               NameMangler.PERTYPEWITHIN_WITHINTYPEFIELD, UnresolvedType.NONE);
+       }
+
+       private static boolean isSerializableAspect(ResolvedType aspectType) {
+               return UnresolvedType.SERIALIZABLE.resolve(aspectType.getWorld()).isAssignableFrom(aspectType);
+       }
+
+       public static ResolvedMember perObjectBind(UnresolvedType declaringType) {
+               return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, NameMangler.PEROBJECT_BIND_METHOD,
+                               "(Ljava/lang/Object;)V");
+       }
+
+       // PTWIMPL ResolvedMember for getInstance() method, declared in aspect
+       public static ResolvedMember perTypeWithinGetInstance(UnresolvedType declaringType) {
+               // private static a.X ajc$getInstance(java.lang.Class)
+               ResolvedMemberImpl rm = new ResolvedMemberImpl(Member.METHOD, declaringType, PRIVATE_STATIC, declaringType, // return value
+                               NameMangler.PERTYPEWITHIN_GETINSTANCE_METHOD, new UnresolvedType[] { UnresolvedType.JAVA_LANG_CLASS });
+               return rm;
+       }
+
+       // PTWIMPL ResolvedMember for getWithinTypeName() method
+       public static ResolvedMember perTypeWithinGetWithinTypeNameMethod(UnresolvedType declaringType, boolean inJava5Mode) {
+               // public String getWithinTypeName()
+               ResolvedMemberImpl rm = new ResolvedMemberImpl(Member.METHOD, declaringType, Modifier.PUBLIC,
+                               UnresolvedType.JAVA_LANG_STRING, // return value
+                               NameMangler.PERTYPEWITHIN_GETWITHINTYPENAME_METHOD, UnresolvedType.NONE);
+               return rm;
+       }
+
+       public static ResolvedMember perTypeWithinCreateAspectInstance(UnresolvedType declaringType) {
+               // public static a.X ajc$createAspectInstance(java.lang.String)
+               ResolvedMemberImpl rm = new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, declaringType, // return value
+                               NameMangler.PERTYPEWITHIN_CREATEASPECTINSTANCE_METHOD, new UnresolvedType[] { UnresolvedType
+                                               .forSignature("Ljava/lang/String;") }, new UnresolvedType[] {});
+               return rm;
+       }
+
+       public static UnresolvedType perObjectInterfaceType(UnresolvedType aspectType) {
+               return UnresolvedType.forName(aspectType.getName() + "$ajcMightHaveAspect");
+       }
+
+       public static ResolvedMember perObjectInterfaceGet(UnresolvedType aspectType) {
+               return new ResolvedMemberImpl(Member.METHOD, perObjectInterfaceType(aspectType), Modifier.PUBLIC | Modifier.ABSTRACT,
+                               NameMangler.perObjectInterfaceGet(aspectType), "()" + aspectType.getSignature());
+       }
+
+       public static ResolvedMember perObjectInterfaceSet(UnresolvedType aspectType) {
+               return new ResolvedMemberImpl(Member.METHOD, perObjectInterfaceType(aspectType), Modifier.PUBLIC | Modifier.ABSTRACT,
+                               NameMangler.perObjectInterfaceSet(aspectType), "(" + aspectType.getSignature() + ")V");
+       }
+
+       // PTWIMPL ResolvedMember for localAspectOf() method, declared in matched type
+       public static ResolvedMember perTypeWithinLocalAspectOf(UnresolvedType shadowType, UnresolvedType aspectType) {
+               return new ResolvedMemberImpl(Member.METHOD, shadowType,// perTypeWithinInterfaceType(aspectType),
+                               Modifier.PUBLIC | Modifier.STATIC, NameMangler.perTypeWithinLocalAspectOf(aspectType), "()"
+                                               + aspectType.getSignature());
+       }
+
+       public static ResolvedMember perSingletonAspectOfMethod(UnresolvedType declaringType) {
+               return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, "aspectOf", "()" + declaringType.getSignature());
+       }
+
+       public static ResolvedMember perSingletonHasAspectMethod(UnresolvedType declaringType) {
+               return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, "hasAspect", "()Z");
+       }
+
+       public static ResolvedMember perCflowAspectOfMethod(UnresolvedType declaringType) {
+               return perSingletonAspectOfMethod(declaringType);
+       }
+
+       public static ResolvedMember perCflowHasAspectMethod(UnresolvedType declaringType) {
+               return perSingletonHasAspectMethod(declaringType);
+       }
+
+       public static ResolvedMember perObjectAspectOfMethod(UnresolvedType declaringType) {
+               return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, "aspectOf", "(Ljava/lang/Object;)"
+                               + declaringType.getSignature());
+       }
+
+       public static ResolvedMember perObjectHasAspectMethod(UnresolvedType declaringType) {
+               return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, "hasAspect", "(Ljava/lang/Object;)Z");
+       }
+
+       // PTWIMPL ResolvedMember for aspectOf(), declared in aspect
+       public static ResolvedMember perTypeWithinAspectOfMethod(UnresolvedType declaringType, boolean inJava5Mode) {
+               UnresolvedType parameterType = null;
+               if (inJava5Mode) {
+                       parameterType = UnresolvedType.forRawTypeName("java.lang.Class");
+               } else {
+                       parameterType = UnresolvedType.forSignature("Ljava/lang/Class;");
+               }
+               return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, declaringType, "aspectOf",
+                               new UnresolvedType[] { parameterType });
+               // return new ResolvedMemberImpl(Member.METHOD,
+               // declaringType, PUBLIC_STATIC, "aspectOf",
+               // "(Ljava/lang/Class;)" + declaringType.getSignature());
+       }
+
+       /*
+        * public static ResolvedMember perTypeWithinGetWithinTypeMethod(UnresolvedType declaringType, boolean inJava5Mode) {
+        * UnresolvedType returnType = null; if (inJava5Mode) { returnType = UnresolvedType.forRawTypeName("java.lang.Class"); } else {
+        * returnType = UnresolvedType.forSignature("Ljava/lang/Class;"); } return new
+        * ResolvedMemberImpl(Member.METHOD,declaringType,Modifier.PUBLIC,ResolvedType.JAVA_LANG_STRING,"getWithinType",new
+        * UnresolvedType[]{}); }
+        */
+
+       // PTWIMPL ResolvedMember for hasAspect(), declared in aspect
+       public static ResolvedMember perTypeWithinHasAspectMethod(UnresolvedType declaringType, boolean inJava5Mode) {
+               UnresolvedType parameterType = null;
+               if (inJava5Mode) {
+                       parameterType = UnresolvedType.forRawTypeName("java.lang.Class");
+               } else {
+                       parameterType = UnresolvedType.forSignature("Ljava/lang/Class;");
+               }
+               return new ResolvedMemberImpl(Member.METHOD, declaringType, PUBLIC_STATIC, ResolvedType.BOOLEAN, "hasAspect",
+                               new UnresolvedType[] { parameterType });
+               // return new ResolvedMemberImpl(Member.METHOD,
+               // declaringType, PUBLIC_STATIC, "hasAspect",
+               // "(Ljava/lang/Class;)Z");
+       }
+
+       // -- privileged accessors
+
+       public static ResolvedMember privilegedAccessMethodForMethod(UnresolvedType aspectType, ResolvedMember method) {
+               return new ResolvedMemberImpl(Member.METHOD, method.getDeclaringType(), Modifier.PUBLIC
+                               | (method.isStatic() ? Modifier.STATIC : 0), method.getReturnType(), NameMangler.privilegedAccessMethodForMethod(
+                               method.getName(), method.getDeclaringType(), aspectType), method.getParameterTypes(), method.getExceptions());
+       }
+
+       public static ResolvedMember privilegedAccessMethodForFieldGet(UnresolvedType aspectType, Member field) {
+               String sig;
+               if (field.isStatic()) {
+                       sig = "()" + field.getReturnType().getSignature();
+               } else {
+                       sig = "(" + field.getDeclaringType().getSignature() + ")" + field.getReturnType().getSignature();
+               }
+
+               return new ResolvedMemberImpl(Member.METHOD, field.getDeclaringType(), PUBLIC_STATIC, // Modifier.PUBLIC | (field.isStatic()
+                               // ? Modifier.STATIC : 0),
+                               NameMangler.privilegedAccessMethodForFieldGet(field.getName(), field.getDeclaringType(), aspectType), sig);
+       }
+
+       public static ResolvedMember privilegedAccessMethodForFieldSet(UnresolvedType aspectType, Member field) {
+               String sig;
+               if (field.isStatic()) {
+                       sig = "(" + field.getReturnType().getSignature() + ")V";
+               } else {
+                       sig = "(" + field.getDeclaringType().getSignature() + field.getReturnType().getSignature() + ")V";
+               }
+
+               return new ResolvedMemberImpl(Member.METHOD, field.getDeclaringType(), PUBLIC_STATIC, // Modifier.PUBLIC | (field.isStatic()
+                               // ? Modifier.STATIC : 0),
+                               NameMangler.privilegedAccessMethodForFieldSet(field.getName(), field.getDeclaringType(), aspectType), sig);
+       }
+
+       // --- inline accessors
+       // ??? can eclipse handle a transform this weird without putting synthetics into the mix
+       public static ResolvedMember superAccessMethod(UnresolvedType baseType, ResolvedMember method) {
+               return new ResolvedMemberImpl(Member.METHOD, baseType, Modifier.PUBLIC, method.getReturnType(), NameMangler
+                               .superDispatchMethod(baseType, method.getName()), method.getParameterTypes(), method.getExceptions());
+       }
+
+       public static ResolvedMember inlineAccessMethodForMethod(UnresolvedType aspectType, ResolvedMember method) {
+               UnresolvedType[] paramTypes = method.getParameterTypes();
+               if (!method.isStatic()) {
+                       paramTypes = UnresolvedType.insert(method.getDeclaringType(), paramTypes);
+               }
+               return new ResolvedMemberImpl(Member.METHOD, aspectType,
+                               PUBLIC_STATIC, // ??? what about privileged and super access
+                               // ???Modifier.PUBLIC | (method.isStatic() ? Modifier.STATIC : 0),
+                               method.getReturnType(),
+
+                               NameMangler.inlineAccessMethodForMethod(method.getName(), method.getDeclaringType(), aspectType), paramTypes,
+                               method.getExceptions());
+       }
+
+       public static ResolvedMember inlineAccessMethodForFieldGet(UnresolvedType aspectType, Member field) {
+               String sig;
+               if (field.isStatic()) {
+                       sig = "()" + field.getReturnType().getSignature();
+               } else {
+                       sig = "(" + field.getDeclaringType().getSignature() + ")" + field.getReturnType().getSignature();
+               }
+
+               return new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, // Modifier.PUBLIC | (field.isStatic() ?
+                               // Modifier.STATIC : 0),
+                               NameMangler.inlineAccessMethodForFieldGet(field.getName(), field.getDeclaringType(), aspectType), sig);
+       }
+
+       public static ResolvedMember inlineAccessMethodForFieldSet(UnresolvedType aspectType, Member field) {
+               String sig;
+               if (field.isStatic()) {
+                       sig = "(" + field.getReturnType().getSignature() + ")V";
+               } else {
+                       sig = "(" + field.getDeclaringType().getSignature() + field.getReturnType().getSignature() + ")V";
+               }
+
+               return new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, // Modifier.PUBLIC | (field.isStatic() ?
+                               // Modifier.STATIC : 0),
+                               NameMangler.inlineAccessMethodForFieldSet(field.getName(), field.getDeclaringType(), aspectType), sig);
+       }
+
+       // --- runtimeLibrary api stuff
+
+       public static Member cflowStackPeekInstance() {
+               return new MemberImpl(Member.METHOD, CFLOW_STACK_TYPE, 0, "peekInstance", "()Ljava/lang/Object;");
+       }
+
+       public static Member cflowStackPushInstance() {
+               return new MemberImpl(Member.METHOD, CFLOW_STACK_TYPE, 0, "pushInstance", "(Ljava/lang/Object;)V");
+       }
+
+       public static Member cflowStackIsValid() {
+               return new MemberImpl(Member.METHOD, CFLOW_STACK_TYPE, 0, "isValid", "()Z");
+       }
+
+       public static Member cflowStackInit() {
+               return new MemberImpl(Member.CONSTRUCTOR, CFLOW_STACK_TYPE, 0, "<init>", "()V");
+       }
+
+       public static Member aroundClosurePreInitializationField() {
+               return new MemberImpl(Member.FIELD, AROUND_CLOSURE_TYPE, 0, "preInitializationState", "[Ljava/lang/Object;");
+       }
+
+       public static Member aroundClosurePreInitializationGetter() {
+               return new MemberImpl(Member.METHOD, AROUND_CLOSURE_TYPE, 0, "getPreInitializationState", "()[Ljava/lang/Object;");
+       }
+
+       public static ResolvedMember preIntroducedConstructor(UnresolvedType aspectType, UnresolvedType targetType,
+                       UnresolvedType[] paramTypes) {
+               return new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC_FINAL, UnresolvedType.OBJECTARRAY, NameMangler
+                               .preIntroducedConstructor(aspectType, targetType), paramTypes);
+       }
+
+       public static ResolvedMember postIntroducedConstructor(UnresolvedType aspectType, UnresolvedType targetType,
+                       UnresolvedType[] paramTypes) {
+               return new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC_FINAL, ResolvedType.VOID, NameMangler
+                               .postIntroducedConstructor(aspectType, targetType), UnresolvedType.insert(targetType, paramTypes));
+       }
+
+       public static ResolvedMember itdAtDeclareParentsField(ResolvedType targetType, UnresolvedType itdType, UnresolvedType aspectType) {
+               return new ResolvedMemberImpl(Member.FIELD, targetType, Modifier.PRIVATE, itdType, NameMangler.itdAtDeclareParentsField(
+                               aspectType, itdType), null);
+       }
+
+       public static ResolvedMember interConstructor(ResolvedType targetType, ResolvedMember constructor, UnresolvedType aspectType) {
+               //              
+               // ResolvedType targetType,
+               // UnresolvedType[] argTypes,
+               // int modifiers)
+               // {
+               ResolvedMember ret = new ResolvedMemberImpl(Member.CONSTRUCTOR, targetType, Modifier.PUBLIC, ResolvedType.VOID, "<init>",
+                               constructor.getParameterTypes(), constructor.getExceptions());
+               // System.out.println("ret: " + ret + " mods: " + Modifier.toString(modifiers));
+               if (Modifier.isPublic(constructor.getModifiers()))
+                       return ret;
+               while (true) {
+                       ret = addCookieTo(ret, aspectType);
+                       if (targetType.lookupMemberNoSupers(ret) == null)
+                               return ret;
+               }
+       }
+
+       public static ResolvedMember interFieldInitializer(ResolvedMember field, UnresolvedType aspectType) {
+               return new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, NameMangler.interFieldInitializer(aspectType, field
+                               .getDeclaringType(), field.getName()), field.isStatic() ? "()V" : "(" + field.getDeclaringType().getSignature()
+                               + ")V");
+       }
+
+       /**
+        * Makes public and non-final
+        */
+       private static int makePublicNonFinal(int modifiers) {
+               return (modifiers & ~VISIBILITY & ~Modifier.FINAL) | Modifier.PUBLIC;
+       }
+
+       /**
+        * This static method goes on the aspect that declares the inter-type field
+        */
+       public static ResolvedMember interFieldSetDispatcher(ResolvedMember field, UnresolvedType aspectType) {
+               ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, ResolvedType.VOID, NameMangler
+                               .interFieldSetDispatcher(aspectType, field.getDeclaringType(), field.getName()),
+                               field.isStatic() ? new UnresolvedType[] { field.getReturnType() } : new UnresolvedType[] {
+                                               field.getDeclaringType(), field.getReturnType() });
+               rm.setTypeVariables(field.getTypeVariables());
+               return rm;
+       }
+
+       /**
+        * This static method goes on the aspect that declares the inter-type field
+        */
+       public static ResolvedMember interFieldGetDispatcher(ResolvedMember field, UnresolvedType aspectType) {
+               ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, field.getReturnType(), NameMangler
+                               .interFieldGetDispatcher(aspectType, field.getDeclaringType(), field.getName()),
+                               field.isStatic() ? UnresolvedType.NONE : new UnresolvedType[] { field.getDeclaringType() }, UnresolvedType.NONE);
+               rm.setTypeVariables(field.getTypeVariables());
+               return rm;
+       }
+
+       // private static int makeFieldModifiers(int declaredModifiers) {
+       // int ret = Modifier.PUBLIC;
+       // if (Modifier.isTransient(declaredModifiers)) ret |= Modifier.TRANSIENT;
+       // if (Modifier.isVolatile(declaredModifiers)) ret |= Modifier.VOLATILE;
+       // return ret;
+       // }
+
+       /**
+        * This field goes on the class the field is declared onto
+        */
+       public static ResolvedMember interFieldClassField(ResolvedMember field, UnresolvedType aspectType) {
+               return new ResolvedMemberImpl(Member.FIELD, field.getDeclaringType(), makePublicNonFinal(field.getModifiers()), field
+                               .getReturnType(), NameMangler.interFieldClassField(field.getModifiers(), aspectType, field.getDeclaringType(),
+                               field.getName()), UnresolvedType.NONE, UnresolvedType.NONE);
+       }
+
+       /**
+        * This field goes on top-most implementers of the interface the field is declared onto
+        */
+       public static ResolvedMember interFieldInterfaceField(ResolvedMember field, UnresolvedType onClass, UnresolvedType aspectType) {
+               return new ResolvedMemberImpl(Member.FIELD, onClass, makePublicNonFinal(field.getModifiers()), field.getReturnType(),
+                               NameMangler.interFieldInterfaceField(aspectType, field.getDeclaringType(), field.getName()), UnresolvedType.NONE,
+                               UnresolvedType.NONE);
+       }
+
+       /**
+        * This instance method goes on the interface the field is declared onto as well as its top-most implementors
+        */
+       public static ResolvedMember interFieldInterfaceSetter(ResolvedMember field, ResolvedType onType, UnresolvedType aspectType) {
+               int modifiers = Modifier.PUBLIC;
+               if (onType.isInterface())
+                       modifiers |= Modifier.ABSTRACT;
+               ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, onType, modifiers, ResolvedType.VOID, NameMangler
+                               .interFieldInterfaceSetter(aspectType, field.getDeclaringType(), field.getName()), new UnresolvedType[] { field
+                               .getReturnType() }, UnresolvedType.NONE);
+               rm.setTypeVariables(field.getTypeVariables());
+               return rm;
+       }
+
+       /**
+        * This instance method goes on the interface the field is declared onto as well as its top-most implementors
+        */
+       public static ResolvedMember interFieldInterfaceGetter(ResolvedMember field, ResolvedType onType, UnresolvedType aspectType) {
+               int modifiers = Modifier.PUBLIC;
+               if (onType.isInterface())
+                       modifiers |= Modifier.ABSTRACT;
+               ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, onType, modifiers, field.getReturnType(), NameMangler
+                               .interFieldInterfaceGetter(aspectType, field.getDeclaringType(), field.getName()), UnresolvedType.NONE,
+                               UnresolvedType.NONE);
+               rm.setTypeVariables(field.getTypeVariables());
+               return rm;
+       }
+
+       /**
+        * This method goes on the target type of the inter-type method. (and possibly the topmost-implementors, if the target type is
+        * an interface). The implementation will call the interMethodDispatch method on the aspect.
+        */
+       public static ResolvedMember interMethod(ResolvedMember meth, UnresolvedType aspectType, boolean onInterface) {
+               if (Modifier.isPublic(meth.getModifiers()) && !onInterface)
+                       return meth;
+
+               int modifiers = makePublicNonFinal(meth.getModifiers());
+               if (onInterface)
+                       modifiers |= Modifier.ABSTRACT;
+
+               ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, meth.getDeclaringType(), modifiers, meth.getReturnType(),
+                               NameMangler.interMethod(meth.getModifiers(), aspectType, meth.getDeclaringType(), meth.getName()), meth
+                                               .getParameterTypes(), meth.getExceptions());
+               rmi.setTypeVariables(meth.getTypeVariables());
+               return rmi;
+       }
+
+       /**
+        * This method goes on the target type of the inter-type method. (and possibly the topmost-implementors, if the target type is
+        * an interface). The implementation will call the interMethodDispatch method on the aspect.
+        */
+       public static ResolvedMember interMethodBridger(ResolvedMember meth, UnresolvedType aspectType, boolean onInterface) {
+               // if (Modifier.isPublic(meth.getModifiers()) && !onInterface)
+               // return meth;
+
+               int modifiers = makePublicNonFinal(meth.getModifiers()) | BRIDGE;
+               if (onInterface)
+                       modifiers |= Modifier.ABSTRACT;
+
+               ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, meth.getDeclaringType(), modifiers, meth.getReturnType(),
+                               NameMangler.interMethod(meth.getModifiers(), aspectType, meth.getDeclaringType(), meth.getName()), meth
+                                               .getParameterTypes(), meth.getExceptions());
+               rmi.setTypeVariables(meth.getTypeVariables());
+               return rmi;
+       }
+
+       /**
+        * Sometimes the intertyped method requires a bridge method alongside it. For example if the method 'N SomeI<N>.m()' is put onto
+        * an interface 'interface I<N extends Number>' and then a concrete implementation is 'class C implements I<Float>' then the ITD
+        * on the interface will be 'Number m()', whereas the ITD on the 'topmostimplementor' will be 'Float m()'. A bridge method needs
+        * to be created in the topmostimplementor 'Number m()' that delegates to 'Float m()'
+        */
+       public static ResolvedMember bridgerToInterMethod(ResolvedMember meth, UnresolvedType aspectType) {
+
+               int modifiers = makePublicNonFinal(meth.getModifiers());
+
+               ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, aspectType, modifiers, meth.getReturnType(), NameMangler
+                               .interMethod(meth.getModifiers(), aspectType, meth.getDeclaringType(), meth.getName()), meth.getParameterTypes(),
+                               meth.getExceptions());
+               rmi.setTypeVariables(meth.getTypeVariables());
+               return rmi;
+       }
+
+       /**
+        * This static method goes on the declaring aspect of the inter-type method. The implementation calls the interMethodBody()
+        * method on the aspect.
+        */
+       public static ResolvedMember interMethodDispatcher(ResolvedMember meth, UnresolvedType aspectType) {
+               UnresolvedType[] paramTypes = meth.getParameterTypes();
+               if (!meth.isStatic()) {
+                       paramTypes = UnresolvedType.insert(meth.getDeclaringType(), paramTypes);
+               }
+
+               ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, meth.getReturnType(), NameMangler
+                               .interMethodDispatcher(aspectType, meth.getDeclaringType(), meth.getName()), paramTypes, meth.getExceptions());
+
+               rmi.setTypeVariables(meth.getTypeVariables());
+
+               return rmi;
+       }
+
+       /**
+        * This method goes on the declaring aspect of the inter-type method. It contains the real body of the ITD method.
+        */
+       public static ResolvedMember interMethodBody(ResolvedMember meth, UnresolvedType aspectType) {
+               UnresolvedType[] paramTypes = meth.getParameterTypes();
+               if (!meth.isStatic()) {
+                       paramTypes = UnresolvedType.insert(meth.getDeclaringType(), paramTypes);
+               }
+
+               int modifiers = PUBLIC_STATIC;
+               if (Modifier.isStrict(meth.getModifiers())) {
+                       modifiers |= Modifier.STRICT;
+               }
+
+               ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, aspectType, modifiers, meth.getReturnType(), NameMangler
+                               .interMethodBody(aspectType, meth.getDeclaringType(), meth.getName()), paramTypes, meth.getExceptions());
+               rmi.setTypeVariables(meth.getTypeVariables());
+               return rmi;
+       }
+
+       private static ResolvedMember addCookieTo(ResolvedMember ret, UnresolvedType aspectType) {
+               UnresolvedType[] params = ret.getParameterTypes();
+
+               UnresolvedType[] freshParams = UnresolvedType.add(params, aspectType);
+               return new ResolvedMemberImpl(ret.getKind(), ret.getDeclaringType(), ret.getModifiers(), ret.getReturnType(),
+                               ret.getName(), freshParams, ret.getExceptions());
+       }
+
+       public static ResolvedMember toObjectConversionMethod(UnresolvedType fromType) {
+               if (fromType.isPrimitiveType()) {
+                       String name = fromType.toString() + "Object";
+                       return new ResolvedMemberImpl(Member.METHOD, CONVERSIONS_TYPE, PUBLIC_STATIC, UnresolvedType.OBJECT, name,
+                                       new UnresolvedType[] { fromType }, UnresolvedType.NONE);
+               } else {
+                       return null;
+               }
+       }
+
+       public static Member interfaceConstructor(ResolvedType resolvedTypeX) {
+               // AMC next two lines should not be needed when sig for generic type is changed
+               ResolvedType declaringType = resolvedTypeX;
+               if (declaringType.isRawType())
+                       declaringType = declaringType.getGenericType();
+               return new ResolvedMemberImpl(Member.CONSTRUCTOR, declaringType, Modifier.PUBLIC, "<init>", "()V");
+       }
+
+       // -- common types we use. Note: Java 5 dependand types are refered to as String
+       public final static UnresolvedType ASPECT_ANNOTATION = UnresolvedType.forSignature("Lorg/aspectj/lang/annotation/Aspect;");
+
+       public final static UnresolvedType BEFORE_ANNOTATION = UnresolvedType.forSignature("Lorg/aspectj/lang/annotation/Before;");
+
+       public final static UnresolvedType AROUND_ANNOTATION = UnresolvedType.forSignature("Lorg/aspectj/lang/annotation/Around;");
+
+       public final static UnresolvedType AFTERRETURNING_ANNOTATION = UnresolvedType
+                       .forSignature("Lorg/aspectj/lang/annotation/AfterReturning;");
+
+       public final static UnresolvedType AFTERTHROWING_ANNOTATION = UnresolvedType
+                       .forSignature("Lorg/aspectj/lang/annotation/AfterThrowing;");
+
+       public final static UnresolvedType AFTER_ANNOTATION = UnresolvedType.forSignature("Lorg/aspectj/lang/annotation/After;");
+
+       public final static UnresolvedType POINTCUT_ANNOTATION = UnresolvedType.forSignature("Lorg/aspectj/lang/annotation/Pointcut;");
+
+       public final static UnresolvedType DECLAREERROR_ANNOTATION = UnresolvedType
+                       .forSignature("Lorg/aspectj/lang/annotation/DeclareError;");
+
+       public final static UnresolvedType DECLAREWARNING_ANNOTATION = UnresolvedType
+                       .forSignature("Lorg/aspectj/lang/annotation/DeclareWarning;");
+
+       public final static UnresolvedType DECLAREPRECEDENCE_ANNOTATION = UnresolvedType
+                       .forSignature("Lorg/aspectj/lang/annotation/DeclarePrecedence;");
+
+       // public final static UnresolvedType DECLAREIMPLEMENTS_ANNOTATION =
+       // UnresolvedType.forSignature("Lorg/aspectj/lang/annotation/DeclareImplements;");
+
+       public final static UnresolvedType DECLAREPARENTS_ANNOTATION = UnresolvedType
+                       .forSignature("Lorg/aspectj/lang/annotation/DeclareParents;");
+
+       public final static UnresolvedType TYPEX_JOINPOINT = UnresolvedType.forSignature("Lorg/aspectj/lang/JoinPoint;");
+
+       public final static UnresolvedType TYPEX_PROCEEDINGJOINPOINT = UnresolvedType
+                       .forSignature("Lorg/aspectj/lang/ProceedingJoinPoint;");
+
+       public final static UnresolvedType TYPEX_STATICJOINPOINT = UnresolvedType
+                       .forSignature("Lorg/aspectj/lang/JoinPoint$StaticPart;");
+
+       public final static UnresolvedType TYPEX_ENCLOSINGSTATICJOINPOINT = UnresolvedType
+                       .forSignature("Lorg/aspectj/lang/JoinPoint$EnclosingStaticPart;");
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AnnotatedElement.java b/org.aspectj.matcher/src/org/aspectj/weaver/AnnotatedElement.java
new file mode 100644 (file)
index 0000000..86297b8
--- /dev/null
@@ -0,0 +1,21 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+/**
+ * Represents any element that may have annotations
+ */
+public interface AnnotatedElement {
+       boolean hasAnnotation(UnresolvedType ofType);
+
+       ResolvedType[] getAnnotationTypes();
+
+       AnnotationAJ getAnnotationOfType(UnresolvedType ofType);
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AnnotationAJ.java b/org.aspectj.matcher/src/org/aspectj/weaver/AnnotationAJ.java
new file mode 100644 (file)
index 0000000..c7605c1
--- /dev/null
@@ -0,0 +1,102 @@
+/* *******************************************************************
+ * Copyright (c) 2006-2008 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.util.Set;
+
+/**
+ * Simple representation of an annotation that the weaver can work with.
+ * 
+ * @author AndyClement
+ */
+public interface AnnotationAJ {
+
+       public static final AnnotationAJ[] EMPTY_ARRAY = new AnnotationAJ[0];
+
+       /**
+        * @return the signature for the annotation type, eg. Lcom/foo/MyAnno;
+        */
+       public String getTypeSignature();
+
+       /**
+        * @return the type name for the annotation, eg. com.foo.MyAnno
+        */
+       public String getTypeName();
+
+       /**
+        * @return the type of the annotation
+        */
+       public ResolvedType getType();
+
+       /**
+        * return true if this annotation can target an annotation type
+        */
+       public boolean allowedOnAnnotationType();
+
+       /**
+        * @return true if this annotation can be put on a field
+        */
+       public boolean allowedOnField();
+
+       /**
+        * @return true if this annotation can target a 'regular' type. A 'regular' type is enum/class/interface - it is *not*
+        *         annotation.
+        */
+       public boolean allowedOnRegularType();
+
+       /**
+        * @return for the @target annotation, this will return a set of the element-types it can be applied to. For other annotations ,
+        *         it returns the empty set.
+        */
+       public Set getTargets();
+
+       /**
+        * @param name the name of the value
+        * @return true if there is a value with that name
+        */
+       public boolean hasNamedValue(String name);
+
+       /**
+        * @param name the name of the annotation field
+        * @param value the value of the annotation field
+        * @return true if there is a value with the specified name and value
+        */
+       public boolean hasNameValuePair(String name, String value);
+
+       /**
+        * @return String representation of the valid targets for this annotation, eg. "{TYPE,FIELD}"
+        */
+       public String getValidTargets();
+
+       /**
+        * @return String form of the annotation and any values, eg. @Foo(a=b,c=d)
+        */
+       public String stringify();
+
+       /**
+        * @return true if this annotation is marked with @target
+        */
+       public boolean specifiesTarget();
+
+       /**
+        * @return true if the annotation is marked for runtime visibility
+        */
+       public boolean isRuntimeVisible();
+
+       /**
+        * Determine the string representation of the value of a field.  For example in @SuppressAjWarnings({"adviceDidNotMatch"})
+        * the return value for getStringFormOfValue("value") would be "[adviceDidNotMatch]".
+        * 
+        * @param name the name of the annotation field being looked up
+        * @return string representation of the value of that field, may be null if no such field set
+        */
+       public String getStringFormOfValue(String name);
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AnnotationAnnotationValue.java b/org.aspectj.matcher/src/org/aspectj/weaver/AnnotationAnnotationValue.java
new file mode 100644 (file)
index 0000000..8002371
--- /dev/null
@@ -0,0 +1,35 @@
+/* *******************************************************************
+ * Copyright (c) 2006 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement IBM     initial implementation 
+ * ******************************************************************/
+ package org.aspectj.weaver;
+
+public class AnnotationAnnotationValue extends AnnotationValue {
+
+       private AnnotationAJ value;
+       
+       public AnnotationAnnotationValue(AnnotationAJ value) {
+               super(AnnotationValue.ANNOTATION);
+               this.value = value;
+       }
+       
+       public AnnotationAJ getAnnotation() {
+               return value;
+       }
+       
+       public String stringify() {
+               return value.stringify();
+       }
+       
+       public String toString() {
+               return value.toString();
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AnnotationNameValuePair.java b/org.aspectj.matcher/src/org/aspectj/weaver/AnnotationNameValuePair.java
new file mode 100644 (file)
index 0000000..3ab561b
--- /dev/null
@@ -0,0 +1,47 @@
+/* *******************************************************************
+ * Copyright (c) 2006 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement IBM     initial implementation 
+ * ******************************************************************/
+ package org.aspectj.weaver;
+
+public class AnnotationNameValuePair {
+       
+       private String name;
+       
+       private AnnotationValue val;
+
+        public AnnotationNameValuePair(String name,AnnotationValue val) {
+                this.name = name;
+                this.val = val;
+        }
+        
+        public String getName() {
+                return name;
+        }
+        
+        public AnnotationValue getValue() {
+                return val;
+        }
+        
+        public String toString() {
+               StringBuffer sb = new StringBuffer();
+               sb.append(name+"="+val.toString());
+               return sb.toString();
+       }
+
+       public String stringify() {
+               StringBuffer sb = new StringBuffer();
+               if (!name.equals("value")) {
+                       sb.append(name+"=");
+               }
+               sb.append(val.stringify());
+               return sb.toString();
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AnnotationOnTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/AnnotationOnTypeMunger.java
new file mode 100644 (file)
index 0000000..6286d33
--- /dev/null
@@ -0,0 +1,57 @@
+/* *******************************************************************
+ * Copyright (c) 2005 IBM
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * Represents adding an annotation to a type
+ */
+public class AnnotationOnTypeMunger extends ResolvedTypeMunger {
+       AnnotationAJ newAnnotation;
+
+       public AnnotationOnTypeMunger(AnnotationAJ anno) {
+               super(AnnotationOnType, null);
+               newAnnotation = anno;
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               throw new RuntimeException("unimplemented");
+       }
+
+       public AnnotationAJ getNewAnnotation() {
+               return newAnnotation;
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof AnnotationOnTypeMunger))
+                       return false;
+               AnnotationOnTypeMunger o = (AnnotationOnTypeMunger) other;
+               // TODO does not check equality of annotation values
+               return newAnnotation.getTypeSignature().equals(
+                               o.newAnnotation.getTypeSignature());
+       }
+
+       private volatile int hashCode = 0;
+
+       public int hashCode() {
+               if (hashCode == 0) {
+                       int result = 17;
+                       result = 37 * result + newAnnotation.getTypeSignature().hashCode();
+                       hashCode = result;
+               }
+               return hashCode;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AnnotationTargetKind.java b/org.aspectj.matcher/src/org/aspectj/weaver/AnnotationTargetKind.java
new file mode 100644 (file)
index 0000000..e037041
--- /dev/null
@@ -0,0 +1,51 @@
+/********************************************************************
+ * Copyright (c) 2005 Contributors. All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *       Helen Hawkins - Initial implementation
+ *******************************************************************/
+package org.aspectj.weaver;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import org.aspectj.util.TypeSafeEnum;
+
+/**
+ * A TypeSafeEnum similar to the Java5 ElementType Enum
+ */
+public class AnnotationTargetKind extends TypeSafeEnum {
+
+       public AnnotationTargetKind(String name, int key) {
+               super(name, key);
+       }
+       
+    public static AnnotationTargetKind read(DataInputStream s) throws IOException {
+        int key = s.readByte();
+        switch(key) {
+            case 1: return ANNOTATION_TYPE;
+            case 2: return CONSTRUCTOR;
+            case 3: return FIELD;
+            case 4: return LOCAL_VARIABLE;
+            case 5: return METHOD;
+            case 6: return PACKAGE;
+            case 7: return PARAMETER;
+            case 8: return TYPE;
+        }
+        throw new BCException("weird annotation target kind " + key);
+    }
+
+       public static final AnnotationTargetKind ANNOTATION_TYPE = new AnnotationTargetKind("ANNOTATION_TYPE", 1);
+       public static final AnnotationTargetKind CONSTRUCTOR = new AnnotationTargetKind("CONSTRUCTOR", 2);
+       public static final AnnotationTargetKind FIELD = new AnnotationTargetKind("FIELD", 3);
+       public static final AnnotationTargetKind LOCAL_VARIABLE = new AnnotationTargetKind("LOCAL_VARIABLE", 4);
+       public static final AnnotationTargetKind METHOD = new AnnotationTargetKind("METHOD", 5);
+       public static final AnnotationTargetKind PACKAGE = new AnnotationTargetKind("PACKAGE", 6);
+       public static final AnnotationTargetKind PARAMETER = new AnnotationTargetKind("PARAMETER", 7);
+       public static final AnnotationTargetKind TYPE = new AnnotationTargetKind("TYPE", 8);
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AnnotationValue.java b/org.aspectj.matcher/src/org/aspectj/weaver/AnnotationValue.java
new file mode 100644 (file)
index 0000000..9c7a4b9
--- /dev/null
@@ -0,0 +1,72 @@
+/* *******************************************************************
+ * Copyright (c) 2006 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement IBM     initial implementation 
+ * ******************************************************************/
+ package org.aspectj.weaver;
+
+
+public abstract class AnnotationValue {
+       
+       protected int valueKind;
+
+       public static final int STRING = 's';
+       public static final int ENUM_CONSTANT = 'e';
+       public static final int CLASS = 'c';
+       public static final int ANNOTATION = '@';
+       public static final int ARRAY = '[';
+    
+       public static final int PRIMITIVE_INT    = 'I';
+       public static final int PRIMITIVE_BYTE   = 'B';
+       public static final int PRIMITIVE_CHAR   = 'C';
+       public static final int PRIMITIVE_DOUBLE = 'D';
+       public static final int PRIMITIVE_FLOAT  = 'F';
+       public static final int PRIMITIVE_LONG   = 'J';
+       public static final int PRIMITIVE_SHORT  = 'S';
+       public static final int PRIMITIVE_BOOLEAN= 'Z';
+
+       public abstract String stringify();
+       
+       public AnnotationValue(int kind) {
+               valueKind = kind;
+       }
+       
+       public static String whatKindIsThis(int kind) {
+               switch (kind) {
+                 case PRIMITIVE_BYTE: // byte
+                         return "byte";
+                 case PRIMITIVE_CHAR: // char
+                         return "char";
+                 case PRIMITIVE_DOUBLE: // double
+                         return "double";
+                 case PRIMITIVE_FLOAT: // float
+                       return "float";
+                 case PRIMITIVE_INT: // int
+                         return "int";
+                 case PRIMITIVE_LONG: // long
+                         return "long";
+                 case PRIMITIVE_SHORT: // short
+                         return "short";
+                 case PRIMITIVE_BOOLEAN: // boolean
+                         return "boolean";
+                 case 's': // String
+                         return "string";
+                 case 'e': // Enum constant
+                         return "enum";
+                 case 'c': // Class
+                         return "class";
+                 case '@': // Annotation
+                         return "annotation";
+                 case '[': // Array
+                         return "array";
+                 default: 
+                       throw new RuntimeException("Dont know what this is : "+kind);
+               }
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ArrayAnnotationValue.java b/org.aspectj.matcher/src/org/aspectj/weaver/ArrayAnnotationValue.java
new file mode 100644 (file)
index 0000000..8b63eaa
--- /dev/null
@@ -0,0 +1,57 @@
+/* *******************************************************************
+ * Copyright (c) 2006 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement IBM     initial implementation 
+ * ******************************************************************/
+ package org.aspectj.weaver;
+
+public class ArrayAnnotationValue extends AnnotationValue {
+
+       private AnnotationValue[] values;
+       
+       public ArrayAnnotationValue() {
+               super(AnnotationValue.ARRAY);
+       }
+       
+       public void setValues(AnnotationValue[] values) {
+               this.values = values;
+       }
+       
+       public ArrayAnnotationValue(AnnotationValue[] values) {
+               super(AnnotationValue.ARRAY);
+               this.values = values;
+       }
+       
+       public AnnotationValue[] getValues() {
+               return values;
+       }
+       
+       public String stringify() {
+               StringBuffer sb = new StringBuffer();
+               sb.append("[");
+               for (int i = 0; i < values.length; i++) {
+                       sb.append(values[i].stringify());
+                       if (i+1<values.length) sb.append(",");
+               }
+               sb.append("]");
+               return sb.toString();
+       }
+       
+       public String toString() {
+               StringBuffer sb = new StringBuffer();
+               sb.append("{");
+               for (int i = 0; i < values.length; i++) {
+                       sb.append(values[i].toString());
+                       if ((i+1)<values.length) sb.append(",");
+               }
+               sb.append("}");
+               return sb.toString();
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ArrayReferenceType.java b/org.aspectj.matcher/src/org/aspectj/weaver/ArrayReferenceType.java
new file mode 100644 (file)
index 0000000..21af1b8
--- /dev/null
@@ -0,0 +1,196 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement     initial implementation 
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * Represents a resolved array type
+ * 
+ * @author Andy Clement
+ */
+public class ArrayReferenceType extends ReferenceType {
+
+       private final ResolvedType componentType;
+
+       public ArrayReferenceType(String sig, String erasureSig, World world, ResolvedType componentType) {
+               super(sig, erasureSig, world);
+               this.componentType = componentType;
+       }
+
+       // These methods are from the original implementation when Array was a ResolvedType and not a ReferenceType
+
+       public final ResolvedMember[] getDeclaredFields() {
+               return ResolvedMember.NONE;
+       }
+
+       public final ResolvedMember[] getDeclaredMethods() {
+               // ??? should this return clone? Probably not...
+               // If it ever does, here is the code:
+               // ResolvedMember cloneMethod =
+               // new ResolvedMember(Member.METHOD,this,Modifier.PUBLIC,UnresolvedType.OBJECT,"clone",new UnresolvedType[]{});
+               // return new ResolvedMember[]{cloneMethod};
+               return ResolvedMember.NONE;
+       }
+
+       public final ResolvedType[] getDeclaredInterfaces() {
+               return new ResolvedType[] { world.getCoreType(CLONEABLE), world.getCoreType(SERIALIZABLE) };
+       }
+
+       public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
+               return null;
+       }
+
+       public AnnotationAJ[] getAnnotations() {
+               return AnnotationAJ.EMPTY_ARRAY;
+       }
+
+       public ResolvedType[] getAnnotationTypes() {
+               return ResolvedType.NONE;
+       }
+
+       public final ResolvedMember[] getDeclaredPointcuts() {
+               return ResolvedMember.NONE;
+       }
+
+       public boolean hasAnnotation(UnresolvedType ofType) {
+               return false;
+       }
+
+       public final ResolvedType getSuperclass() {
+               return world.getCoreType(OBJECT);
+       }
+
+       public final boolean isAssignableFrom(ResolvedType o) {
+               if (!o.isArray())
+                       return false;
+               if (o.getComponentType().isPrimitiveType()) {
+                       return o.equals(this);
+               } else {
+                       return getComponentType().resolve(world).isAssignableFrom(o.getComponentType().resolve(world));
+               }
+       }
+
+       public boolean isAssignableFrom(ResolvedType o, boolean allowMissing) {
+               return isAssignableFrom(o);
+       }
+
+       public final boolean isCoerceableFrom(ResolvedType o) {
+               if (o.equals(UnresolvedType.OBJECT) || o.equals(UnresolvedType.SERIALIZABLE) || o.equals(UnresolvedType.CLONEABLE)) {
+                       return true;
+               }
+               if (!o.isArray())
+                       return false;
+               if (o.getComponentType().isPrimitiveType()) {
+                       return o.equals(this);
+               } else {
+                       return getComponentType().resolve(world).isCoerceableFrom(o.getComponentType().resolve(world));
+               }
+       }
+
+       public final int getModifiers() {
+               int mask = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
+               return (componentType.getModifiers() & mask) | Modifier.FINAL;
+       }
+
+       public UnresolvedType getComponentType() {
+               return componentType;
+       }
+
+       public ResolvedType getResolvedComponentType() {
+               return componentType;
+       }
+
+       public ISourceContext getSourceContext() {
+               return getResolvedComponentType().getSourceContext();
+       }
+
+       // Methods overridden from ReferenceType follow
+
+       public TypeVariable[] getTypeVariables() {
+               if (this.typeVariables == null && componentType.getTypeVariables() != null) {
+                       this.typeVariables = componentType.getTypeVariables();
+                       for (int i = 0; i < this.typeVariables.length; i++) {
+                               this.typeVariables[i].resolve(world);
+                       }
+               }
+               return this.typeVariables;
+       }
+
+       public boolean isAnnotation() {
+               return false;
+       }
+
+       public boolean isAnonymous() {
+               return false;
+       }
+
+       public boolean isAnnotationStyleAspect() {
+               return false;
+       }
+
+       public boolean isAspect() {
+               return false;
+       }
+
+       public boolean isPrimitiveType() {
+               return typeKind == TypeKind.PRIMITIVE;
+       }
+
+       public boolean isSimpleType() {
+               return typeKind == TypeKind.SIMPLE;
+       }
+
+       public boolean isRawType() {
+               return typeKind == TypeKind.RAW;
+       }
+
+       public boolean isGenericType() {
+               return typeKind == TypeKind.GENERIC;
+       }
+
+       public boolean isParameterizedType() {
+               return typeKind == TypeKind.PARAMETERIZED;
+       }
+
+       public boolean isTypeVariableReference() {
+               return typeKind == TypeKind.TYPE_VARIABLE;
+       }
+
+       public boolean isGenericWildcard() {
+               return typeKind == TypeKind.WILDCARD;
+       }
+
+       public boolean isEnum() {
+               return false;
+       }
+
+       public boolean isNested() {
+               return false;
+       }
+
+       public boolean isClass() {
+               return false;
+       }
+
+       public boolean canAnnotationTargetType() {
+               return false;
+       }
+
+       public AnnotationTargetKind[] getAnnotationTargetKinds() {
+               return null;
+       }
+
+       public boolean isAnnotationWithRuntimeRetention() {
+               return false;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/BCException.java b/org.aspectj.matcher/src/org/aspectj/weaver/BCException.java
new file mode 100644 (file)
index 0000000..3685184
--- /dev/null
@@ -0,0 +1,58 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+import org.aspectj.bridge.context.CompilationAndWeavingContext;
+
+/**
+ * Exception to use inside the bcweaver.
+ */
+public class BCException extends RuntimeException {
+    Throwable thrown;
+    public BCException() {
+        super();
+    }
+
+    public BCException(String s) {
+        super(s + "\n" + CompilationAndWeavingContext.getCurrentContext());
+    }
+    public BCException(String s, Throwable thrown) {
+        this(s);
+        this.thrown = thrown;
+    }
+    public void printStackTrace() {
+        printStackTrace(System.err);
+    }
+    public void printStackTrace(PrintStream s) {
+        printStackTrace(new PrintWriter(s));
+    }
+    public void printStackTrace(PrintWriter s) {
+        super.printStackTrace(s);
+        if (null != thrown) {
+            s.print("Caused by: ");
+            s.print(thrown.getClass().getName());
+            String message = thrown.getMessage();
+            if (null != message) {
+                s.print(": ");
+                s.print(message);
+            }
+            s.println();
+            thrown.printStackTrace(s);
+        }
+    }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/BindingScope.java b/org.aspectj.matcher/src/org/aspectj/weaver/BindingScope.java
new file mode 100644 (file)
index 0000000..b49122e
--- /dev/null
@@ -0,0 +1,58 @@
+/* *******************************************************************
+ * Copyright (c) 2006-2008 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+ package org.aspectj.weaver;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.weaver.patterns.FormalBinding;
+import org.aspectj.weaver.patterns.SimpleScope;
+
+/**
+ * BindingScope that knows the enclosingType, which is needed for pointcut reference resolution
+ * 
+ * @author Alexandre Vasseur
+ */
+public class BindingScope extends SimpleScope {
+       private final ResolvedType m_enclosingType;
+       private final ISourceContext m_sourceContext;
+
+       public BindingScope(ResolvedType type, ISourceContext sourceContext, FormalBinding[] bindings) {
+               super(type.getWorld(), bindings);
+               m_enclosingType = type;
+               m_sourceContext = sourceContext;
+       }
+
+       public ResolvedType getEnclosingType() {
+               return m_enclosingType;
+       }
+
+       public ISourceLocation makeSourceLocation(IHasPosition location) {
+               return m_sourceContext.makeSourceLocation(location);
+       }
+
+       public UnresolvedType lookupType(String name, IHasPosition location) {
+               // bug 126560
+               if (m_enclosingType != null) {
+                       // add the package we're in to the list of imported
+                       // prefixes so that we can find types in the same package
+                       String pkgName = m_enclosingType.getPackageName();
+                       if (pkgName != null && !pkgName.equals("")) {
+                               String[] currentImports = getImportedPrefixes();
+                               String[] newImports = new String[currentImports.length + 1];
+                               for (int i = 0; i < currentImports.length; i++) {
+                                       newImports[i] = currentImports[i];
+                               }
+                               newImports[currentImports.length] = pkgName.concat(".");
+                               setImportedPrefixes(newImports);
+                       }
+               }
+               return super.lookupType(name, location);
+       }
+
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/BoundedReferenceType.java b/org.aspectj.matcher/src/org/aspectj/weaver/BoundedReferenceType.java
new file mode 100644 (file)
index 0000000..1839d2c
--- /dev/null
@@ -0,0 +1,334 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import org.aspectj.weaver.patterns.PerClause;
+
+/**
+ * A BoundedReferenceType is the result of a generics wildcard expression ?
+ * extends String, ? super Foo etc..
+ * 
+ * The "signature" for a bounded reference type follows the generic signature
+ * specification in section 4.4 of JVM spec: *,+,- plus signature strings.
+ * 
+ * The bound may be a type variable (e.g. ? super T)
+ */
+public class BoundedReferenceType extends ReferenceType {
+
+       private ResolvedType lowerBound;
+
+       private ResolvedType upperBound;
+
+       protected ReferenceType[] additionalInterfaceBounds = new ReferenceType[0];
+
+       protected boolean isExtends = true;
+
+       protected boolean isSuper = false;
+
+       public UnresolvedType getUpperBound() {
+               return upperBound;
+       }
+
+       public UnresolvedType getLowerBound() {
+               return lowerBound;
+       }
+
+       public BoundedReferenceType(ReferenceType aBound, boolean isExtends,
+                       World world) {
+               super((isExtends ? "+" : "-") + aBound.signature,
+                               aBound.signatureErasure, world);
+               this.isExtends = isExtends;
+               this.isSuper = !isExtends;
+               if (isExtends) {
+                       upperBound = aBound;
+               } else {
+                       lowerBound = aBound;
+                       upperBound = world.resolve(UnresolvedType.OBJECT);
+               }
+               setDelegate(new ReferenceTypeReferenceTypeDelegate(
+                               (ReferenceType) getUpperBound()));
+       }
+
+       public BoundedReferenceType(ReferenceType aBound, boolean isExtends,
+                       World world, ReferenceType[] additionalInterfaces) {
+               this(aBound, isExtends, world);
+               this.additionalInterfaceBounds = additionalInterfaces;
+       }
+
+       public ReferenceType[] getAdditionalBounds() {
+               return additionalInterfaceBounds;
+       }
+
+       public UnresolvedType parameterize(Map typeBindings) {
+               ReferenceType[] parameterizedAdditionalInterfaces = new ReferenceType[additionalInterfaceBounds == null ? 0
+                               : additionalInterfaceBounds.length];
+               for (int i = 0; i < parameterizedAdditionalInterfaces.length; i++) {
+                       parameterizedAdditionalInterfaces[i] = (ReferenceType) additionalInterfaceBounds[i]
+                                       .parameterize(typeBindings);
+               }
+               if (isExtends) {
+                       return new BoundedReferenceType((ReferenceType) getUpperBound()
+                                       .parameterize(typeBindings), isExtends, world,
+                                       parameterizedAdditionalInterfaces);
+               } else {
+                       return new BoundedReferenceType((ReferenceType) getLowerBound()
+                                       .parameterize(typeBindings), isExtends, world,
+                                       parameterizedAdditionalInterfaces);
+               }
+       }
+
+       /**
+        * only for use when resolving GenericsWildcardTypeX or a
+        * TypeVariableReferenceType
+        */
+       protected BoundedReferenceType(String sig, String sigErasure, World world) {
+               super(sig, sigErasure, world);
+               upperBound = world.resolve(UnresolvedType.OBJECT);
+               setDelegate(new ReferenceTypeReferenceTypeDelegate(
+                               (ReferenceType) getUpperBound()));
+       }
+
+       public ReferenceType[] getInterfaceBounds() {
+               return additionalInterfaceBounds;
+       }
+
+       public boolean hasLowerBound() {
+               return getLowerBound() != null;
+       }
+
+       public boolean isExtends() {
+               return (isExtends && !getUpperBound().getSignature().equals(
+                               "Ljava/lang/Object;"));
+       }
+
+       public boolean isSuper() {
+               return isSuper;
+       }
+
+       public boolean alwaysMatches(ResolvedType aCandidateType) {
+               if (isExtends()) {
+                       // aCandidateType must be a subtype of upperBound
+                       return ((ReferenceType) getUpperBound())
+                                       .isAssignableFrom(aCandidateType);
+               } else if (isSuper()) {
+                       // aCandidateType must be a supertype of lowerBound
+                       return aCandidateType
+                                       .isAssignableFrom((ReferenceType) getLowerBound());
+               } else {
+                       return true; // straight '?'
+               }
+       }
+
+       // this "maybe matches" that
+       public boolean canBeCoercedTo(ResolvedType aCandidateType) {
+               if (alwaysMatches(aCandidateType))
+                       return true;
+               if (aCandidateType.isGenericWildcard()) {
+                       BoundedReferenceType boundedRT = (BoundedReferenceType) aCandidateType;
+                       ResolvedType myUpperBound = (ResolvedType) getUpperBound();
+                       ResolvedType myLowerBound = (ResolvedType) getLowerBound();
+                       if (isExtends()) {
+                               if (boundedRT.isExtends()) {
+                                       return myUpperBound
+                                                       .isAssignableFrom((ResolvedType) boundedRT
+                                                                       .getUpperBound());
+                               } else if (boundedRT.isSuper()) {
+                                       return myUpperBound == boundedRT.getLowerBound();
+                               } else {
+                                       return true; // it's '?'
+                               }
+                       } else if (isSuper()) {
+                               if (boundedRT.isSuper()) {
+                                       return ((ResolvedType) boundedRT.getLowerBound())
+                                                       .isAssignableFrom(myLowerBound);
+                               } else if (boundedRT.isExtends()) {
+                                       return myLowerBound == boundedRT.getUpperBound();
+                               } else {
+                                       return true;
+                               }
+                       } else {
+                               return true;
+                       }
+               } else {
+                       return false;
+               }
+       }
+
+       public String getSimpleName() {
+               if (!isExtends() && !isSuper())
+                       return "?";
+               if (isExtends()) {
+                       return ("? extends " + getUpperBound().getSimpleName());
+               } else {
+                       return ("? super " + getLowerBound().getSimpleName());
+               }
+       }
+
+       // override to include additional interface bounds...
+       public ResolvedType[] getDeclaredInterfaces() {
+               ResolvedType[] interfaces = super.getDeclaredInterfaces();
+               if (additionalInterfaceBounds.length > 0) {
+                       ResolvedType[] allInterfaces = new ResolvedType[interfaces.length
+                                       + additionalInterfaceBounds.length];
+                       System
+                                       .arraycopy(interfaces, 0, allInterfaces, 0,
+                                                       interfaces.length);
+                       System.arraycopy(additionalInterfaceBounds, 0, allInterfaces,
+                                       interfaces.length, additionalInterfaceBounds.length);
+                       return allInterfaces;
+               } else {
+                       return interfaces;
+               }
+       }
+
+       public boolean isGenericWildcard() {
+               return true;
+       }
+
+       protected static class ReferenceTypeReferenceTypeDelegate extends
+                       AbstractReferenceTypeDelegate {
+
+               public ReferenceTypeReferenceTypeDelegate(ReferenceType backing) {
+                       super(backing, false);
+               }
+
+               public void addAnnotation(AnnotationAJ annotationX) {
+                       throw new UnsupportedOperationException(
+                                       "What on earth do you think you are doing???");
+               }
+
+               public boolean isAspect() {
+                       return resolvedTypeX.isAspect();
+               }
+
+               public boolean isAnnotationStyleAspect() {
+                       return resolvedTypeX.isAnnotationStyleAspect();
+               }
+
+               public boolean isInterface() {
+                       return resolvedTypeX.isInterface();
+               }
+
+               public boolean isEnum() {
+                       return resolvedTypeX.isEnum();
+               }
+
+               public boolean isAnnotation() {
+                       return resolvedTypeX.isAnnotation();
+               }
+
+               public boolean isAnnotationWithRuntimeRetention() {
+                       return resolvedTypeX.isAnnotationWithRuntimeRetention();
+               }
+
+               public boolean isAnonymous() {
+                       return resolvedTypeX.isAnonymous();
+               }
+
+               public boolean isNested() {
+                       return resolvedTypeX.isNested();
+               }
+
+               public ResolvedType getOuterClass() {
+                       return resolvedTypeX.getOuterClass();
+               }
+
+               public String getRetentionPolicy() {
+                       return resolvedTypeX.getRetentionPolicy();
+               }
+
+               public boolean canAnnotationTargetType() {
+                       return resolvedTypeX.canAnnotationTargetType();
+               }
+
+               public AnnotationTargetKind[] getAnnotationTargetKinds() {
+                       return resolvedTypeX.getAnnotationTargetKinds();
+               }
+
+               public boolean isGeneric() {
+                       return resolvedTypeX.isGenericType();
+               }
+
+               public String getDeclaredGenericSignature() {
+                       return resolvedTypeX.getDeclaredGenericSignature();
+               }
+
+               public boolean hasAnnotation(UnresolvedType ofType) {
+                       return resolvedTypeX.hasAnnotation(ofType);
+               }
+
+               public AnnotationAJ[] getAnnotations() {
+                       return resolvedTypeX.getAnnotations();
+               }
+
+               public ResolvedType[] getAnnotationTypes() {
+                       return resolvedTypeX.getAnnotationTypes();
+               }
+
+               public ResolvedMember[] getDeclaredFields() {
+                       return resolvedTypeX.getDeclaredFields();
+               }
+
+               public ResolvedType[] getDeclaredInterfaces() {
+                       return resolvedTypeX.getDeclaredInterfaces();
+               }
+
+               public ResolvedMember[] getDeclaredMethods() {
+                       return resolvedTypeX.getDeclaredMethods();
+               }
+
+               public ResolvedMember[] getDeclaredPointcuts() {
+                       return resolvedTypeX.getDeclaredPointcuts();
+               }
+
+               public PerClause getPerClause() {
+                       return resolvedTypeX.getPerClause();
+               }
+
+               public Collection getDeclares() {
+                       return resolvedTypeX.getDeclares();
+               }
+
+               public Collection getTypeMungers() {
+                       return resolvedTypeX.getTypeMungers();
+               }
+
+               public Collection getPrivilegedAccesses() {
+                       return Collections.EMPTY_LIST;
+               }
+
+               public int getModifiers() {
+                       return resolvedTypeX.getModifiers();
+               }
+
+               public ResolvedType getSuperclass() {
+                       return resolvedTypeX.getSuperclass();
+               }
+
+               public WeaverStateInfo getWeaverState() {
+                       return null;
+               }
+
+               public TypeVariable[] getTypeVariables() {
+                       return resolvedTypeX.getTypeVariables();
+               }
+
+               public void ensureDelegateConsistent() {
+                       resolvedTypeX.getDelegate().ensureDelegateConsistent();
+               }
+
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Checker.java b/org.aspectj.matcher/src/org/aspectj/weaver/Checker.java
new file mode 100644 (file)
index 0000000..7505d12
--- /dev/null
@@ -0,0 +1,151 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
+import org.aspectj.weaver.patterns.PerClause;
+import org.aspectj.weaver.patterns.Pointcut;
+
+/**
+ * Representation of a shadow munger for a declare error or warning declaration.
+ * 
+ * @author Andy Clement
+ */
+public class Checker extends ShadowMunger {
+
+       private final String message;
+       private final boolean isError; // if not error then it is a warning
+       private volatile int hashCode = -1;
+
+       /**
+        * Create a Checker for a deow.
+        * 
+        * @param deow the declare error or warning for which to create the checker munger
+        */
+       public Checker(DeclareErrorOrWarning deow) {
+               super(deow.getPointcut(), deow.getStart(), deow.getEnd(), deow.getSourceContext());
+               this.message = deow.getMessage();
+               this.isError = deow.isError();
+       }
+
+       /**
+        * Only used when filling in a parameterized Checker.
+        * 
+        * @param pc the pointcut
+        * @param start the start
+        * @param end the end
+        * @param context the source context
+        * @param message the message string
+        * @param isError whether it is an error or just a warning
+        */
+       private Checker(Pointcut pc, int start, int end, ISourceContext context, String message, boolean isError) {
+               super(pc, start, end, context);
+               this.message = message;
+               this.isError = isError;
+       }
+
+       public boolean isError() {
+               return isError;
+       }
+
+       /**
+        * Not supported for a Checker
+        */
+       public void specializeOn(Shadow shadow) {
+               throw new RuntimeException("illegal state");
+       }
+
+       /**
+        * Not supported for a Checker
+        */
+       public void implementOn(Shadow shadow) {
+               throw new RuntimeException("illegal state");
+       }
+
+       /**
+        * Determine if the Checker matches at a shadow. If it does then we can immediately report the message. There (currently) can
+        * never be a non-statically determinable match.
+        * 
+        * @param shadow the shadow which to match against
+        * @param world the world through which to access message handlers
+        */
+       public boolean match(Shadow shadow, World world) {
+               if (super.match(shadow, world)) {
+                       world.reportCheckerMatch(this, shadow);
+               }
+               return false;
+       }
+
+       // FIXME what the hell?
+       public int compareTo(Object other) {
+               return 0;
+       }
+
+       // FIXME Alex: ATAJ is that ok in all cases ?
+       /**
+        * Default to true
+        * 
+        * @return
+        */
+       public boolean mustCheckExceptions() {
+               return true;
+       }
+
+       public Collection getThrownExceptions() {
+               return Collections.EMPTY_LIST;
+       }
+
+       // FIXME this perhaps ought to take account of the other fields in advice ...
+       public boolean equals(Object other) {
+               if (!(other instanceof Checker)) {
+                       return false;
+               }
+               Checker o = (Checker) other;
+               return o.isError == isError && ((o.pointcut == null) ? (pointcut == null) : o.pointcut.equals(pointcut));
+       }
+
+       public int hashCode() {
+               if (hashCode == -1) {
+                       int result = 17;
+                       result = 37 * result + (isError ? 1 : 0);
+                       result = 37 * result + ((pointcut == null) ? 0 : pointcut.hashCode());
+                       hashCode = result;
+               }
+               return hashCode;
+       }
+
+       public ShadowMunger parameterizeWith(ResolvedType declaringType, Map typeVariableMap) {
+               Checker ret = new Checker(this.pointcut.parameterizeWith(typeVariableMap, declaringType.getWorld()), this.start, this.end,
+                               this.sourceContext, this.message, this.isError);
+               return ret;
+       }
+
+       /**
+        * Concretize this Checker by concretizing the pointcut.
+        * 
+        */
+       public ShadowMunger concretize(ResolvedType theAspect, World world, PerClause clause) {
+               this.pointcut = this.pointcut.concretize(theAspect, getDeclaringType(), 0, this);
+               this.hashCode = -1;
+               return this;
+       }
+
+       public String getMessage() {
+               return this.message;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ClassAnnotationValue.java b/org.aspectj.matcher/src/org/aspectj/weaver/ClassAnnotationValue.java
new file mode 100644 (file)
index 0000000..a85c10c
--- /dev/null
@@ -0,0 +1,31 @@
+/* *******************************************************************
+ * Copyright (c) 2006 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement IBM     initial implementation 
+ * ******************************************************************/
+ package org.aspectj.weaver;
+
+public class ClassAnnotationValue extends AnnotationValue {
+
+       private String signature;
+       
+       public ClassAnnotationValue(String sig) {
+               super(AnnotationValue.CLASS);
+               this.signature = sig;
+       }
+       
+       public String stringify() {
+               return signature;
+       }       
+       
+       public String toString() {
+               return signature;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ConcreteTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/ConcreteTypeMunger.java
new file mode 100644 (file)
index 0000000..524d091
--- /dev/null
@@ -0,0 +1,144 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.util.Map;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.util.PartialOrder;
+
+public abstract class ConcreteTypeMunger implements PartialOrder.PartialComparable {
+       protected ResolvedTypeMunger munger;
+       protected ResolvedType aspectType;
+
+       public ConcreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) {
+               this.munger = munger;
+               this.aspectType = aspectType;
+       }
+
+       // An EclipseTypeMunger and a BcelTypeMunger may say TRUE for equivalentTo()...
+       // public boolean equivalentTo(Object other) {
+       // if (! (other instanceof ConcreteTypeMunger)) return false;
+       // ConcreteTypeMunger o = (ConcreteTypeMunger) other;
+       // return ((o.getMunger() == null) ? (getMunger() == null) : o.getMunger().equals(getMunger()))
+       // && ((o.getAspectType() == null) ? (getAspectType() == null) : o.getAspectType().equals(getAspectType()));
+       // }
+
+       // public abstract boolean munge(LazyClassGen gen);
+
+       /**
+        * returns null for mungers that are used internally, but were not part of a declared thing in source code.
+        */
+       public ResolvedTypeMunger getMunger() {
+               return munger;
+       }
+
+       public ResolvedType getAspectType() {
+               return aspectType;
+       }
+
+       public ResolvedMember getSignature() {
+               return munger.getSignature();
+       }
+
+       public World getWorld() {
+               return aspectType.getWorld();
+       }
+
+       public ISourceLocation getSourceLocation() {
+               if (munger == null)
+                       return null;
+               return munger.getSourceLocation(); // XXX
+       }
+
+       public boolean matches(ResolvedType onType) {
+               if (munger == null)
+                       throw new RuntimeException("huh: " + this);
+               return munger.matches(onType, aspectType);
+       }
+
+       public ResolvedMember getMatchingSyntheticMember(Member member) {
+               return munger.getMatchingSyntheticMember(member, aspectType);
+       }
+
+       public int compareTo(Object other) {
+               ConcreteTypeMunger o = (ConcreteTypeMunger) other;
+
+               ResolvedType otherAspect = o.aspectType;
+
+               if (aspectType.equals(otherAspect)) {
+                       return getSignature().getStart() < o.getSignature().getStart() ? -1 : +1;
+               } else if (aspectType.isAssignableFrom(o.aspectType)) {
+                       return +1;
+               } else if (o.aspectType.isAssignableFrom(aspectType)) {
+                       return -1;
+               } else {
+                       return 0;
+               }
+       }
+
+       public int fallbackCompareTo(Object other) {
+               // ConcreteTypeMunger o = (ConcreteTypeMunger) other;
+               return 0;
+       }
+
+       /**
+        * returns true if the ITD target type used type variables, for example I<T>. When they are specified like this, the ITDs
+        * 'share' type variables with the generic type. Usually this method is called because we need to know whether to tailor the
+        * munger for addition to a particular type. For example: <code>
+        *   interface I<T> {}
+        *   
+        *   aspect X implements I<String> {
+        *     List<T> I<T>.foo { return null; }
+        *   }
+        * </code> In this case the munger matches X but it matches with the form <code>
+        *   List<String> foo() { return null; }
+        * </code>
+        */
+       public boolean isTargetTypeParameterized() {
+               if (munger == null)
+                       return false;
+               return munger.sharesTypeVariablesWithGenericType();
+       }
+
+       /**
+        * For an ITD made on a generic type that shares type variables with that target type, this method will tailor the ITD for a
+        * particular usage of the generic type - either in its raw or parameterized form.
+        */
+       public abstract ConcreteTypeMunger parameterizedFor(ResolvedType targetType);
+
+       public boolean isLateMunger() {
+               if (munger == null)
+                       return false;
+               return munger.isLateMunger();
+       }
+
+       public abstract ConcreteTypeMunger parameterizeWith(Map parameterizationMap, World world);
+
+       /**
+        * Some type mungers are created purely to help with the implementation of shadow mungers. For example to support the cflow()
+        * pointcut we create a new cflow field in the aspect, and that is added via a BcelCflowCounterFieldAdder.
+        * 
+        * During compilation we need to compare sets of type mungers, and if some only come into existence after the 'shadowy' type
+        * things have been processed, we need to ignore them during the comparison.
+        * 
+        * Returning true from this method indicates the type munger exists to support 'shadowy' stuff - and so can be ignored in some
+        * comparison.
+        */
+       public boolean existsToSupportShadowMunging() {
+               if (munger != null) {
+                       return munger.existsToSupportShadowMunging();
+               }
+               return false;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Constants.java b/org.aspectj.matcher/src/org/aspectj/weaver/Constants.java
new file mode 100644 (file)
index 0000000..7c55aab
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM 
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Andy Clement - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.weaver;
+
+/**
+ * Some useful weaver constants. 
+ *
+ * Current uses:
+ * 1. Holds values that are necessary for working with 1.5 code but
+ *    which don't exist in a 1.4 world.  
+ */
+public interface Constants {
+
+       public final static int ACC_BRIDGE  = 0x0040;
+       public final static int ACC_VARARGS = 0x0080;
+       
+       public final static String RUNTIME_LEVEL_12 = "1.2";
+       public final static String RUNTIME_LEVEL_15 = "1.5";
+       
+       // Default for 1.5.0
+       public final static String RUNTIME_LEVEL_DEFAULT = RUNTIME_LEVEL_15;
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembers.java b/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembers.java
new file mode 100644 (file)
index 0000000..9cdb78a
--- /dev/null
@@ -0,0 +1,533 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.aspectj.weaver.patterns.Declare;
+import org.aspectj.weaver.patterns.DeclareAnnotation;
+import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
+import org.aspectj.weaver.patterns.DeclareParents;
+import org.aspectj.weaver.patterns.DeclarePrecedence;
+import org.aspectj.weaver.patterns.DeclareSoft;
+import org.aspectj.weaver.patterns.PerClause;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.patterns.PointcutRewriter;
+
+/**
+ * This holds on to all members that have an invasive effect outside of there
+ * own compilation unit. These members need to be all gathered up and in a world
+ * before any weaving can take place.
+ * 
+ * They are also important in the compilation process and need to be gathered up
+ * before the inter-type declaration weaving stage (unsurprisingly).
+ * 
+ * All members are concrete.
+ * 
+ * @author Jim Hugunin
+ */
+public class CrosscuttingMembers {
+       private final ResolvedType inAspect;
+       private final World world;
+
+       private PerClause perClause;
+
+       private List shadowMungers = new ArrayList(4);
+       private List typeMungers = new ArrayList(4);
+       private List lateTypeMungers = new ArrayList(0);
+
+       private List declareParents = new ArrayList(4);
+       private List declareSofts = new ArrayList(0);
+       private List declareDominates = new ArrayList(4);
+
+       // These are like declare parents type mungers
+       private List declareAnnotationsOnType = new ArrayList();
+       private List declareAnnotationsOnField = new ArrayList();
+       private List declareAnnotationsOnMethods = new ArrayList(); // includes
+                                                                                                                               // ctors
+
+       private boolean shouldConcretizeIfNeeded = true;
+
+       public CrosscuttingMembers(ResolvedType inAspect, boolean shouldConcretizeIfNeeded) {
+               this.inAspect = inAspect;
+               world = inAspect.getWorld();
+               this.shouldConcretizeIfNeeded = shouldConcretizeIfNeeded;
+       }
+
+       private final Hashtable cflowFields = new Hashtable();
+       private final Hashtable cflowBelowFields = new Hashtable();
+
+       // public void addConcreteShadowMungers(Collection c) {
+       // shadowMungers.addAll(c);
+       // }
+
+       public void addConcreteShadowMunger(ShadowMunger m) {
+               // assert m is concrete
+               shadowMungers.add(m);
+       }
+
+       public void addShadowMungers(Collection c) {
+               for (Iterator i = c.iterator(); i.hasNext();) {
+                       addShadowMunger((ShadowMunger) i.next());
+               }
+       }
+
+       private void addShadowMunger(ShadowMunger m) {
+               if (inAspect.isAbstract())
+                       return; // we don't do mungers for abstract aspects
+               addConcreteShadowMunger(m.concretize(inAspect, world, perClause));
+       }
+
+       public void addTypeMungers(Collection c) {
+               typeMungers.addAll(c);
+       }
+
+       public void addTypeMunger(ConcreteTypeMunger m) {
+               if (m == null)
+                       throw new Error("FIXME AV - should not happen or what ?");// return;
+                                                                                                                                               // //???
+               typeMungers.add(m);
+       }
+
+       public void addLateTypeMungers(Collection c) {
+               lateTypeMungers.addAll(c);
+       }
+
+       public void addLateTypeMunger(ConcreteTypeMunger m) {
+               lateTypeMungers.add(m);
+       }
+
+       public void addDeclares(Collection c) {
+               for (Iterator i = c.iterator(); i.hasNext();) {
+                       addDeclare((Declare) i.next());
+               }
+       }
+
+       public void addDeclare(Declare declare) {
+               // this is not extensible, oh well
+               if (declare instanceof DeclareErrorOrWarning) {
+                       ShadowMunger m = new Checker((DeclareErrorOrWarning) declare);
+                       m.setDeclaringType(declare.getDeclaringType());
+                       addShadowMunger(m);
+               } else if (declare instanceof DeclarePrecedence) {
+                       declareDominates.add(declare);
+               } else if (declare instanceof DeclareParents) {
+                       DeclareParents dp = (DeclareParents) declare;
+                       exposeTypes(dp.getParents().getExactTypes());
+                       declareParents.add(dp);
+               } else if (declare instanceof DeclareSoft) {
+                       DeclareSoft d = (DeclareSoft) declare;
+                       // Ordered so that during concretization we can check the related
+                       // munger
+                       ShadowMunger m = Advice.makeSoftener(world, d.getPointcut(), d.getException(), inAspect, d);
+                       m.setDeclaringType(d.getDeclaringType());
+                       Pointcut concretePointcut = d.getPointcut().concretize(inAspect, d.getDeclaringType(), 0, m);
+                       m.pointcut = concretePointcut;
+                       declareSofts.add(new DeclareSoft(d.getException(), concretePointcut));
+                       addConcreteShadowMunger(m);
+               } else if (declare instanceof DeclareAnnotation) {
+                       // FIXME asc perf Possible Improvement. Investigate why this is
+                       // called twice in a weave ?
+                       DeclareAnnotation da = (DeclareAnnotation) declare;
+                       if (da.getAspect() == null)
+                               da.setAspect(inAspect);
+                       if (da.isDeclareAtType()) {
+                               declareAnnotationsOnType.add(da);
+                       } else if (da.isDeclareAtField()) {
+                               declareAnnotationsOnField.add(da);
+                       } else if (da.isDeclareAtMethod() || da.isDeclareAtConstuctor()) {
+                               declareAnnotationsOnMethods.add(da);
+                       }
+               } else {
+                       throw new RuntimeException("unimplemented");
+               }
+       }
+
+       public void exposeTypes(Collection typesToExpose) {
+               for (Iterator i = typesToExpose.iterator(); i.hasNext();) {
+                       exposeType((UnresolvedType) i.next());
+               }
+       }
+
+       public void exposeType(UnresolvedType typeToExpose) {
+               if (ResolvedType.isMissing(typeToExpose))
+                       return;
+               if (typeToExpose.isParameterizedType() || typeToExpose.isRawType()) {
+                       if (typeToExpose instanceof ResolvedType) {
+                               typeToExpose = ((ResolvedType) typeToExpose).getGenericType();
+                       } else {
+                               typeToExpose = UnresolvedType.forSignature(typeToExpose.getErasureSignature());
+                       }
+               }
+               // Check we haven't already got a munger for this:
+               String signatureToLookFor = typeToExpose.getSignature();
+               for (Iterator iterator = typeMungers.iterator(); iterator.hasNext();) {
+                       ConcreteTypeMunger cTM = (ConcreteTypeMunger) iterator.next();
+                       ResolvedTypeMunger rTM = cTM.getMunger();
+                       if (rTM != null && rTM instanceof ExposeTypeMunger) {
+                               String exposedType = ((ExposeTypeMunger) rTM).getExposedTypeSignature();
+                               if (exposedType.equals(signatureToLookFor))
+                                       return; // dont need to bother
+                       }
+               }
+               addTypeMunger(world.getWeavingSupport().concreteTypeMunger(new ExposeTypeMunger(typeToExpose), inAspect));
+               // ResolvedMember member = new ResolvedMemberImpl(
+               // Member.STATIC_INITIALIZATION, typeToExpose, 0, ResolvedType.VOID,
+               // "<clinit>", UnresolvedType.NONE);
+               // addTypeMunger(world.concreteTypeMunger(
+               // new PrivilegedAccessMunger(member), inAspect));
+       }
+
+       public void addPrivilegedAccesses(Collection accessedMembers) {
+               for (Iterator i = accessedMembers.iterator(); i.hasNext();) {
+                       addPrivilegedAccess((ResolvedMember) i.next());
+               }
+       }
+
+       private void addPrivilegedAccess(ResolvedMember member) {
+               // System.err.println("add priv access: " + member);
+               addTypeMunger(world.getWeavingSupport().concreteTypeMunger(new PrivilegedAccessMunger(member), inAspect));
+       }
+
+       public Collection getCflowEntries() {
+               ArrayList ret = new ArrayList();
+               for (Iterator i = shadowMungers.iterator(); i.hasNext();) {
+                       ShadowMunger m = (ShadowMunger) i.next();
+                       if (m instanceof Advice) {
+                               Advice a = (Advice) m;
+                               if (a.getKind().isCflow()) {
+                                       ret.add(a);
+                               }
+                       }
+               }
+               return ret;
+       }
+
+       /**
+        * Updates the records if something has changed. This is called at most
+        * twice, firstly whilst collecting ITDs and declares. At this point the
+        * CrosscuttingMembers we're comparing ourselves with doesn't know about
+        * shadowmungers. Therefore a straight comparison with the existing list of
+        * shadowmungers would return that something has changed even though it
+        * might not have, so in this first round we ignore the shadowMungers. The
+        * second time this is called is whilst we're preparing to weave. At this
+        * point we know everything in the system and so we're able to compare the
+        * shadowMunger list. (see bug 129163)
+        * 
+        * @param other
+        * @param careAboutShadowMungers
+        * @return true if something has changed since the last time this method was
+        *         called, false otherwise
+        */
+       public boolean replaceWith(CrosscuttingMembers other, boolean careAboutShadowMungers) {
+               boolean changed = false;
+
+               if (careAboutShadowMungers) {
+                       if (perClause == null || !perClause.equals(other.perClause)) {
+                               changed = true;
+                               perClause = other.perClause;
+                       }
+               }
+
+               // XXX all of the below should be set equality rather than list equality
+               // System.err.println("old: " + shadowMungers + " new: " +
+               // other.shadowMungers);
+
+               if (careAboutShadowMungers) {
+                       // bug 129163: use set equality rather than list equality
+                       Set theseShadowMungers = new HashSet();
+                       Set theseInlinedAroundMungers = new HashSet();
+                       for (Iterator iter = shadowMungers.iterator(); iter.hasNext();) {
+                               ShadowMunger munger = (ShadowMunger) iter.next();
+                               if (munger instanceof Advice) {
+                                       Advice adviceMunger = (Advice) munger;
+                                       // bug 154054: if we're around advice that has been inlined
+                                       // then we need to do more checking than existing equals
+                                       // methods allow
+                                       if (!world.isXnoInline() && adviceMunger.getKind().equals(AdviceKind.Around)) {
+                                               theseInlinedAroundMungers.add(adviceMunger);
+                                       } else {
+                                               theseShadowMungers.add(adviceMunger);
+                                       }
+                               } else {
+                                       theseShadowMungers.add(munger);
+                               }
+                       }
+                       Set tempSet = new HashSet();
+                       tempSet.addAll(other.shadowMungers);
+                       Set otherShadowMungers = new HashSet();
+                       Set otherInlinedAroundMungers = new HashSet();
+                       for (Iterator iter = tempSet.iterator(); iter.hasNext();) {
+                               ShadowMunger munger = (ShadowMunger) iter.next();
+                               if (munger instanceof Advice) {
+                                       Advice adviceMunger = (Advice) munger;
+                                       // bug 154054: if we're around advice that has been inlined
+                                       // then we need to do more checking than existing equals
+                                       // methods allow
+                                       if (!world.isXnoInline() && adviceMunger.getKind().equals(AdviceKind.Around)) {
+                                               otherInlinedAroundMungers.add(rewritePointcutInMunger(adviceMunger));
+                                       } else {
+                                               otherShadowMungers.add(rewritePointcutInMunger(adviceMunger));
+                                       }
+                               } else {
+                                       otherShadowMungers.add(rewritePointcutInMunger(munger));
+                               }
+                       }
+                       if (!theseShadowMungers.equals(otherShadowMungers)) {
+                               changed = true;
+                       }
+                       if (!equivalent(theseInlinedAroundMungers, otherInlinedAroundMungers)) {
+                               changed = true;
+                       }
+
+                       // bug 158573 - if there are no changes then preserve whether
+                       // or not a particular shadowMunger has matched something.
+                       if (!changed) {
+                               for (Iterator iter = shadowMungers.iterator(); iter.hasNext();) {
+                                       ShadowMunger munger = (ShadowMunger) iter.next();
+                                       int i = other.shadowMungers.indexOf(munger);
+                                       ShadowMunger otherMunger = (ShadowMunger) other.shadowMungers.get(i);
+                                       if (munger instanceof Advice) {
+                                               ((Advice) otherMunger).setHasMatchedSomething(((Advice) munger).hasMatchedSomething());
+                                       }
+                               }
+                       }
+                       // replace the existing list of shadowmungers with the
+                       // new ones in case anything like the sourcelocation has
+                       // changed, however, don't want this flagged as a change
+                       // which will force a full build - bug 134541
+                       shadowMungers = other.shadowMungers;
+               }
+
+               // bug 129163: use set equality rather than list equality and
+               // if we dont care about shadow mungers then ignore those
+               // typeMungers which are created to help with the implementation
+               // of shadowMungers
+               Set theseTypeMungers = new HashSet();
+               Set otherTypeMungers = new HashSet();
+               if (!careAboutShadowMungers) {
+                       for (Iterator iter = typeMungers.iterator(); iter.hasNext();) {
+                               Object o = iter.next();
+                               if (o instanceof ConcreteTypeMunger) {
+                                       ConcreteTypeMunger typeMunger = (ConcreteTypeMunger) o;
+                                       if (!typeMunger.existsToSupportShadowMunging()) {
+                                               theseTypeMungers.add(typeMunger);
+                                       }
+                               } else {
+                                       theseTypeMungers.add(o);
+                               }
+                       }
+
+                       for (Iterator iter = other.typeMungers.iterator(); iter.hasNext();) {
+                               Object o = iter.next();
+                               if (o instanceof ConcreteTypeMunger) {
+                                       ConcreteTypeMunger typeMunger = (ConcreteTypeMunger) o;
+                                       if (!typeMunger.existsToSupportShadowMunging()) {
+                                               otherTypeMungers.add(typeMunger);
+                                       }
+                               } else {
+                                       otherTypeMungers.add(o);
+                               }
+                       }
+               } else {
+                       theseTypeMungers.addAll(typeMungers);
+                       otherTypeMungers.addAll(other.typeMungers);
+               }
+
+               // initial go at equivalence logic rather than set compare (see
+               // pr133532)
+               // if (theseTypeMungers.size()!=otherTypeMungers.size()) {
+               // changed = true;
+               // typeMungers = other.typeMungers;
+               // } else {
+               // boolean foundInequality=false;
+               // for (Iterator iter = theseTypeMungers.iterator(); iter.hasNext() &&
+               // !foundInequality;) {
+               // Object thisOne = (Object) iter.next();
+               // boolean foundInOtherSet = false;
+               // for (Iterator iterator = otherTypeMungers.iterator();
+               // iterator.hasNext();) {
+               // Object otherOne = (Object) iterator.next();
+               // if (thisOne instanceof ConcreteTypeMunger && otherOne instanceof
+               // ConcreteTypeMunger) {
+               // if (((ConcreteTypeMunger)thisOne).equivalentTo(otherOne)) {
+               // foundInOtherSet=true;
+               // } else if (thisOne.equals(otherOne)) {
+               // foundInOtherSet=true;
+               // }
+               // } else {
+               // if (thisOne.equals(otherOne)) {
+               // foundInOtherSet=true;
+               // }
+               // }
+               // }
+               // if (!foundInOtherSet) foundInequality=true;
+               // }
+               // if (foundInequality) {
+               // changed = true;
+               // typeMungers = other.typeMungers;
+               // // } else {
+               // // typeMungers = other.typeMungers;
+               // }
+               // }
+               if (!theseTypeMungers.equals(otherTypeMungers)) {
+                       changed = true;
+                       typeMungers = other.typeMungers;
+               }
+
+               if (!lateTypeMungers.equals(other.lateTypeMungers)) {
+                       changed = true;
+                       lateTypeMungers = other.lateTypeMungers;
+               }
+
+               if (!declareDominates.equals(other.declareDominates)) {
+                       changed = true;
+                       declareDominates = other.declareDominates;
+               }
+
+               if (!declareParents.equals(other.declareParents)) {
+                       changed = true;
+                       declareParents = other.declareParents;
+               }
+
+               if (!declareSofts.equals(other.declareSofts)) {
+                       changed = true;
+                       declareSofts = other.declareSofts;
+               }
+
+               // DECAT for when attempting to replace an aspect
+               if (!declareAnnotationsOnType.equals(other.declareAnnotationsOnType)) {
+                       changed = true;
+                       declareAnnotationsOnType = other.declareAnnotationsOnType;
+               }
+
+               if (!declareAnnotationsOnField.equals(other.declareAnnotationsOnField)) {
+                       changed = true;
+                       declareAnnotationsOnField = other.declareAnnotationsOnField;
+               }
+
+               if (!declareAnnotationsOnMethods.equals(other.declareAnnotationsOnMethods)) {
+                       changed = true;
+                       declareAnnotationsOnMethods = other.declareAnnotationsOnMethods;
+               }
+
+               return changed;
+       }
+
+       private boolean equivalent(Set theseInlinedAroundMungers, Set otherInlinedAroundMungers) {
+               if (theseInlinedAroundMungers.size() != otherInlinedAroundMungers.size()) {
+                       return false;
+               }
+               for (Iterator iter = theseInlinedAroundMungers.iterator(); iter.hasNext();) {
+                       Advice thisAdvice = (Advice) iter.next();
+                       boolean foundIt = false;
+                       for (Iterator iterator = otherInlinedAroundMungers.iterator(); iterator.hasNext();) {
+                               Advice otherAdvice = (Advice) iterator.next();
+                               if (thisAdvice.equals(otherAdvice)) {
+                                       if (thisAdvice.getSignature() instanceof ResolvedMemberImpl) {
+                                               if (((ResolvedMemberImpl) thisAdvice.getSignature()).isEquivalentTo(otherAdvice.getSignature())) {
+                                                       foundIt = true;
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               }
+                       }
+                       if (!foundIt) {
+                               return false;
+                       }
+               }
+               return true;
+       }
+
+       private ShadowMunger rewritePointcutInMunger(ShadowMunger munger) {
+               PointcutRewriter pr = new PointcutRewriter();
+               Pointcut p = munger.getPointcut();
+               Pointcut newP = pr.rewrite(p);
+               if (p.m_ignoreUnboundBindingForNames.length != 0) {// *sigh* dirty fix
+                                                                                                                       // for dirty hacky
+                                                                                                                       // implementation
+                                                                                                                       // pr149305
+                       newP.m_ignoreUnboundBindingForNames = p.m_ignoreUnboundBindingForNames;
+               }
+               munger.setPointcut(newP);
+               return munger;
+       }
+
+       public void setPerClause(PerClause perClause) {
+               if (shouldConcretizeIfNeeded) {
+                       this.perClause = perClause.concretize(inAspect);
+               } else {
+                       this.perClause = perClause;
+               }
+       }
+
+       public List getDeclareDominates() {
+               return declareDominates;
+       }
+
+       public List getDeclareParents() {
+               return declareParents;
+       }
+
+       public List getDeclareSofts() {
+               return declareSofts;
+       }
+
+       public List getShadowMungers() {
+               return shadowMungers;
+       }
+
+       public List getTypeMungers() {
+               return typeMungers;
+       }
+
+       public List getLateTypeMungers() {
+               return lateTypeMungers;
+       }
+
+       public List getDeclareAnnotationOnTypes() {
+               return declareAnnotationsOnType;
+       }
+
+       public List getDeclareAnnotationOnFields() {
+               return declareAnnotationsOnField;
+       }
+
+       /**
+        * includes declare @method and @constructor
+        */
+       public List getDeclareAnnotationOnMethods() {
+               return declareAnnotationsOnMethods;
+       }
+
+       public Map getCflowBelowFields() {
+               return cflowBelowFields;
+       }
+
+       public Map getCflowFields() {
+               return cflowFields;
+       }
+
+       public void clearCaches() {
+               cflowFields.clear();
+               cflowBelowFields.clear();
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembersSet.java b/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembersSet.java
new file mode 100644 (file)
index 0000000..186d7ef
--- /dev/null
@@ -0,0 +1,305 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.aspectj.weaver.patterns.DeclareParents;
+import org.aspectj.weaver.patterns.IVerificationRequired;
+import org.aspectj.weaver.tools.Trace;
+import org.aspectj.weaver.tools.TraceFactory;
+
+/**
+ * This holds on to all CrosscuttingMembers for a world. It handles management of change.
+ * 
+ * @author Jim Hugunin
+ */
+public class CrosscuttingMembersSet {
+       // FIXME AV - ? we may need a sequencedHashMap there to ensure source based precedence for @AJ advice
+       private final Map /* ResolvedType (the aspect) > CrosscuttingMembers */members = new HashMap();
+
+       private List shadowMungers = null;
+       private List typeMungers = null;
+       private List lateTypeMungers = null;
+       private List declareSofts = null;
+       private List declareParents = null;
+       private List declareAnnotationOnTypes = null;
+       private List declareAnnotationOnFields = null;
+       private List declareAnnotationOnMethods = null; // includes ctors
+       private List declareDominates = null;
+       private boolean changedSinceLastReset = false;
+
+       private List /* IVerificationRequired */verificationList = null; // List of things to be verified once the type system is
+                                                                                                                                       // 'complete'
+
+       private static Trace trace = TraceFactory.getTraceFactory().getTrace(CrosscuttingMembersSet.class);
+
+       public CrosscuttingMembersSet(World world) {
+               trace.enter("<init>", this, world);
+
+               trace.exit("<init>");
+       }
+
+       public boolean addOrReplaceAspect(ResolvedType aspectType) {
+               return addOrReplaceAspect(aspectType, true);
+       }
+
+       /**
+        * @return whether or not that was a change to the global signature XXX for efficiency we will need a richer representation than
+        *         this
+        */
+       public boolean addOrReplaceAspect(ResolvedType aspectType, boolean inWeavingPhase) {
+               trace.enter("addOrReplaceAspect", this, new Object[] { aspectType, new Boolean(inWeavingPhase) });
+
+               boolean change = false;
+               CrosscuttingMembers xcut = (CrosscuttingMembers) members.get(aspectType);
+               if (xcut == null) {
+                       members.put(aspectType, aspectType.collectCrosscuttingMembers(inWeavingPhase));
+                       clearCaches();
+                       change = true;
+               } else {
+                       if (xcut.replaceWith(aspectType.collectCrosscuttingMembers(inWeavingPhase), inWeavingPhase)) {
+                               clearCaches();
+                               change = true;
+                       } else {
+                               if (inWeavingPhase) {
+                                       // bug 134541 - even though we haven't changed we may have updated the
+                                       // sourcelocation for the shadowMunger which we need to pick up
+                                       shadowMungers = null;
+                               }
+                               change = false;
+                       }
+               }
+               if (aspectType.isAbstract()) {
+                       // we might have sub-aspects that need to re-collect their crosscutting members from us
+                       boolean ancestorChange = addOrReplaceDescendantsOf(aspectType, inWeavingPhase);
+                       change = change || ancestorChange;
+               }
+               changedSinceLastReset = changedSinceLastReset || change;
+
+               trace.exit("addOrReplaceAspect", change);
+               return change;
+       }
+
+       private boolean addOrReplaceDescendantsOf(ResolvedType aspectType, boolean inWeavePhase) {
+               // System.err.println("Looking at descendants of "+aspectType.getName());
+               Set knownAspects = members.keySet();
+               Set toBeReplaced = new HashSet();
+               for (Iterator it = knownAspects.iterator(); it.hasNext();) {
+                       ResolvedType candidateDescendant = (ResolvedType) it.next();
+                       if ((candidateDescendant != aspectType) && (aspectType.isAssignableFrom(candidateDescendant))) {
+                               toBeReplaced.add(candidateDescendant);
+                       }
+               }
+               boolean change = false;
+               for (Iterator it = toBeReplaced.iterator(); it.hasNext();) {
+                       ResolvedType next = (ResolvedType) it.next();
+                       boolean thisChange = addOrReplaceAspect(next, inWeavePhase);
+                       change = change || thisChange;
+               }
+               return change;
+       }
+
+       public void addAdviceLikeDeclares(ResolvedType aspectType) {
+               CrosscuttingMembers xcut = (CrosscuttingMembers) members.get(aspectType);
+               xcut.addDeclares(aspectType.collectDeclares(true));
+       }
+
+       public boolean deleteAspect(UnresolvedType aspectType) {
+               boolean isAspect = members.remove(aspectType) != null;
+               clearCaches();
+               return isAspect;
+       }
+
+       public boolean containsAspect(UnresolvedType aspectType) {
+               return members.containsKey(aspectType);
+       }
+
+       // XXX only for testing
+       public void addFixedCrosscuttingMembers(ResolvedType aspectType) {
+               members.put(aspectType, aspectType.crosscuttingMembers);
+               clearCaches();
+       }
+
+       private void clearCaches() {
+               shadowMungers = null;
+               typeMungers = null;
+               lateTypeMungers = null;
+               declareSofts = null;
+               declareParents = null;
+               declareAnnotationOnFields = null;
+               declareAnnotationOnMethods = null;
+               declareAnnotationOnTypes = null;
+               declareDominates = null;
+       }
+
+       public List getShadowMungers() {
+               if (shadowMungers == null) {
+                       ArrayList ret = new ArrayList();
+                       for (Iterator i = members.values().iterator(); i.hasNext();) {
+                               ret.addAll(((CrosscuttingMembers) i.next()).getShadowMungers());
+                       }
+                       shadowMungers = ret;
+               }
+               return shadowMungers;
+       }
+
+       public List getTypeMungers() {
+               if (typeMungers == null) {
+                       ArrayList ret = new ArrayList();
+                       for (Iterator i = members.values().iterator(); i.hasNext();) {
+                               ret.addAll(((CrosscuttingMembers) i.next()).getTypeMungers());
+                       }
+                       typeMungers = ret;
+               }
+               return typeMungers;
+       }
+
+       public List getLateTypeMungers() {
+               if (lateTypeMungers == null) {
+                       ArrayList ret = new ArrayList();
+                       for (Iterator i = members.values().iterator(); i.hasNext();) {
+                               ret.addAll(((CrosscuttingMembers) i.next()).getLateTypeMungers());
+                       }
+                       lateTypeMungers = ret;
+               }
+               return lateTypeMungers;
+       }
+
+       public List getDeclareSofts() {
+               if (declareSofts == null) {
+                       Set ret = new HashSet();
+                       for (Iterator i = members.values().iterator(); i.hasNext();) {
+                               ret.addAll(((CrosscuttingMembers) i.next()).getDeclareSofts());
+                       }
+                       declareSofts = new ArrayList();
+                       declareSofts.addAll(ret);
+               }
+               return declareSofts;
+       }
+
+       public List getDeclareParents() {
+               if (declareParents == null) {
+                       Set ret = new HashSet();
+                       for (Iterator i = members.values().iterator(); i.hasNext();) {
+                               ret.addAll(((CrosscuttingMembers) i.next()).getDeclareParents());
+                       }
+                       declareParents = new ArrayList();
+                       declareParents.addAll(ret);
+               }
+               return declareParents;
+       }
+
+       // DECAT Merge multiple together
+       public List getDeclareAnnotationOnTypes() {
+               if (declareAnnotationOnTypes == null) {
+                       Set ret = new HashSet();
+                       for (Iterator i = members.values().iterator(); i.hasNext();) {
+                               ret.addAll(((CrosscuttingMembers) i.next()).getDeclareAnnotationOnTypes());
+                       }
+                       declareAnnotationOnTypes = new ArrayList();
+                       declareAnnotationOnTypes.addAll(ret);
+               }
+               return declareAnnotationOnTypes;
+       }
+
+       public List getDeclareAnnotationOnFields() {
+               if (declareAnnotationOnFields == null) {
+                       Set ret = new HashSet();
+                       for (Iterator i = members.values().iterator(); i.hasNext();) {
+                               ret.addAll(((CrosscuttingMembers) i.next()).getDeclareAnnotationOnFields());
+                       }
+                       declareAnnotationOnFields = new ArrayList();
+                       declareAnnotationOnFields.addAll(ret);
+               }
+               return declareAnnotationOnFields;
+       }
+
+       /**
+        * Return an amalgamation of the declare @method/@constructor statements.
+        */
+       public List getDeclareAnnotationOnMethods() {
+               if (declareAnnotationOnMethods == null) {
+                       Set ret = new HashSet();
+                       for (Iterator i = members.values().iterator(); i.hasNext();) {
+                               ret.addAll(((CrosscuttingMembers) i.next()).getDeclareAnnotationOnMethods());
+                       }
+                       declareAnnotationOnMethods = new ArrayList();
+                       declareAnnotationOnMethods.addAll(ret);
+               }
+               return declareAnnotationOnMethods;
+       }
+
+       public List getDeclareDominates() {
+               if (declareDominates == null) {
+                       ArrayList ret = new ArrayList();
+                       for (Iterator i = members.values().iterator(); i.hasNext();) {
+                               ret.addAll(((CrosscuttingMembers) i.next()).getDeclareDominates());
+                       }
+                       declareDominates = ret;
+               }
+               return declareDominates;
+       }
+
+       public ResolvedType findAspectDeclaringParents(DeclareParents p) {
+               Set keys = this.members.keySet();
+               for (Iterator iter = keys.iterator(); iter.hasNext();) {
+                       ResolvedType element = (ResolvedType) iter.next();
+                       for (Iterator i = ((CrosscuttingMembers) members.get(element)).getDeclareParents().iterator(); i.hasNext();) {
+                               DeclareParents dp = (DeclareParents) i.next();
+                               if (dp.equals(p))
+                                       return element;
+                       }
+               }
+               return null;
+       }
+
+       public void reset() {
+               verificationList = null;
+               changedSinceLastReset = false;
+       }
+
+       public boolean hasChangedSinceLastReset() {
+               return changedSinceLastReset;
+       }
+
+       /**
+        * Record something that needs verifying when we believe the type system is complete. Used for things that can't be verified as
+        * we go along - for example some recursive type variable references (pr133307)
+        */
+       public void recordNecessaryCheck(IVerificationRequired verification) {
+               if (verificationList == null)
+                       verificationList = new ArrayList();
+               verificationList.add(verification);
+       }
+
+       /**
+        * Called when type bindings are complete - calls all registered verification objects in turn.
+        */
+       public void verify() {
+               if (verificationList == null)
+                       return;
+               for (Iterator iter = verificationList.iterator(); iter.hasNext();) {
+                       IVerificationRequired element = (IVerificationRequired) iter.next();
+                       element.verify();
+               }
+               verificationList = null;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/CustomMungerFactory.java b/org.aspectj.matcher/src/org/aspectj/weaver/CustomMungerFactory.java
new file mode 100644 (file)
index 0000000..3ff37a4
--- /dev/null
@@ -0,0 +1,58 @@
+/* *******************************************************************
+ * Copyright (c) 2007 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Linton Ye https://bugs.eclipse.org/bugs/show_bug.cgi?id=193065
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.util.Collection;
+
+/**
+ * <p>
+ * This interface is introduced to support tools like PointcutDoctor.
+ * </p>
+ * <p>
+ * A CustomMungerFactory is used to create ShadowMungers and/or
+ * ConcreteTypeMungers so that an extender can extract extra information during
+ * the weaving process.
+ * </p>
+ * <p>
+ * A CustomMungerFactory is assigned to a weaver through its AjCompiler in
+ * extenders' code, and gets invoked by the weaver right before the weaving
+ * starts. The custom shadow/type mungers being created will be added into the
+ * shadow/type munger list in the weaver and participate the weaving process.
+ * For example, the match method of each custom shadow munger will be called
+ * against each shadow.
+ * </p>
+ * @author lintonye
+ * 
+ */
+public interface CustomMungerFactory {
+
+       /**
+        * @param aspectType
+        * @return a Collection&lt;ShadowMunger&gt; of custom shadow mungers for the
+        *         given aspect
+        */
+       public Collection/* ShadowMunger */createCustomShadowMungers(
+                       ResolvedType aspectType);
+
+       /**
+        * @param aspectType
+        * @return a Collection&lt;ConcreteTypeMunger&gt; of custom type mungers for the
+        *         given aspect
+        */
+       public Collection/* ConcreteTypeMunger */createCustomTypeMungers(
+                       ResolvedType aspectType);
+       
+       public Collection/* ShadowMunger */getAllCreatedCustomShadowMungers();
+
+       public Collection/* ConcreteTypeMunger */getAllCreatedCustomTypeMungers();
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Dump.java b/org.aspectj.matcher/src/org/aspectj/weaver/Dump.java
new file mode 100644 (file)
index 0000000..bdc6ec4
--- /dev/null
@@ -0,0 +1,506 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Matthew Webster 
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.lang.ref.WeakReference;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHolder;
+import org.aspectj.bridge.Version;
+import org.aspectj.weaver.tools.Trace;
+import org.aspectj.weaver.tools.TraceFactory;
+import org.aspectj.weaver.tools.Traceable;
+
+/**
+ * @author websterm
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class Dump {
+
+       public final static String DUMP_CONDITION_PROPERTY = "org.aspectj.weaver.Dump.condition";
+       public final static String DUMP_DIRECTORY_PROPERTY = "org.aspectj.dump.directory";
+
+       /* Format for unique filename based on date & time */
+       private static final String FILENAME_PREFIX = "ajcore";
+//     private static final DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); 
+//     private static final DateFormat timeFormat = new SimpleDateFormat("HHmmss.SSS"); 
+       private static final String FILENAME_SUFFIX = "txt";
+       
+       public static final String UNKNOWN_FILENAME = "Unknown";
+       public static final String DUMP_EXCLUDED = "Excluded";
+       public static final String NULL_OR_EMPTY = "Empty";
+       
+       private static Class exceptionClass;
+       private static IMessage.Kind conditionKind = IMessage.ABORT;
+       private static File directory = new File(".");
+
+       private String reason;
+       private String fileName;
+       private PrintStream print;
+       
+       private static String[] savedCommandLine;
+       private static List savedFullClasspath;
+       private static IMessageHolder savedMessageHolder;
+       
+       private static Map nodes = new WeakHashMap();
+       private static String lastDumpFileName = UNKNOWN_FILENAME;
+       
+       private static boolean preserveOnNextReset = false;
+       
+       private static Trace trace = TraceFactory.getTraceFactory().getTrace(Dump.class);
+       
+       /**
+        * for testing only, so that we can verify dump contents
+        * after compilation has completely finished
+        */
+       public static void preserveOnNextReset() {
+               preserveOnNextReset = true;             
+       }
+       
+       public static void reset() {
+               if (preserveOnNextReset) {
+                       preserveOnNextReset = false;
+                       return;
+               }
+               else {
+                       nodes.clear();
+                       savedMessageHolder = null;
+               }
+       }
+       
+       
+       /*
+        * Dump methods
+        */
+       public static String dump (String reason) {
+               String fileName = UNKNOWN_FILENAME;
+               Dump dump = null;
+               try {
+                       dump = new Dump(reason);
+                       fileName = dump.getFileName();
+                       dump.dumpDefault();
+               }
+               finally {
+                       if (dump != null) dump.close();
+               }
+               return fileName;
+       }
+       
+       public static String dumpWithException (Throwable th) {
+               return dumpWithException(savedMessageHolder,th);
+       }
+       
+       public static String dumpWithException (IMessageHolder messageHolder, Throwable th) {
+               if (trace.isTraceEnabled()) trace.enter("dumpWithException",null,new Object[] {messageHolder, th});
+
+               String fileName = UNKNOWN_FILENAME;
+               Dump dump = null;
+               try {
+                       dump = new Dump(th.getClass().getName());
+                       fileName = dump.getFileName();
+                       dump.dumpException(messageHolder,th);
+               }
+               finally {
+                       if (dump != null) dump.close();
+               }
+               
+               if (trace.isTraceEnabled()) trace.exit("dumpWithException",fileName);
+               return fileName;
+       }
+
+       public static String dumpOnExit () {
+               return dumpOnExit(savedMessageHolder, false);
+       }
+
+       public static String dumpOnExit (IMessageHolder messageHolder, boolean reset) {
+               if (trace.isTraceEnabled()) trace.enter("dumpOnExit",null,messageHolder);
+               String fileName = UNKNOWN_FILENAME;
+       
+               if (!shouldDumpOnExit(messageHolder)) {
+                       fileName = DUMP_EXCLUDED;
+               }
+               else {
+                       Dump dump = null;
+                       try {
+                               dump = new Dump(conditionKind.toString());
+                               fileName = dump.getFileName();
+                               dump.dumpDefault(messageHolder);
+                       }
+                       finally {
+                               if (dump != null) dump.close();
+                       }
+               }
+               
+               if (reset) messageHolder.clearMessages();
+
+               if (trace.isTraceEnabled()) trace.exit("dumpOnExit",fileName);
+               return fileName;
+       }
+
+       private static boolean shouldDumpOnExit (IMessageHolder messageHolder) {
+               if (trace.isTraceEnabled()) trace.enter("shouldDumpOnExit",null,messageHolder);
+               if (trace.isTraceEnabled()) trace.event("shouldDumpOnExit",null,conditionKind);
+               boolean result = (messageHolder == null) || messageHolder.hasAnyMessage(conditionKind,true);
+               
+               if (trace.isTraceEnabled()) trace.exit("shouldDumpOnExit",result);
+               return result;
+       }
+
+       /*
+        * Dump configuration
+        */
+       public static void setDumpOnException (boolean b) {
+               if (b) {
+                       exceptionClass = java.lang.Throwable.class;
+               }
+               else {
+                       exceptionClass = null;
+               }
+       }
+       
+       public static boolean setDumpDirectory (String directoryName) {
+               if (trace.isTraceEnabled()) trace.enter("setDumpDirectory",null,directoryName);
+               boolean success = false;
+
+               File newDirectory = new File(directoryName);
+               if (newDirectory.exists()) {
+                       directory = newDirectory;
+                       success = true;
+               }
+               
+               if (trace.isTraceEnabled()) trace.exit("setDumpDirectory",success);
+               return success;
+               
+       }
+       
+       public static boolean getDumpOnException () {
+               return (exceptionClass != null);
+       }
+
+       public static boolean setDumpOnExit (IMessage.Kind condition) {
+               if (trace.isTraceEnabled()) trace.event("setDumpOnExit",null,condition);
+
+               conditionKind = condition;
+               return true;
+       }
+
+       public static boolean setDumpOnExit (String condition) {
+               for (Iterator i = IMessage.KINDS.iterator(); i.hasNext();) {
+                       IMessage.Kind kind = (IMessage.Kind)i.next();
+                       if (kind.toString().equals(condition)) {
+                               return setDumpOnExit(kind);
+                       }
+               }
+               return false;
+       }
+       
+       public static IMessage.Kind getDumpOnExit () {
+               return conditionKind; 
+       }
+       
+       public static String getLastDumpFileName () {
+               return lastDumpFileName;
+       }
+
+       /*
+        * Dump registration
+        */
+       public static void saveCommandLine (String[] args) {
+               savedCommandLine = new String[args.length];
+               System.arraycopy(args,0,savedCommandLine,0,args.length); 
+       }
+
+       public static void saveFullClasspath (List list) {
+               savedFullClasspath = list;
+       }
+
+       public static void saveMessageHolder (IMessageHolder holder) {
+               savedMessageHolder = holder;
+       }
+
+       public static void registerNode (Class module, INode newNode) {
+               if (trace.isTraceEnabled()) trace.enter("registerNode",null,new Object[] { module, newNode} );
+
+               nodes.put(newNode,new WeakReference(newNode));
+
+               if (trace.isTraceEnabled()) trace.exit("registerNode",nodes.size());
+       }
+       
+       /*
+        * Dump methods
+        */
+       private Dump (String reason) {
+               if (trace.isTraceEnabled()) trace.enter("<init>",this,reason);
+
+               this.reason = reason;
+               
+               openDump();
+               dumpAspectJProperties();
+               dumpDumpConfiguration();
+               
+               if (trace.isTraceEnabled()) trace.exit("<init>",this);
+       }
+
+       public String getFileName() {
+               return fileName;
+       }
+       
+       private void dumpDefault () {
+               dumpDefault(savedMessageHolder);
+       }
+               
+       private void dumpDefault (IMessageHolder holder) {
+               dumpSytemProperties();
+               dumpCommandLine();
+               dumpFullClasspath();
+               dumpCompilerMessages(holder);
+               
+               dumpNodes();
+       }
+
+       private void dumpNodes() {
+
+               /*
+                * Dump registered nodes
+                */
+               IVisitor dumpVisitor = new IVisitor() {
+
+                       public void visitObject (Object obj) {
+                               println(formatObj(obj));
+                       }
+
+                       public void visitList (List list) {
+                               println(list);
+                       }
+               };
+               Set keys = nodes.keySet();
+               for (Iterator i = keys.iterator(); i.hasNext();) {
+                       Object module = i.next();
+//                     INode dumpNode = (INode)nodes.get(module);
+                       INode dumpNode = (INode)module;
+                       println("---- " + formatObj(dumpNode) + " ----");
+                       try {
+                               dumpNode.accept(dumpVisitor); 
+                       }
+                       catch (Exception ex) {
+                               trace.error(formatObj(dumpNode).toString(),ex);
+                       }
+               }
+       }
+       
+       private void dumpException (IMessageHolder messageHolder, Throwable th) {
+               println("---- Exception Information ---");
+               println(th);
+               dumpDefault(messageHolder);
+       }
+       
+       private void dumpAspectJProperties () {
+               println("---- AspectJ Properties ---");
+               println("AspectJ Compiler " + Version.text + " built on " + Version.time_text);
+       }
+       
+       private void dumpDumpConfiguration () {
+               println("---- Dump Properties ---");
+               println("Dump file: " + fileName);
+               println("Dump reason: " + reason);
+               println("Dump on exception: " + (exceptionClass != null));
+               println("Dump at exit condition: " + conditionKind);
+       }
+       
+       private void dumpFullClasspath () {
+               println("---- Full Classpath ---");
+               if (savedFullClasspath != null && savedFullClasspath.size() > 0) {
+                       for (Iterator iter = savedFullClasspath.iterator(); iter.hasNext(); ) {
+                               String fileName = (String)iter.next();
+                               File file = new File(fileName);
+                               println(file);
+                       }
+               }
+               else {
+                       println(NULL_OR_EMPTY);
+               }
+       }
+       
+       private void dumpSytemProperties () {
+               println("---- System Properties ---");
+               Properties props = System.getProperties();
+               println(props);
+       }
+       
+       private void dumpCommandLine () {
+               println("---- Command Line ---");
+               println(savedCommandLine);
+       }
+       
+       private void dumpCompilerMessages (IMessageHolder messageHolder) {
+               println("---- Compiler Messages ---");
+               if (messageHolder != null) for (Iterator i = messageHolder.getUnmodifiableListView().iterator(); i.hasNext(); ) {
+                       IMessage message = (IMessage)i.next();
+                       println(message.toString());
+               }
+               else {
+                       println(NULL_OR_EMPTY);
+               }
+       }
+
+       /*
+        * Dump output
+        */     
+       private void openDump () {
+               if (print != null) return;
+               
+               Date now = new Date();
+               fileName = FILENAME_PREFIX + "."
+                       + new SimpleDateFormat("yyyyMMdd").format(now) + "."
+                       + new SimpleDateFormat("HHmmss.SSS").format(now) + "."
+                       + FILENAME_SUFFIX;
+               try {
+                       File file = new File(directory,fileName);
+                       print = new PrintStream(new FileOutputStream(file),true);
+                       trace.info("Dumping to " + file.getAbsolutePath());
+               }
+               catch (Exception ex) {
+                       print = System.err;
+                       trace.info("Dumping to stderr");
+                       fileName = UNKNOWN_FILENAME;
+               }
+               
+               lastDumpFileName = fileName;
+       }
+       
+       public void close () {
+               print.close();
+       }
+       
+       private void println (Object obj) {
+               print.println(obj);
+       }
+       
+       private void println (Object[] array) {
+               if (array == null) {
+                       println(NULL_OR_EMPTY);
+                       return;
+               }
+               
+               for (int i = 0; i < array.length; i++) {
+                       print.println(array[i]);
+               }
+       }
+       
+       private void println (Properties props) {
+               Iterator iter = props.keySet().iterator();
+               while (iter.hasNext()) {
+                       String key = (String)iter.next();
+                       String value = props.getProperty(key);
+                       print.println(key + "=" + value);
+               }
+       }
+       
+       private void println (Throwable th) {
+               th.printStackTrace(print);
+       }
+       
+       private void println (File file) {
+               print.print(file.getAbsolutePath());
+               if (!file.exists()) {
+                       println("(missing)");                   
+               }
+               else if (file.isDirectory()) {
+                       int count = file.listFiles().length;
+                       println("(" + count + " entries)");                     
+               }
+               else {
+                       println("(" + file.length() + " bytes)");                       
+               }
+       }
+       
+       private void println (List list) {
+               if (list == null || list.isEmpty()) println(NULL_OR_EMPTY);
+               else for (Iterator i = list.iterator(); i.hasNext();) {
+            Object o = i.next();
+            if (o instanceof Exception) {
+                println((Exception)o);
+            } else {
+               println(o.toString());
+            }
+               }
+       }
+       
+       private static Object formatObj(Object obj) {
+               
+               /* These classes have a safe implementation of toString() */
+               if (obj == null
+                               || obj instanceof String
+                           || obj instanceof Number
+                           || obj instanceof Boolean
+                           || obj instanceof Exception
+                           || obj instanceof Character
+                           || obj instanceof Class
+                           || obj instanceof File
+                           || obj instanceof StringBuffer
+                           || obj instanceof URL
+                   ) return obj;
+               else try {
+                       
+                       /* Classes can provide an alternative implementation of toString() */
+                       if (obj instanceof Traceable) {
+                               Traceable t = (Traceable)obj;
+                               return t.toTraceString();
+                       }
+                       
+                       /* Use classname@hashcode */
+                       else return obj.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(obj));
+               
+               /* Object.hashCode() can be override and may thow an exception */       
+               } catch (Exception ex) {
+                       return obj.getClass().getName() + "@FFFFFFFF";
+               }
+       }
+       
+       static {
+               String exceptionName = System.getProperty("org.aspectj.weaver.Dump.exception","true");
+               if (!exceptionName.equals("false")) setDumpOnException(true);
+               
+               String conditionName = System.getProperty(DUMP_CONDITION_PROPERTY);
+               if (conditionName != null) setDumpOnExit(conditionName);
+               
+               String directoryName = System.getProperty(DUMP_DIRECTORY_PROPERTY);
+               if (directoryName != null) setDumpDirectory(directoryName);
+       }
+
+       public interface INode {
+               
+               public void accept (IVisitor visior);
+               
+       }
+
+       public interface IVisitor {
+               
+               public void visitObject (Object s);
+               public void visitList (List list);
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/EnumAnnotationValue.java b/org.aspectj.matcher/src/org/aspectj/weaver/EnumAnnotationValue.java
new file mode 100644 (file)
index 0000000..c29709c
--- /dev/null
@@ -0,0 +1,37 @@
+/* *******************************************************************
+ * Copyright (c) 2006 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement IBM     initial implementation 
+ * ******************************************************************/
+ package org.aspectj.weaver;
+
+public class EnumAnnotationValue extends AnnotationValue {
+
+       private String type;
+       private String value;
+       
+       public EnumAnnotationValue(String type,String value) {
+               super(AnnotationValue.ENUM_CONSTANT);
+               this.type = type;
+               this.value = value;
+       }
+       
+       public String getType() {
+               return type;
+       }
+       
+       public String stringify() {
+               return value;
+       }       
+       
+       public String toString() {
+               return value;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ExposeTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/ExposeTypeMunger.java
new file mode 100644 (file)
index 0000000..486ddbe
--- /dev/null
@@ -0,0 +1,30 @@
+/* *******************************************************************
+ * Copyright (c) 2007 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement, IBM       initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+/**
+ * Special kind of privileged access munger which exposes a type to be public.
+ */
+public class ExposeTypeMunger extends PrivilegedAccessMunger {
+
+       public ExposeTypeMunger(UnresolvedType typeToExpose) {
+               super(new ResolvedMemberImpl(Member.STATIC_INITIALIZATION, typeToExpose, 0, ResolvedType.VOID, "<clinit>", UnresolvedType.NONE));
+       }
+
+       public String toString() {
+               return "ExposeTypeMunger("+getSignature().getDeclaringType().getName()+")";
+       }
+
+       public String getExposedTypeSignature() {
+               return getSignature().getDeclaringType().getSignature();
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/GeneratedReferenceTypeDelegate.java b/org.aspectj.matcher/src/org/aspectj/weaver/GeneratedReferenceTypeDelegate.java
new file mode 100644 (file)
index 0000000..88e8c87
--- /dev/null
@@ -0,0 +1,158 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.util.Collection;
+
+import org.aspectj.weaver.patterns.PerClause;
+
+/**
+ * A delegate that can sit in the ReferenceType instance created for an aspect generated from aop.xml. Only answers the minimal set
+ * of information required as the type is processed.
+ * 
+ * @author Andy Clement
+ */
+public class GeneratedReferenceTypeDelegate extends AbstractReferenceTypeDelegate {
+
+       private ResolvedType superclass;
+
+       public GeneratedReferenceTypeDelegate(ReferenceType backing) {
+               super(backing, false);
+       }
+
+       public void addAnnotation(AnnotationAJ annotationX) {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public boolean isAspect() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public boolean isAnnotationStyleAspect() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public boolean isInterface() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public boolean isEnum() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public boolean isAnnotation() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public boolean isAnnotationWithRuntimeRetention() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public boolean isAnonymous() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public boolean isNested() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public ResolvedType getOuterClass() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public String getRetentionPolicy() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public boolean canAnnotationTargetType() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public AnnotationTargetKind[] getAnnotationTargetKinds() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public boolean isGeneric() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public String getDeclaredGenericSignature() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public boolean hasAnnotation(UnresolvedType ofType) {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public AnnotationAJ[] getAnnotations() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public ResolvedType[] getAnnotationTypes() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public ResolvedMember[] getDeclaredFields() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public ResolvedType[] getDeclaredInterfaces() {
+               return ResolvedType.NONE;
+       }
+
+       public ResolvedMember[] getDeclaredMethods() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public ResolvedMember[] getDeclaredPointcuts() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public PerClause getPerClause() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public Collection getDeclares() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public Collection getTypeMungers() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public Collection getPrivilegedAccesses() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public int getModifiers() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public void setSuperclass(ResolvedType superclass) {
+               this.superclass = superclass;
+       }
+
+       public ResolvedType getSuperclass() {
+               return this.superclass;
+       }
+
+       public WeaverStateInfo getWeaverState() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public TypeVariable[] getTypeVariables() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+       public void ensureDelegateConsistent() {
+               throw new UnsupportedOperationException("Not supported for GeneratedReferenceTypeDelegate");
+       }
+
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/IClassFileProvider.java b/org.aspectj.matcher/src/org/aspectj/weaver/IClassFileProvider.java
new file mode 100644 (file)
index 0000000..ead81da
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.weaver;
+
+import java.util.Iterator;
+
+/**
+ * @author colyer
+ *
+ * Clients implementing the IClassFileProvider can have a set of class files under 
+ * their control woven by a weaver, by calling the weave(IClassFileProvider source) method.
+ * The contract is that a call to getRequestor().acceptResult() is providing a result for
+ * the class file most recently returned from the getClassFileIterator().
+ */
+public interface IClassFileProvider {
+       
+       /**
+        * Answer an iterator that can be used to iterate over a set of UnwovenClassFiles to
+        * be woven. During a weave, this method may be called multiple times.  
+        * @return iterator over UnwovenClassFiles.
+        */
+       Iterator getClassFileIterator();
+       
+       /**
+        * The client to which the woven results should be returned.
+        */
+       IWeaveRequestor getRequestor();
+
+    /**
+     * @return true if weaver should only do some internal munging as the one needed
+     * for @AspectJ aspectOf methods creation
+     */
+    boolean isApplyAtAspectJMungersOnly();
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/IClassWeaver.java b/org.aspectj.matcher/src/org/aspectj/weaver/IClassWeaver.java
new file mode 100644 (file)
index 0000000..679d0fa
--- /dev/null
@@ -0,0 +1,29 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+/**
+ * An IClassWeaver is initialized with a class (a type, really, but let's ignore that for now)
+ * and a world, and has one method that actually weaves the contents of the world into the class
+ * implementation.
+ */
+
+public interface IClassWeaver {
+       
+    /** perform the weaving.
+     * 
+     * @return <code>true</code> if the class is changed by the weaving, <code>false</code> otherwise.
+     */
+    boolean weave();
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ICrossReferenceHandler.java b/org.aspectj.matcher/src/org/aspectj/weaver/ICrossReferenceHandler.java
new file mode 100644 (file)
index 0000000..e38338a
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.weaver;
+
+import org.aspectj.bridge.ISourceLocation;
+
+/**
+ * Clients can pass a single cross-reference handler to the weaver on construction of a BcelWorld. Any cross-references detected
+ * during munging will be notified to the handler.
+ */
+public interface ICrossReferenceHandler {
+
+       void addCrossReference(ISourceLocation from, ISourceLocation to, String kind, boolean runtimeTest);
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/IEclipseSourceContext.java b/org.aspectj.matcher/src/org/aspectj/weaver/IEclipseSourceContext.java
new file mode 100644 (file)
index 0000000..10d0258
--- /dev/null
@@ -0,0 +1,16 @@
+/********************************************************************
+ * Copyright (c) 2006 Contributors. All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: IBM Corporation - initial API and implementation 
+ *                              Helen Hawkins   - iniital version
+ *******************************************************************/
+package org.aspectj.weaver;
+
+
+public interface IEclipseSourceContext extends ISourceContext {
+       public void removeUnnecessaryProblems(Member method, int problemLineNumber);
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/IHasPosition.java b/org.aspectj.matcher/src/org/aspectj/weaver/IHasPosition.java
new file mode 100644 (file)
index 0000000..e47e09b
--- /dev/null
@@ -0,0 +1,33 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+public interface IHasPosition {
+       /**
+        * The starting index of this location in the character stream.
+        */
+    int getStart();
+    
+    /**
+     * The ending index of this location in the character stream
+     * 
+     * This points to the last character in this token.
+     * 
+     * If a location truly had no contents, then start == end + 1.  We don't recommend this.
+     */
+    int getEnd();
+//
+//     String getFileName();
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/IHasSourceLocation.java b/org.aspectj.matcher/src/org/aspectj/weaver/IHasSourceLocation.java
new file mode 100644 (file)
index 0000000..b070d90
--- /dev/null
@@ -0,0 +1,21 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import org.aspectj.bridge.ISourceLocation;
+
+public interface IHasSourceLocation extends IHasPosition {
+       ISourceContext getSourceContext();
+       ISourceLocation getSourceLocation();
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ISourceContext.java b/org.aspectj.matcher/src/org/aspectj/weaver/ISourceContext.java
new file mode 100644 (file)
index 0000000..dfaab8d
--- /dev/null
@@ -0,0 +1,23 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import org.aspectj.bridge.ISourceLocation;
+
+public interface ISourceContext {
+       public ISourceLocation makeSourceLocation(IHasPosition position);
+       public ISourceLocation makeSourceLocation(int line, int offset);
+       public int getOffset();
+       public void tidy();
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/IUnwovenClassFile.java b/org.aspectj.matcher/src/org/aspectj/weaver/IUnwovenClassFile.java
new file mode 100644 (file)
index 0000000..289c20c
--- /dev/null
@@ -0,0 +1,26 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+/**
+ * History: 246125
+ * @author Andy Clement
+ */
+public interface IUnwovenClassFile {
+
+       String getFilename();
+
+       String getClassName();
+
+       byte[] getBytes();
+
+       char[] getClassNameAsChars();
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/IWeaveRequestor.java b/org.aspectj.matcher/src/org/aspectj/weaver/IWeaveRequestor.java
new file mode 100644 (file)
index 0000000..13d8b95
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.weaver;
+
+
+/**
+ * @author colyer
+ * 
+ *         This interface is implemented by clients driving weaving through the IClassFileProvider interface. It is used by the
+ *         weaver to return woven class file results back to the client. The client can correlate weave results with inputs since it
+ *         knows the last UnwovenClassFile returned by its iterator.
+ */
+public interface IWeaveRequestor {
+
+       /*
+        * A class file resulting from a weave (yes, even though the type name says "unwoven"...).
+        */
+       void acceptResult(IUnwovenClassFile result);
+
+       // various notifications to the requestor about our progress...
+       void processingReweavableState();
+
+       void addingTypeMungers();
+
+       void weavingAspects();
+
+       void weavingClasses();
+
+       void weaveCompleted();
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/IWeavingSupport.java b/org.aspectj.matcher/src/org/aspectj/weaver/IWeavingSupport.java
new file mode 100644 (file)
index 0000000..57bf82b
--- /dev/null
@@ -0,0 +1,44 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement     initial implementation 
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import org.aspectj.weaver.ast.Var;
+import org.aspectj.weaver.patterns.PerClause;
+import org.aspectj.weaver.patterns.Pointcut;
+
+/**
+ * Encapsulates operations that a world will need to support if it is actually going to modify bytecode rather than just match
+ * against it. {@see BcelWeavingSupport}
+ * 
+ * @author Andy Clement
+ */
+public interface IWeavingSupport {
+
+       public Advice createAdviceMunger(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member signature);
+
+       public abstract ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField);
+
+       public abstract ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField);
+
+       /**
+        * Register a munger for perclause @AJ aspect so that we add aspectOf(..) to them as needed
+        * 
+        * @see org.aspectj.weaver.bcel.BcelWorld#makePerClauseAspect(ResolvedType, org.aspectj.weaver.patterns.PerClause.Kind)
+        */
+       public abstract ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, PerClause.Kind kind);
+
+       public abstract ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType);
+
+       public ConcreteTypeMunger createAccessForInlineMunger(ResolvedType inAspect);
+
+       public Var makeCflowAccessVar(ResolvedType formalType, Member cflowField, int arrayIndex);
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/IntMap.java b/org.aspectj.matcher/src/org/aspectj/weaver/IntMap.java
new file mode 100644 (file)
index 0000000..6f37f20
--- /dev/null
@@ -0,0 +1,147 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class IntMap {
+       // public static final IntMap EMPTY = new IntMap(0) {
+       // public boolean directlyInAdvice() { return true; }
+       // public ShadowMunger getEnclosingAdvice() { return null; } //XXX possible
+       // };
+
+       // XXX begin hack to avoid a signature refactoring in Pointcut
+       private ResolvedType concreteAspect;
+       private ShadowMunger enclosingAdvice;
+       private List/* ResolvedPointcutDefinition */enclosingDefinition = new ArrayList();
+
+       public void pushEnclosingDefinition(ResolvedPointcutDefinition def) {
+               enclosingDefinition.add(def);
+       }
+
+       public void popEnclosingDefinitition() {
+               enclosingDefinition.remove(enclosingDefinition.size() - 1);
+       }
+
+       public ResolvedPointcutDefinition peekEnclosingDefinition() {
+               if (enclosingDefinition.size() == 0)
+                       return null;
+               return (ResolvedPointcutDefinition) enclosingDefinition.get(enclosingDefinition.size() - 1);
+       }
+
+       public boolean directlyInAdvice() {
+               return enclosingDefinition.isEmpty();
+       }
+
+       public ShadowMunger getEnclosingAdvice() {
+               return enclosingAdvice;
+       }
+
+       public void setEnclosingAdvice(ShadowMunger advice) {
+               this.enclosingAdvice = advice;
+       }
+
+       public Member getAdviceSignature() {
+               if (enclosingAdvice instanceof Advice)
+                       return ((Advice) enclosingAdvice).getSignature();
+               else
+                       return null;
+       }
+
+       public ResolvedType getConcreteAspect() {
+               return concreteAspect;
+       }
+
+       public void setConcreteAspect(ResolvedType concreteAspect) {
+               this.concreteAspect = concreteAspect;
+       }
+
+       public void copyContext(IntMap bindings) {
+               this.enclosingAdvice = bindings.enclosingAdvice;
+               this.enclosingDefinition = bindings.enclosingDefinition;
+               this.concreteAspect = bindings.concreteAspect;
+       }
+
+       // XXX end hack to avoid a signature refactoring in Pointcut
+
+       private static final int MISSING = -1;
+
+       private int[] map;
+
+       private IntMap(int[] map) {
+               this.map = map;
+       }
+
+       public IntMap() {
+               map = new int[0];
+       }
+
+       public IntMap(int initialCapacity) {
+               map = new int[initialCapacity];
+               for (int i = 0; i < initialCapacity; i++) {
+                       map[i] = MISSING;
+               }
+       }
+
+       public void put(int key, int val) {
+               /* assert (val >= 0 && key >= 0) */
+               if (key >= map.length) {
+                       int[] tmp = new int[key * 2 + 1]; // ??? better expansion function
+                       System.arraycopy(map, 0, tmp, 0, map.length);
+                       for (int i = map.length, len = tmp.length; i < len; i++)
+                               tmp[i] = MISSING;
+                       map = tmp;
+               }
+               map[key] = val;
+       }
+
+       public int get(int key) {
+               return map[key];
+       }
+
+       public boolean hasKey(int key) {
+               return (key < map.length && map[key] != MISSING);
+       }
+
+       // ---- factory methods
+
+       public static IntMap idMap(int size) {
+               int[] map = new int[size];
+               for (int i = 0; i < size; i++) {
+                       map[i] = i;
+               }
+               return new IntMap(map);
+       }
+
+       // ---- from object
+
+       public String toString() {
+               StringBuffer buf = new StringBuffer("[");
+               boolean seenFirst = false;
+               for (int i = 0, len = map.length; i < len; i++) {
+                       if (map[i] != MISSING) {
+                               if (seenFirst) {
+                                       buf.append(", ");
+                               }
+                               seenFirst = true;
+                               buf.append(i);
+                               buf.append(" -> ");
+                               buf.append(map[i]);
+                       }
+               }
+               buf.append("]");
+               return buf.toString();
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Iterators.java b/org.aspectj.matcher/src/org/aspectj/weaver/Iterators.java
new file mode 100644 (file)
index 0000000..1e5e6e6
--- /dev/null
@@ -0,0 +1,264 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+public final class Iterators {
+
+       /**
+        * Private constructor, nobody should ever make one of these
+        */
+       private Iterators() {
+       }
+
+       /**
+        * A getter represents a mapping function from Object to Iterator
+        */
+       public interface Getter {
+               Iterator get(Object target);
+       }
+
+       /**
+        * A filter represents a mapping function from Iterator to Iterator
+        */
+       public interface Filter {
+               Iterator filter(Iterator in);
+       }
+
+       /**
+        * Create a new filter F that, when wrapped around another iterator I, creates a new iterator I' that will return only those
+        * values of I that have not yet been returned by I', discarding duplicates.
+        */
+       public static Filter dupFilter() {
+               return new Filter() {
+                       final Set seen = new HashSet(); // should have weak ptrs?
+
+                       public Iterator filter(final Iterator in) {
+                               return new Iterator() {
+                                       boolean fresh = false;
+                                       Object peek;
+
+                                       public boolean hasNext() {
+                                               if (fresh)
+                                                       return true;
+                                               while (true) {
+                                                       if (!in.hasNext())
+                                                               return false;
+                                                       peek = in.next();
+                                                       if (!seen.contains(peek)) {
+                                                               return fresh = true;
+                                                       } else {
+                                                               peek = null; // garbage collection
+                                                       }
+                                               }
+                                       }
+
+                                       public Object next() {
+                                               if (!hasNext())
+                                                       throw new NoSuchElementException();
+                                               Object ret = peek;
+                                               peek = null;
+                                               fresh = false;
+                                               return ret;
+                                       }
+
+                                       public void remove() {
+                                               throw new UnsupportedOperationException();
+                                       }
+                               };
+                       }
+               };
+       }
+
+       /**
+        * Creates an iterator that will return the elements of a specified array, in order. Like Arrays.asList(o).iterator(), without
+        * all that pesky safety.
+        */
+
+       public static Iterator array(final Object[] o) {
+               return new Iterator() {
+                       int i = 0;
+                       int len = (o == null) ? 0 : o.length;
+
+                       public boolean hasNext() {
+                               return i < len;
+                       }
+
+                       public Object next() {
+                               if (i < len) {
+                                       return o[i++];
+                               } else {
+                                       throw new NoSuchElementException();
+                               }
+                       }
+
+                       public void remove() {
+                               throw new UnsupportedOperationException();
+                       }
+               };
+       }
+
+       /**
+        * creates an iterator I based on a base iterator A and a getter G. I returns, in order, forall (i in I), G(i).
+        */
+       public static Iterator mapOver(final Iterator a, final Getter g) {
+               return new Iterator() {
+                       Iterator delegate = new Iterator() {
+                               public boolean hasNext() {
+                                       if (!a.hasNext())
+                                               return false;
+                                       Object o = a.next();
+                                       delegate = append1(g.get(o), this);
+                                       return delegate.hasNext();
+                               }
+
+                               public Object next() {
+                                       if (!hasNext())
+                                               throw new UnsupportedOperationException();
+                                       return delegate.next();
+                               }
+
+                               public void remove() {
+                                       throw new UnsupportedOperationException();
+                               }
+                       };
+
+                       public boolean hasNext() {
+                               return delegate.hasNext();
+                       }
+
+                       public Object next() {
+                               return delegate.next();
+                       }
+
+                       public void remove() {
+                               throw new UnsupportedOperationException();
+                       }
+               };
+       }
+
+       /**
+        * creates an iterator I based on a base iterator A and a getter G. I returns, in order, forall (i in I) i :: forall (i' in
+        * g(i)) recur(i', g)
+        */
+       public static Iterator recur(final Object a, final Getter g) {
+               return new Iterator() {
+                       Iterator delegate = one(a);
+
+                       public boolean hasNext() {
+                               return delegate.hasNext();
+                       }
+
+                       public Object next() {
+                               Object next = delegate.next();
+                               delegate = append(g.get(next), delegate);
+                               return next;
+                       }
+
+                       public void remove() {
+                               throw new UnsupportedOperationException();
+                       }
+               };
+       }
+
+       /**
+        * creates an iterator I based on base iterators A and B. Returns the elements returned by A followed by those returned by B. If
+        * B is empty, simply returns A, and if A is empty, simply returns B. Do NOT USE if b.hasNext() is not idempotent.
+        */
+       public static Iterator append(final Iterator a, final Iterator b) {
+               if (!b.hasNext())
+                       return a;
+               return append1(a, b);
+       }
+
+       /**
+        * creates an iterator I based on base iterators A and B. Returns the elements returned by A followed by those returned by B. If
+        * A is empty, simply returns B. Guaranteed not to call B.hasNext() until A is empty.
+        */
+       public static Iterator append1(final Iterator a, final Iterator b) {
+               if (!a.hasNext())
+                       return b;
+               return new Iterator() {
+                       public boolean hasNext() {
+                               return a.hasNext() || b.hasNext();
+                       }
+
+                       public Object next() {
+                               if (a.hasNext())
+                                       return a.next();
+                               if (b.hasNext())
+                                       return b.next();
+                               throw new NoSuchElementException();
+                       }
+
+                       public void remove() {
+                               throw new UnsupportedOperationException();
+                       }
+               };
+       }
+
+       /**
+        * creates an iterator I based on a base iterator A and an object O. Returns the elements returned by A, followed by O.
+        */
+       public static Iterator snoc(final Iterator first, final Object last) {
+               return new Iterator() {
+                       Object last1 = last;
+
+                       public boolean hasNext() {
+                               return first.hasNext() || last1 != null;
+                       }
+
+                       public Object next() {
+                               if (first.hasNext())
+                                       return first.next();
+                               else if (last1 == null)
+                                       throw new NoSuchElementException();
+                               Object ret = last1;
+                               last1 = null;
+                               return ret;
+                       }
+
+                       public void remove() {
+                               throw new UnsupportedOperationException();
+                       }
+               };
+       }
+
+       /**
+        * creates an iterator I based on an object O. Returns O, once.
+        */
+       public static Iterator one(final Object it) {
+               return new Iterator() {
+                       boolean avail = true;
+
+                       public boolean hasNext() {
+                               return avail;
+                       }
+
+                       public Object next() {
+                               if (!avail)
+                                       throw new NoSuchElementException();
+                               avail = false;
+                               return it;
+                       }
+
+                       public void remove() {
+                               throw new UnsupportedOperationException();
+                       }
+               };
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/JoinPointSignature.java b/org.aspectj.matcher/src/org/aspectj/weaver/JoinPointSignature.java
new file mode 100644 (file)
index 0000000..399c731
--- /dev/null
@@ -0,0 +1,409 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.weaver.AjAttribute.EffectiveSignatureAttribute;
+
+/**
+ * @author colyer Instances of this class are created by
+ *         ResolvedMember.getSignatures() when collating all of the signatures
+ *         for a member. We need to create entries in the set for the "gaps" in
+ *         the hierarchy. For example:
+ * 
+ *         class A { void foo(); } 
+ * 
+ *         class B extends A {}
+ * 
+ *         Join Point : call(* B.foo())
+ * 
+ *         has signatures:
+ * 
+ *         B.foo() AND A.foo() B.foo() will be created as a
+ *         ResolvedMemberWithSubstituteDeclaringType
+ * 
+ *         Oh for a JDK 1.4 dynamic proxy.... we have to run on 1.3 :(
+ */
+public class JoinPointSignature implements ResolvedMember {
+
+       private ResolvedMember realMember;
+       private ResolvedType substituteDeclaringType;
+
+       public JoinPointSignature(ResolvedMember backing, ResolvedType aType) {
+               this.realMember = backing;
+               this.substituteDeclaringType = aType;
+       }
+
+       public UnresolvedType getDeclaringType() {
+               return substituteDeclaringType;
+       }
+
+       public int getModifiers(World world) {
+               return realMember.getModifiers(world);
+       }
+
+       public int getModifiers() {
+               return realMember.getModifiers();
+       }
+
+       public UnresolvedType[] getExceptions(World world) {
+               return realMember.getExceptions(world);
+       }
+
+       public UnresolvedType[] getExceptions() {
+               return realMember.getExceptions();
+       }
+
+       public ShadowMunger getAssociatedShadowMunger() {
+               return realMember.getAssociatedShadowMunger();
+       }
+
+       public boolean isAjSynthetic() {
+               return realMember.isAjSynthetic();
+       }
+
+       public boolean hasAnnotations() {
+               return realMember.hasAnnotations();
+       }
+
+       public boolean hasAnnotation(UnresolvedType ofType) {
+               return realMember.hasAnnotation(ofType);
+       }
+
+       public ResolvedType[] getAnnotationTypes() {
+               return realMember.getAnnotationTypes();
+       }
+
+       public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
+               return realMember.getAnnotationOfType(ofType);
+       }
+
+       public void setAnnotationTypes(UnresolvedType[] annotationtypes) {
+               realMember.setAnnotationTypes(annotationtypes);
+       }
+
+       public void addAnnotation(AnnotationAJ annotation) {
+               realMember.addAnnotation(annotation);
+       }
+
+       public boolean isBridgeMethod() {
+               return realMember.isBridgeMethod();
+       }
+
+       public boolean isVarargsMethod() {
+               return realMember.isVarargsMethod();
+       }
+
+       public boolean isSynthetic() {
+               return realMember.isSynthetic();
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               realMember.write(s);
+       }
+
+       public ISourceContext getSourceContext(World world) {
+               return realMember.getSourceContext(world);
+       }
+
+       public String[] getParameterNames() {
+               return realMember.getParameterNames();
+       }
+
+       public void setParameterNames(String[] names) {
+               realMember.setParameterNames(names);
+       }
+
+       public String[] getParameterNames(World world) {
+               return realMember.getParameterNames(world);
+       }
+
+       public EffectiveSignatureAttribute getEffectiveSignature() {
+               return realMember.getEffectiveSignature();
+       }
+
+       public ISourceLocation getSourceLocation() {
+               return realMember.getSourceLocation();
+       }
+
+       public int getEnd() {
+               return realMember.getEnd();
+       }
+
+       public ISourceContext getSourceContext() {
+               return realMember.getSourceContext();
+       }
+
+       public int getStart() {
+               return realMember.getStart();
+       }
+
+       public void setPosition(int sourceStart, int sourceEnd) {
+               realMember.setPosition(sourceStart, sourceEnd);
+       }
+
+       public void setSourceContext(ISourceContext sourceContext) {
+               realMember.setSourceContext(sourceContext);
+       }
+
+       public boolean isAbstract() {
+               return realMember.isAbstract();
+       }
+
+       public boolean isPublic() {
+               return realMember.isPublic();
+       }
+
+       public boolean isProtected() {
+               return realMember.isProtected();
+       }
+
+       public boolean isNative() {
+               return realMember.isNative();
+       }
+
+       public boolean isDefault() {
+               return realMember.isDefault();
+       }
+
+       public boolean isVisible(ResolvedType fromType) {
+               return realMember.isVisible(fromType);
+       }
+
+       public void setCheckedExceptions(UnresolvedType[] checkedExceptions) {
+               realMember.setCheckedExceptions(checkedExceptions);
+       }
+
+       public void setAnnotatedElsewhere(boolean b) {
+               realMember.setAnnotatedElsewhere(b);
+       }
+
+       public boolean isAnnotatedElsewhere() {
+               return realMember.isAnnotatedElsewhere();
+       }
+
+       public UnresolvedType getGenericReturnType() {
+               return realMember.getGenericReturnType();
+       }
+
+       public UnresolvedType[] getGenericParameterTypes() {
+               return realMember.getGenericParameterTypes();
+       }
+
+       public ResolvedMemberImpl parameterizedWith(
+                       UnresolvedType[] typeParameters, ResolvedType newDeclaringType,
+                       boolean isParameterized) {
+               return realMember.parameterizedWith(typeParameters, newDeclaringType,
+                               isParameterized);
+       }
+
+       public ResolvedMemberImpl parameterizedWith(
+                       UnresolvedType[] typeParameters, ResolvedType newDeclaringType,
+                       boolean isParameterized, List aliases) {
+               return realMember.parameterizedWith(typeParameters, newDeclaringType,
+                               isParameterized, aliases);
+       }
+
+       public void setTypeVariables(TypeVariable[] types) {
+               realMember.setTypeVariables(types);
+       }
+
+       public TypeVariable[] getTypeVariables() {
+               return realMember.getTypeVariables();
+       }
+
+       public TypeVariable getTypeVariableNamed(String name) {
+               return realMember.getTypeVariableNamed(name);
+       }
+
+       public boolean matches(ResolvedMember aCandidateMatch) {
+               return realMember.matches(aCandidateMatch);
+       }
+
+       public ResolvedMember resolve(World world) {
+               return realMember.resolve(world);
+       }
+
+       public int compareTo(Object other) {
+               return realMember.compareTo(other);
+       }
+
+       public MemberKind getKind() {
+               return realMember.getKind();
+       }
+
+       public UnresolvedType getReturnType() {
+               return realMember.getReturnType();
+       }
+
+       public UnresolvedType getType() {
+               return realMember.getType();
+       }
+
+       public String getName() {
+               return realMember.getName();
+       }
+
+       public UnresolvedType[] getParameterTypes() {
+               return realMember.getParameterTypes();
+       }
+
+       public AnnotationAJ[][] getParameterAnnotations() {
+               return realMember.getParameterAnnotations();
+       }
+
+       public ResolvedType[][] getParameterAnnotationTypes() {
+               return realMember.getParameterAnnotationTypes();
+       }
+
+       public String getSignature() {
+               return realMember.getSignature();
+       }
+
+       public int getArity() {
+               return realMember.getArity();
+       }
+
+       public String getParameterSignature() {
+               return realMember.getParameterSignature();
+       }
+
+       public boolean isCompatibleWith(Member am) {
+               return realMember.isCompatibleWith(am);
+       }
+
+       public boolean isStatic() {
+               return realMember.isStatic();
+       }
+
+       public boolean isInterface() {
+               return realMember.isInterface();
+       }
+
+       public boolean isPrivate() {
+               return realMember.isPrivate();
+       }
+
+       public boolean canBeParameterized() {
+               return realMember.canBeParameterized();
+       }
+
+       public AnnotationAJ[] getAnnotations() {
+               return realMember.getAnnotations();
+       }
+
+       public Collection getDeclaringTypes(World world) {
+               throw new UnsupportedOperationException(
+                               "Adrian doesn't think you should be calling this...");
+       }
+
+       public Iterator getJoinPointSignatures(World world) {
+               return realMember.getJoinPointSignatures(world);
+       }
+
+       public String toString() {
+               StringBuffer buf = new StringBuffer();
+               buf.append(getReturnType().getName());
+               buf.append(' ');
+               buf.append(getDeclaringType().getName());
+               buf.append('.');
+               buf.append(getName());
+               if (getKind() != FIELD) {
+                       buf.append("(");
+                       UnresolvedType[] parameterTypes = getParameterTypes();
+                       if (parameterTypes.length != 0) {
+                               buf.append(parameterTypes[0]);
+                               for (int i = 1, len = parameterTypes.length; i < len; i++) {
+                                       buf.append(", ");
+                                       buf.append(parameterTypes[i].getName());
+                               }
+                       }
+                       buf.append(")");
+               }
+               return buf.toString();
+       }
+
+       public String toGenericString() {
+               return realMember.toGenericString();
+       }
+
+       public String toDebugString() {
+               return realMember.toDebugString();
+       }
+
+       public void resetName(String newName) {
+               realMember.resetName(newName);
+       }
+
+       public void resetKind(MemberKind newKind) {
+               realMember.resetKind(newKind);
+       }
+
+       public void resetModifiers(int newModifiers) {
+               realMember.resetModifiers(newModifiers);
+       }
+
+       public void resetReturnTypeToObjectArray() {
+               realMember.resetReturnTypeToObjectArray();
+       }
+
+       public boolean equals(Object obj) {
+               if (!(obj instanceof JoinPointSignature))
+                       return false;
+               JoinPointSignature other = (JoinPointSignature) obj;
+               if (!realMember.equals(other.realMember))
+                       return false;
+               if (!substituteDeclaringType.equals(other.substituteDeclaringType))
+                       return false;
+               return true;
+       }
+
+       public int hashCode() {
+               return 17 + (37 * realMember.hashCode())
+                               + (37 * substituteDeclaringType.hashCode());
+       }
+
+       public boolean hasBackingGenericMember() {
+               return realMember.hasBackingGenericMember();
+       }
+
+       public ResolvedMember getBackingGenericMember() {
+               return realMember.getBackingGenericMember();
+       }
+
+       public void evictWeavingState() {
+               realMember.evictWeavingState();
+       }
+
+       public ResolvedMember parameterizedWith(Map m, World w) {
+               return realMember.parameterizedWith(m, w);
+       }
+
+       public String getAnnotationDefaultValue() {
+               return realMember.getAnnotationDefaultValue();
+       }
+
+       public String getParameterSignatureErased() {
+               return realMember.getParameterSignatureErased();
+       }
+
+       public String getSignatureErased() {
+               return realMember.getSignatureErased();
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/JoinPointSignatureIterator.java b/org.aspectj.matcher/src/org/aspectj/weaver/JoinPointSignatureIterator.java
new file mode 100644 (file)
index 0000000..cc754d1
--- /dev/null
@@ -0,0 +1,251 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * Iterates over the signatures of a join point, calculating new signatures
+ * lazily to minimize processing and to avoid unneccessary "can't find type"
+ * errors. Iterator can be cached and reused by calling the "reset" method
+ * between iterations.
+ */
+public class JoinPointSignatureIterator implements Iterator {
+       
+       private Member signaturesOfMember;
+       private ResolvedMember firstDefiningMember;
+       ResolvedType firstDefiningType;
+       private World world;
+       private List /*JoinPointSignature*/ discoveredSignatures = new ArrayList();
+       private List additionalSignatures = Collections.EMPTY_LIST;
+       private Iterator discoveredSignaturesIterator = null;
+       private Iterator superTypeIterator = null;
+       private Set visitedSuperTypes = new HashSet();
+       private List /*SearchPair*/ yetToBeProcessedSuperMembers = null;//new ArrayList();
+       
+       private boolean iteratingOverDiscoveredSignatures = true;
+       private boolean couldBeFurtherAsYetUndiscoveredSignatures = true;
+       
+       /**
+        * 
+        */
+       public JoinPointSignatureIterator(Member joinPointSignature, World inAWorld) {
+               this.signaturesOfMember = joinPointSignature;
+               this.world = inAWorld;
+               addSignaturesUpToFirstDefiningMember();
+               if (!shouldWalkUpHierarchy()) couldBeFurtherAsYetUndiscoveredSignatures = false;
+       }
+
+       public void reset() {
+               discoveredSignaturesIterator = discoveredSignatures.iterator();
+               additionalSignatures.clear();
+               iteratingOverDiscoveredSignatures = true;
+       }
+       
+       /* (non-Javadoc)
+        * @see java.util.Iterator#hasNext()
+        */
+       public boolean hasNext() {
+               if (iteratingOverDiscoveredSignatures && discoveredSignaturesIterator.hasNext()) {
+                       return true;
+               } else if (couldBeFurtherAsYetUndiscoveredSignatures) {
+                       if (additionalSignatures.size() > 0) return true;
+                       else return findSignaturesFromSupertypes();
+               } else {
+                       return false;
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see java.util.Iterator#next()
+        */
+       public Object next() {
+               if (iteratingOverDiscoveredSignatures && discoveredSignaturesIterator.hasNext()) {
+                       return discoveredSignaturesIterator.next();
+               } else {
+                       if (additionalSignatures.size() > 0) {
+                               return additionalSignatures.remove(0);
+                       }
+               }
+               throw new NoSuchElementException();
+       }
+
+       /* (non-Javadoc)
+        * @see java.util.Iterator#remove()
+        */
+       public void remove() {
+               throw new UnsupportedOperationException("can't remove from JoinPointSignatureIterator");
+       }
+       
+       private void addSignaturesUpToFirstDefiningMember() {
+               // Walk up hierarchy creating one member for each type up to and including the
+       // first defining type
+       ResolvedType originalDeclaringType = signaturesOfMember.getDeclaringType().resolve(world);
+       
+       if (world.isJoinpointArrayConstructionEnabled() && originalDeclaringType.isArray()) { // Aha, this must be the array constructor call join point - a 'special'...
+               Member m = signaturesOfMember;
+               ResolvedMember rm = new ResolvedMemberImpl(m.getKind(),m.getDeclaringType(),m.getModifiers(),m.getReturnType(),m.getName(),m.getParameterTypes());
+               discoveredSignatures.add(new JoinPointSignature(rm,originalDeclaringType));
+               couldBeFurtherAsYetUndiscoveredSignatures = false;
+               return;
+       }
+
+       firstDefiningMember = signaturesOfMember.resolve(world);
+       
+       if (firstDefiningMember == null) {
+               couldBeFurtherAsYetUndiscoveredSignatures = false;
+               return;
+       } 
+       
+       // declaringType can be unresolved if we matched a synthetic member generated by Aj...
+       // should be fixed elsewhere but add this resolve call on the end for now so that we can
+       // focus on one problem at a time...
+       firstDefiningType = firstDefiningMember.getDeclaringType().resolve(world);
+       if (firstDefiningType != originalDeclaringType) {
+               if (signaturesOfMember.getKind() == Member.CONSTRUCTOR) {
+                       return;
+               } 
+       }
+
+       List declaringTypes = new ArrayList();
+       accumulateTypesInBetween(originalDeclaringType, 
+                                                        firstDefiningType,
+                                                        declaringTypes);
+       for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) {
+                       ResolvedType declaringType = (ResolvedType) iter.next();
+                       ResolvedMember member = ((ResolvedMemberImpl)firstDefiningMember).withSubstituteDeclaringType(declaringType);
+                       discoveredSignatures.add(member);
+               }
+       }
+       
+    /**
+     * Build a list containing every type between subtype and supertype, inclusively. 
+     */
+    private void accumulateTypesInBetween(ResolvedType subType, ResolvedType superType, List types) {
+       types.add(subType);
+       if (subType == superType) {
+               return;
+       } else {
+               for (Iterator iter = subType.getDirectSupertypes(); iter.hasNext();) {
+                               ResolvedType parent = (ResolvedType) iter.next();
+                               if (superType.isAssignableFrom(parent,true)) {
+                                       accumulateTypesInBetween(parent, superType,types);
+                               }
+                       }
+       }
+    }
+    
+    private boolean shouldWalkUpHierarchy() {
+       if (signaturesOfMember.getKind() == Member.CONSTRUCTOR) return false;
+       if (signaturesOfMember.getKind() == Member.FIELD) return false;
+       if (signaturesOfMember.isStatic()) return false;
+       return true;
+    }
+    
+    private boolean findSignaturesFromSupertypes() {
+       iteratingOverDiscoveredSignatures = false;
+       if (superTypeIterator == null) {
+               superTypeIterator = firstDefiningType.getDirectSupertypes();
+       }
+       if (superTypeIterator.hasNext()) {
+               ResolvedType superType = (ResolvedType) superTypeIterator.next();
+               if (visitedSuperTypes.contains(superType)) {
+                       return findSignaturesFromSupertypes();
+               } else {
+                       // we haven't looked in this type yet
+                       visitedSuperTypes.add(superType);
+                       if (superType.isMissing()) {
+                               // issue a warning, stop looking for join point signatures in this line
+                               warnOnMissingType(superType);
+                               return findSignaturesFromSupertypes();
+                       }
+                               ResolvedMemberImpl foundMember = (ResolvedMemberImpl) superType.lookupResolvedMember(firstDefiningMember,true);
+                               if (foundMember != null && isVisibleTo(firstDefiningMember,foundMember)) {
+                                       List declaringTypes = new ArrayList();
+                                       // declaring type can be unresolved if the member can from an ITD...
+                                       ResolvedType resolvedDeclaringType = foundMember.getDeclaringType().resolve(world);
+                                       accumulateTypesInBetween(superType, resolvedDeclaringType, declaringTypes);
+                                       for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) {
+                                               ResolvedType declaringType = (ResolvedType) iter.next();
+                                               ResolvedMember member = foundMember.withSubstituteDeclaringType(declaringType);
+                                               discoveredSignatures.add(member);  // for next time we are reset
+                                               if (additionalSignatures==Collections.EMPTY_LIST) additionalSignatures=new ArrayList();
+                                               additionalSignatures.add(member);  // for this time
+                                       }                                       
+                                       // if this was a parameterized type, look in the generic type that backs it too
+                                       if (superType.isParameterizedType() && (foundMember.backingGenericMember != null)) {
+                                               ResolvedMember member =new JoinPointSignature(foundMember.backingGenericMember,foundMember.declaringType.resolve(world)); 
+                                               discoveredSignatures.add(member);  // for next time we are reset
+                                               if (additionalSignatures==Collections.EMPTY_LIST) additionalSignatures=new ArrayList();
+                                               additionalSignatures.add(member);  // for this time
+                                       }
+                                       if (yetToBeProcessedSuperMembers==null) yetToBeProcessedSuperMembers=new ArrayList();
+                                       yetToBeProcessedSuperMembers.add(new SearchPair(foundMember,superType));
+                                       return true;
+                               } else {
+                                       return findSignaturesFromSupertypes();
+                               }
+               }
+       }
+       if (yetToBeProcessedSuperMembers!=null && !yetToBeProcessedSuperMembers.isEmpty()) {
+               SearchPair nextUp = (SearchPair) yetToBeProcessedSuperMembers.remove(0);
+               firstDefiningType = nextUp.type;
+               firstDefiningMember = nextUp.member;
+               superTypeIterator = null;
+               return findSignaturesFromSupertypes();
+       }
+       couldBeFurtherAsYetUndiscoveredSignatures = false;
+       return false;
+    }
+    
+    /**
+     * Returns true if the parent member is visible to the child member 
+     * In the same declaring type this is always true, otherwise if parent is private
+     * it is false.
+     * @param childMember
+     * @param parentMember
+     * @return
+     */
+    private boolean isVisibleTo(ResolvedMember childMember, ResolvedMember parentMember) {
+       if (childMember.getDeclaringType().equals(parentMember.getDeclaringType())) return true;
+       if (Modifier.isPrivate(parentMember.getModifiers())) {
+               return false;
+       } else {
+               return true;
+       }
+    }
+    
+    private void warnOnMissingType(ResolvedType missing) {
+       if (missing instanceof MissingResolvedTypeWithKnownSignature) {
+               // which it should be...
+               MissingResolvedTypeWithKnownSignature mrt = (MissingResolvedTypeWithKnownSignature) missing;
+               mrt.raiseWarningOnJoinPointSignature(signaturesOfMember.toString());
+       }
+    }
+    
+    private static class SearchPair {
+       public ResolvedMember member;
+       public ResolvedType type;
+       public SearchPair(ResolvedMember member, ResolvedType type) {
+               this.member = member;
+               this.type = type;
+       }
+    }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Lint.java b/org.aspectj.matcher/src/org/aspectj/weaver/Lint.java
new file mode 100644 (file)
index 0000000..162c03e
--- /dev/null
@@ -0,0 +1,315 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.MessageFormat;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.weaver.tools.Trace;
+import org.aspectj.weaver.tools.TraceFactory;
+
+public class Lint {
+       /* private */Map kinds = new HashMap();
+       /* private */World world;
+
+       public final Kind invalidAbsoluteTypeName = new Kind("invalidAbsoluteTypeName", "no match for this type name: {0}");
+
+       public final Kind invalidWildcardTypeName = new Kind("invalidWildcardTypeName", "no match for this type pattern: {0}");
+
+       public final Kind unresolvableMember = new Kind("unresolvableMember", "can not resolve this member: {0}");
+
+       public final Kind typeNotExposedToWeaver = new Kind("typeNotExposedToWeaver",
+                       "this affected type is not exposed to the weaver: {0}");
+
+       public final Kind shadowNotInStructure = new Kind("shadowNotInStructure",
+                       "the shadow for this join point is not exposed in the structure model: {0}");
+
+       public final Kind unmatchedSuperTypeInCall = new Kind("unmatchedSuperTypeInCall",
+                       "does not match because declaring type is {0}, if match desired use target({1})");
+
+       public final Kind unmatchedTargetKind = new Kind("unmatchedTargetKind", "does not match because annotation {0} has @Target{1}");
+
+       public final Kind canNotImplementLazyTjp = new Kind("canNotImplementLazyTjp",
+                       "can not implement lazyTjp on this joinpoint {0} because around advice is used");
+
+       public final Kind multipleAdviceStoppingLazyTjp = new Kind("multipleAdviceStoppingLazyTjp",
+                       "can not implement lazyTjp at joinpoint {0} because of advice conflicts, see secondary locations to find conflicting advice");
+
+       public final Kind needsSerialVersionUIDField = new Kind("needsSerialVersionUIDField",
+                       "serialVersionUID of type {0} needs to be set because of {1}");
+
+       public final Kind serialVersionUIDBroken = new Kind("brokeSerialVersionCompatibility",
+                       "serialVersionUID of type {0} is broken because of added field {1}");
+
+       public final Kind noInterfaceCtorJoinpoint = new Kind("noInterfaceCtorJoinpoint",
+                       "no interface constructor-execution join point - use {0}+ for implementing classes");
+
+       public final Kind noJoinpointsForBridgeMethods = new Kind(
+                       "noJoinpointsForBridgeMethods",
+                       "pointcut did not match on the method call to a bridge method.  Bridge methods are generated by the compiler and have no join points");
+
+       public final Kind enumAsTargetForDecpIgnored = new Kind("enumAsTargetForDecpIgnored",
+                       "enum type {0} matches a declare parents type pattern but is being ignored");
+
+       public final Kind annotationAsTargetForDecpIgnored = new Kind("annotationAsTargetForDecpIgnored",
+                       "annotation type {0} matches a declare parents type pattern but is being ignored");
+
+       public final Kind cantMatchArrayTypeOnVarargs = new Kind("cantMatchArrayTypeOnVarargs",
+                       "an array type as the last parameter in a signature does not match on the varargs declared method: {0}");
+
+       public final Kind adviceDidNotMatch = new Kind("adviceDidNotMatch", "advice defined in {0} has not been applied");
+
+       public final Kind invalidTargetForAnnotation = new Kind("invalidTargetForAnnotation",
+                       "{0} is not a valid target for annotation {1}, this annotation can only be applied to {2}");
+
+       public final Kind elementAlreadyAnnotated = new Kind("elementAlreadyAnnotated",
+                       "{0} - already has an annotation of type {1}, cannot add a second instance");
+
+       public final Kind runtimeExceptionNotSoftened = new Kind("runtimeExceptionNotSoftened",
+                       "{0} will not be softened as it is already a RuntimeException");
+
+       public final Kind uncheckedArgument = new Kind("uncheckedArgument",
+                       "unchecked match of {0} with {1} when argument is an instance of {2} at join point {3}");
+
+       public final Kind uncheckedAdviceConversion = new Kind("uncheckedAdviceConversion",
+                       "unchecked conversion when advice applied at shadow {0}, expected {1} but advice uses {2}");
+
+       public final Kind noGuardForLazyTjp = new Kind("noGuardForLazyTjp",
+                       "can not build thisJoinPoint lazily for this advice since it has no suitable guard");
+
+       public final Kind noExplicitConstructorCall = new Kind("noExplicitConstructorCall",
+                       "inter-type constructor does not contain explicit constructor call: field initializers in the target type will not be executed");
+
+       public final Kind aspectExcludedByConfiguration = new Kind("aspectExcludedByConfiguration",
+                       "aspect {0} exluded for class loader {1}");
+
+       public final Kind unorderedAdviceAtShadow = new Kind("unorderedAdviceAtShadow",
+                       "at this shadow {0} no precedence is specified between advice applying from aspect {1} and aspect {2}");
+
+       public final Kind swallowedExceptionInCatchBlock = new Kind("swallowedExceptionInCatchBlock",
+                       "exception swallowed in catch block");
+
+       public final Kind calculatingSerialVersionUID = new Kind("calculatingSerialVersionUID",
+                       "calculated SerialVersionUID for type {0} to be {1}");
+
+       // there are a lot of messages in the cant find type family - I'm defining an umbrella lint warning that
+       // allows a user to control their severity (for e.g. ltw or binary weaving)
+       public final Kind cantFindType = new Kind("cantFindType", "{0}");
+
+       public final Kind cantFindTypeAffectingJoinPointMatch = new Kind("cantFindTypeAffectingJPMatch", "{0}");
+
+       public final Kind advisingSynchronizedMethods = new Kind("advisingSynchronizedMethods",
+                       "advice matching the synchronized method shadow ''{0}'' will be executed outside the lock rather than inside (compiler limitation)");
+
+       public final Kind mustWeaveXmlDefinedAspects = new Kind(
+                       "mustWeaveXmlDefinedAspects",
+                       "XML Defined aspects must be woven in cases where cflow pointcuts are involved. Currently the include/exclude patterns exclude ''{0}''");
+
+       /**
+        * Indicates an aspect could not be found when attempting reweaving.
+        */
+       public final Kind missingAspectForReweaving = new Kind("missingAspectForReweaving",
+                       "aspect {0} cannot be found when reweaving {1}");
+
+       private static Trace trace = TraceFactory.getTraceFactory().getTrace(Lint.class);
+
+       public Lint(World world) {
+               if (trace.isTraceEnabled())
+                       trace.enter("<init>", this, world);
+               this.world = world;
+               if (trace.isTraceEnabled())
+                       trace.exit("<init>");
+       }
+
+       public void setAll(String messageKind) {
+               if (trace.isTraceEnabled())
+                       trace.enter("setAll", this, messageKind);
+               setAll(getMessageKind(messageKind));
+               if (trace.isTraceEnabled())
+                       trace.exit("setAll");
+       }
+
+       private void setAll(IMessage.Kind messageKind) {
+               for (Iterator i = kinds.values().iterator(); i.hasNext();) {
+                       Kind kind = (Kind) i.next();
+                       kind.setKind(messageKind);
+               }
+       }
+
+       public void setFromProperties(File file) {
+               if (trace.isTraceEnabled())
+                       trace.enter("setFromProperties", this, file);
+               try {
+                       InputStream s = new FileInputStream(file);
+                       setFromProperties(s);
+               } catch (IOException ioe) {
+                       MessageUtil.error(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINT_LOAD_ERROR, file.getPath(), ioe
+                                       .getMessage()));
+               }
+               if (trace.isTraceEnabled())
+                       trace.exit("setFromProperties");
+       }
+
+       public void loadDefaultProperties() {
+               InputStream s = getClass().getResourceAsStream("XlintDefault.properties");
+               if (s == null) {
+                       MessageUtil.warn(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINTDEFAULT_LOAD_ERROR));
+                       return;
+               }
+               try {
+                       setFromProperties(s);
+               } catch (IOException ioe) {
+                       MessageUtil.error(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINTDEFAULT_LOAD_PROBLEM, ioe
+                                       .getMessage()));
+               }
+
+       }
+
+       private void setFromProperties(InputStream s) throws IOException {
+               Properties p = new Properties();
+               p.load(s);
+               setFromProperties(p);
+       }
+
+       public void setFromProperties(Properties properties) {
+               for (Iterator i = properties.entrySet().iterator(); i.hasNext();) {
+                       Map.Entry entry = (Map.Entry) i.next();
+                       Kind kind = (Kind) kinds.get(entry.getKey());
+                       if (kind == null) {
+                               MessageUtil.error(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINT_KEY_ERROR, entry.getKey()));
+                       } else {
+                               kind.setKind(getMessageKind((String) entry.getValue()));
+                       }
+               }
+       }
+
+       public Collection allKinds() {
+               return kinds.values();
+       }
+
+       public Kind getLintKind(String name) {
+               return (Kind) kinds.get(name);
+       }
+
+       // temporarily suppress the given lint messages
+       public void suppressKinds(Collection lintKind) {
+               if (lintKind.isEmpty())
+                       return;
+               for (Iterator iter = lintKind.iterator(); iter.hasNext();) {
+                       Kind k = (Kind) iter.next();
+                       k.setSuppressed(true);
+               }
+       }
+
+       // remove any suppression of lint warnings in place
+       public void clearAllSuppressions() {
+               for (Iterator iter = kinds.values().iterator(); iter.hasNext();) {
+                       Kind k = (Kind) iter.next();
+                       k.setSuppressed(false);
+               }
+       }
+
+       public void clearSuppressions(Collection lintKind) {
+               if (lintKind.isEmpty())
+                       return;
+               for (Iterator iter = lintKind.iterator(); iter.hasNext();) {
+                       Kind k = (Kind) iter.next();
+                       k.setSuppressed(false);
+               }
+       }
+
+       private IMessage.Kind getMessageKind(String v) {
+               if (v.equals("ignore"))
+                       return null;
+               else if (v.equals("warning"))
+                       return IMessage.WARNING;
+               else if (v.equals("error"))
+                       return IMessage.ERROR;
+
+               MessageUtil.error(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINT_VALUE_ERROR, v));
+               return null;
+       }
+
+       public Kind fromKey(String lintkey) {
+               return (Lint.Kind) kinds.get(lintkey);
+       }
+
+       public class Kind {
+               private final String name;
+               private final String message;
+               private IMessage.Kind kind = IMessage.WARNING;
+               private boolean isSupressed = false; // by SuppressAjWarnings
+
+               public Kind(String name, String message) {
+                       this.name = name;
+                       this.message = message;
+                       kinds.put(this.name, this);
+               }
+
+               public void setSuppressed(boolean shouldBeSuppressed) {
+                       this.isSupressed = shouldBeSuppressed;
+               }
+
+               public boolean isEnabled() {
+                       return (kind != null) && !isSupressed();
+               }
+
+               private boolean isSupressed() {
+                       // can't suppress errors!
+                       return isSupressed && (kind != IMessage.ERROR);
+               }
+
+               public String getName() {
+                       return name;
+               }
+
+               public IMessage.Kind getKind() {
+                       return kind;
+               }
+
+               public void setKind(IMessage.Kind kind) {
+                       this.kind = kind;
+               }
+
+               public void signal(String info, ISourceLocation location) {
+                       if (kind == null)
+                               return;
+
+                       String text = MessageFormat.format(message, new Object[] { info });
+                       text += " [Xlint:" + name + "]";
+                       world.getMessageHandler().handleMessage(new LintMessage(text, kind, location, null, getLintKind(name)));
+               }
+
+               public void signal(String[] infos, ISourceLocation location, ISourceLocation[] extraLocations) {
+                       if (kind == null)
+                               return;
+
+                       String text = MessageFormat.format(message, (Object[]) infos);
+                       text += " [Xlint:" + name + "]";
+                       world.getMessageHandler().handleMessage(new LintMessage(text, kind, location, extraLocations, getLintKind(name)));
+               }
+
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/LintMessage.java b/org.aspectj.matcher/src/org/aspectj/weaver/LintMessage.java
new file mode 100644 (file)
index 0000000..3a93af9
--- /dev/null
@@ -0,0 +1,47 @@
+/* *******************************************************************
+ * Copyright (c) 2002-2006 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ *     AndyClement extracted as self contained type from Lint type (4-Aug-06)
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.Message;
+
+public class LintMessage extends Message {
+       
+       // private Lint.Kind lintKind;
+       private String lintKind;
+       
+       public LintMessage(
+                       String message, 
+                       IMessage.Kind messageKind, 
+                       ISourceLocation location, 
+                       ISourceLocation[] extraLocations,
+                       Lint.Kind lintKind) {  
+               super(message,"",messageKind,location,null,extraLocations);
+               this.lintKind = lintKind.getName();
+       }
+       
+       public LintMessage(String message, String extraDetails, org.aspectj.weaver.Lint.Kind kind2, Kind kind, ISourceLocation sourceLocation, Throwable object, 
+                       ISourceLocation[] seeAlsoLocations, boolean declared, int id, int sourceStart, int sourceEnd) {
+               super(message,extraDetails,kind,sourceLocation,object,seeAlsoLocations,declared,id,sourceStart,sourceEnd);
+               this.lintKind = kind2.getName();
+       }
+
+       /**
+        * @return Returns the Lint kind of this message
+        */
+       public String getLintKind() {
+               return lintKind;
+       }
+       
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Member.java b/org.aspectj.matcher/src/org/aspectj/weaver/Member.java
new file mode 100644 (file)
index 0000000..04c67e1
--- /dev/null
@@ -0,0 +1,102 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ *               2005 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation
+ *     AMC      extracted as interface 
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * Abstract representation of a member within a type.
+ */
+public interface Member extends Comparable {
+
+       public static final Member[] NONE = new Member[0];
+       public static final MemberKind METHOD = new MemberKind("METHOD", 1);
+       public static final MemberKind FIELD = new MemberKind("FIELD", 2);
+       public static final MemberKind CONSTRUCTOR = new MemberKind("CONSTRUCTOR",
+                       3);
+       public static final MemberKind STATIC_INITIALIZATION = new MemberKind(
+                       "STATIC_INITIALIZATION", 4);
+       public static final MemberKind POINTCUT = new MemberKind("POINTCUT", 5);
+       public static final MemberKind ADVICE = new MemberKind("ADVICE", 6);
+       public static final MemberKind HANDLER = new MemberKind("HANDLER", 7);
+       public static final MemberKind MONITORENTER = new MemberKind(
+                       "MONITORENTER", 8);
+       public static final MemberKind MONITOREXIT = new MemberKind("MONITOREXIT",
+                       9);
+
+       public static final AnnotationAJ[][] NO_PARAMETER_ANNOTATIONXS = new AnnotationAJ[][] {};
+       public static final ResolvedType[][] NO_PARAMETER_ANNOTATION_TYPES = new ResolvedType[][] {};
+
+       public MemberKind getKind();
+
+       public ResolvedMember resolve(World world);
+
+       public int compareTo(Object other);
+
+       public UnresolvedType getDeclaringType();
+
+       public UnresolvedType getReturnType();
+
+       public UnresolvedType getGenericReturnType();
+
+       public UnresolvedType[] getGenericParameterTypes();
+
+       public UnresolvedType getType();
+
+       public String getName();
+
+       public UnresolvedType[] getParameterTypes();
+
+       /**
+        * Return full signature, including return type, e.g. "()LFastCar;". For a
+        * signature without the return type, use getParameterSignature() - it is
+        * important to choose the right one in the face of covariance.
+        */
+       public String getSignature();
+
+       public Iterator getJoinPointSignatures(World world);
+
+       public int getArity();
+
+       /**
+        * Return signature without return type, e.g. "()" for a signature *with*
+        * the return type, use getSignature() - it is important to choose the right
+        * one in the face of covariance.
+        */
+       public String getParameterSignature();
+
+       public int getModifiers(World world);
+
+       public int getModifiers();
+
+       public boolean isStatic();
+
+       public boolean isInterface();
+
+       public boolean isPrivate();
+
+       /**
+        * Returns true iff the member is generic (NOT parameterized)
+        */
+       public boolean canBeParameterized();
+
+       public AnnotationAJ[] getAnnotations();
+
+       public Collection/* ResolvedType */getDeclaringTypes(World world);
+
+       public String[] getParameterNames(World world);
+
+       public UnresolvedType[] getExceptions(World world);
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java
new file mode 100644 (file)
index 0000000..f51146f
--- /dev/null
@@ -0,0 +1,565 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+public class MemberImpl implements Member {
+
+       protected MemberKind kind;
+       protected int modifiers;
+       protected String name;
+       protected UnresolvedType returnType;
+       protected UnresolvedType declaringType;
+       protected UnresolvedType[] parameterTypes;
+       private final String signature;
+       private String paramSignature;
+
+       // OPTIMIZE move out of the member!
+       private boolean reportedCantFindDeclaringType = false;
+       private boolean reportedUnresolvableMember = false;
+
+       /**
+        * All the signatures that a join point with this member as its signature
+        * has.
+        */
+       private JoinPointSignatureIterator joinPointSignatures = null;
+
+       public MemberImpl(MemberKind kind, UnresolvedType declaringType,
+                       int modifiers, String name, String signature) {
+               this.kind = kind;
+               this.declaringType = declaringType;
+               this.modifiers = modifiers;
+               this.name = name;
+               this.signature = signature;
+               if (kind == FIELD) {
+                       this.returnType = UnresolvedType.forSignature(signature);
+                       this.parameterTypes = UnresolvedType.NONE;
+               } else {
+                       Object[] returnAndParams = signatureToTypes(signature, false);
+                       this.returnType = (UnresolvedType) returnAndParams[0];
+                       this.parameterTypes = (UnresolvedType[]) returnAndParams[1];
+                       // always safe not to do this ?!?
+                       // String oldsig=new String(signature);
+                       // signature = typesToSignature(returnType,parameterTypes,true);
+               }
+       }
+
+       public MemberImpl(MemberKind kind, UnresolvedType declaringType,
+                       int modifiers, UnresolvedType returnType, String name,
+                       UnresolvedType[] parameterTypes) {
+               this.kind = kind;
+               this.declaringType = declaringType;
+               this.modifiers = modifiers;
+               this.returnType = returnType;
+               this.name = name;
+               this.parameterTypes = parameterTypes;
+               if (kind == FIELD) {
+                       this.signature = returnType.getErasureSignature();
+               } else {
+                       this.signature = typesToSignature(returnType, parameterTypes, true);
+               }
+       }
+
+       public ResolvedMember resolve(World world) {
+               return world.resolve(this);
+       }
+
+       // ---- utility methods
+
+       /**
+        * returns an Object[] pair of UnresolvedType, UnresolvedType[] representing
+        * return type, argument types parsed from the JVM bytecode signature of a
+        * method. Yes, this should actually return a nice statically-typed pair
+        * object, but we don't have one of those.
+        * 
+        * <blockquote>
+        * 
+        * <pre>
+        *   UnresolvedType.signatureToTypes(&quot;()[Z&quot;)[0].equals(Type.forSignature(&quot;[Z&quot;))
+        *   UnresolvedType.signatureToTypes(&quot;(JJ)I&quot;)[1]
+        *      .equals(UnresolvedType.forSignatures(new String[] {&quot;J&quot;, &quot;J&quot;}))
+        * </pre>
+        * 
+        * </blockquote>
+        * 
+        * @param signature
+        *            the JVM bytecode method signature string we want to break
+        *            apart
+        * @return a pair of UnresolvedType, UnresolvedType[] representing the
+        *         return types and parameter types.
+        */
+       // OPTIMIZE move static util methods out into a memberutils class
+       public static String typesToSignature(UnresolvedType returnType,
+                       UnresolvedType[] paramTypes, boolean useRawTypes) {
+               StringBuffer buf = new StringBuffer();
+               buf.append("(");
+               for (int i = 0, len = paramTypes.length; i < len; i++) {
+                       if (paramTypes[i].isParameterizedType() && useRawTypes)
+                               buf.append(paramTypes[i].getErasureSignature());
+                       else if (paramTypes[i].isTypeVariableReference() && useRawTypes)
+                               buf.append(paramTypes[i].getErasureSignature());
+                       else
+                               buf.append(paramTypes[i].getSignature());
+               }
+               buf.append(")");
+               if (returnType.isParameterizedType() && useRawTypes)
+                       buf.append(returnType.getErasureSignature());
+               else if (returnType.isTypeVariableReference() && useRawTypes)
+                       buf.append(returnType.getErasureSignature());
+               else
+                       buf.append(returnType.getSignature());
+               return buf.toString();
+       }
+
+       /**
+        * Returns "(<signaturesOfParamTypes>,...)" - unlike the other
+        * typesToSignature that also includes the return type, this one just deals
+        * with the parameter types.
+        */
+       public static String typesToSignature(UnresolvedType[] paramTypes) {
+               StringBuffer buf = new StringBuffer();
+               buf.append("(");
+               for (int i = 0; i < paramTypes.length; i++) {
+                       buf.append(paramTypes[i].getSignature());
+               }
+               buf.append(")");
+               return buf.toString();
+       }
+
+       /**
+        * returns an Object[] pair of UnresolvedType, UnresolvedType[] representing
+        * return type, argument types parsed from the JVM bytecode signature of a
+        * method. Yes, this should actually return a nice statically-typed pair
+        * object, but we don't have one of those.
+        * 
+        * <blockquote>
+        * 
+        * <pre>
+        *   UnresolvedType.signatureToTypes(&quot;()[Z&quot;)[0].equals(Type.forSignature(&quot;[Z&quot;))
+        *   UnresolvedType.signatureToTypes(&quot;(JJ)I&quot;)[1]
+        *      .equals(UnresolvedType.forSignatures(new String[] {&quot;J&quot;, &quot;J&quot;}))
+        * </pre>
+        * 
+        * </blockquote>
+        * 
+        * @param signature
+        *            the JVM bytecode method signature string we want to break
+        *            apart
+        * @return a pair of UnresolvedType, UnresolvedType[] representing the
+        *         return types and parameter types.
+        */
+       private static Object[] signatureToTypes(String sig,
+                       boolean keepParameterizationInfo) {
+               boolean hasParameters = sig.charAt(1) != ')';
+               if (hasParameters) {
+                       List l = new ArrayList();
+                       int i = 1;
+                       boolean hasAnyAnglies = sig.indexOf('<') != -1;
+                       while (true) {
+                               char c = sig.charAt(i);
+                               if (c == ')')
+                                       break; // break out when the hit the ')'
+                               int start = i;
+                               while (c == '[')
+                                       c = sig.charAt(++i);
+                               if (c == 'L' || c == 'P') {
+                                       int nextSemicolon = sig.indexOf(';', start);
+                                       int firstAngly = (hasAnyAnglies ? sig.indexOf('<', start)
+                                                       : -1);
+                                       if (!hasAnyAnglies || firstAngly == -1
+                                                       || firstAngly > nextSemicolon) {
+                                               i = nextSemicolon + 1;
+                                               l.add(UnresolvedType.forSignature(sig.substring(start,
+                                                               i)));
+                                       } else {
+                                               // generics generics generics
+                                               // Have to skip to the *correct* ';'
+                                               boolean endOfSigReached = false;
+                                               int posn = firstAngly;
+                                               int genericDepth = 0;
+                                               while (!endOfSigReached) {
+                                                       switch (sig.charAt(posn)) {
+                                                       case '<':
+                                                               genericDepth++;
+                                                               break;
+                                                       case '>':
+                                                               genericDepth--;
+                                                               break;
+                                                       case ';':
+                                                               if (genericDepth == 0)
+                                                                       endOfSigReached = true;
+                                                               break;
+                                                       default:
+                                                       }
+                                                       posn++;
+                                               }
+                                               // posn now points to the correct nextSemicolon :)
+                                               i = posn;
+                                               l.add(UnresolvedType.forSignature(sig.substring(start,
+                                                               i)));
+                                       }
+                               } else if (c == 'T') { // assumed 'reference' to a type
+                                                                               // variable, so just "Tname;"
+                                       int nextSemicolon = sig.indexOf(';', start);
+                                       String nextbit = sig.substring(start, nextSemicolon);
+                                       l.add(UnresolvedType.forSignature(nextbit));
+                                       i = nextSemicolon + 1;
+                               } else {
+                                       i++;
+                                       l.add(UnresolvedType.forSignature(sig.substring(start, i)));
+                               }
+                       }
+                       UnresolvedType[] paramTypes = (UnresolvedType[]) l
+                                       .toArray(new UnresolvedType[l.size()]);
+                       UnresolvedType returnType = UnresolvedType.forSignature(sig
+                                       .substring(i + 1, sig.length()));
+                       return new Object[] { returnType, paramTypes };
+               } else {
+                       UnresolvedType returnType = UnresolvedType.forSignature(sig
+                                       .substring(2));
+                       return new Object[] { returnType, UnresolvedType.NONE };
+               }
+       }
+
+       // ---- factory methods
+       public static MemberImpl field(String declaring, int mods, String name,
+                       String signature) {
+               return field(declaring, mods, UnresolvedType.forSignature(signature),
+                               name);
+       }
+
+       // public static Member field(UnresolvedType declaring, int mods, String
+       // name, UnresolvedType type) {
+       // return new MemberImpl(FIELD, declaring, mods, type, name,
+       // UnresolvedType.NONE);
+       // }
+       // OPTIMIZE do we need to call this? unless necessary the signatureToTypes()
+       // call smacks of laziness on the behalf of the caller
+       // of this method
+       public static MemberImpl method(UnresolvedType declaring, int mods,
+                       String name, String signature) {
+               Object[] pair = signatureToTypes(signature, false);
+               return method(declaring, mods, (UnresolvedType) pair[0], name,
+                               (UnresolvedType[]) pair[1]);
+       }
+
+       public static MemberImpl monitorEnter() {
+               return new MemberImpl(MONITORENTER, UnresolvedType.OBJECT,
+                               Modifier.STATIC, ResolvedType.VOID, "<lock>",
+                               UnresolvedType.ARRAY_WITH_JUST_OBJECT);
+       }
+
+       public static MemberImpl monitorExit() {
+               return new MemberImpl(MONITOREXIT, UnresolvedType.OBJECT,
+                               Modifier.STATIC, ResolvedType.VOID, "<unlock>",
+                               UnresolvedType.ARRAY_WITH_JUST_OBJECT);
+       }
+
+       public static Member pointcut(UnresolvedType declaring, String name,
+                       String signature) {
+               Object[] pair = signatureToTypes(signature, false);
+               return pointcut(declaring, 0, (UnresolvedType) pair[0], name,
+                               (UnresolvedType[]) pair[1]);
+       }
+
+       private static MemberImpl field(String declaring, int mods,
+                       UnresolvedType ty, String name) {
+               return new MemberImpl(FIELD, UnresolvedType.forName(declaring), mods,
+                               ty, name, UnresolvedType.NONE);
+       }
+
+       public static MemberImpl method(UnresolvedType declTy, int mods,
+                       UnresolvedType rTy, String name, UnresolvedType[] paramTys) {
+               return new MemberImpl(
+                               // ??? this calls <clinit> a method
+                               name.equals("<init>") ? CONSTRUCTOR : METHOD, declTy, mods,
+                               rTy, name, paramTys);
+       }
+
+       private static Member pointcut(UnresolvedType declTy, int mods,
+                       UnresolvedType rTy, String name, UnresolvedType[] paramTys) {
+               return new MemberImpl(POINTCUT, declTy, mods, rTy, name, paramTys);
+       }
+
+       public static ResolvedMemberImpl makeExceptionHandlerSignature(
+                       UnresolvedType inType, UnresolvedType catchType) {
+               return new ResolvedMemberImpl(HANDLER, inType, Modifier.STATIC,
+                               "<catch>", "(" + catchType.getSignature() + ")V");
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof Member))
+                       return false;
+               Member o = (Member) other;
+               return (getKind() == o.getKind() && getName().equals(o.getName())
+                               && getSignature().equals(o.getSignature()) && getDeclaringType()
+                               .equals(o.getDeclaringType()));
+       }
+
+       /**
+        * Equality is checked based on the underlying signature, so the hash code
+        * of a member is based on its kind, name, signature, and declaring type.
+        * The algorithm for this was taken from page 38 of effective java.
+        */
+       private volatile int hashCode = 0;
+
+       public int hashCode() {
+               if (hashCode == 0) {
+                       int result = 17;
+                       result = 37 * result + getKind().hashCode();
+                       result = 37 * result + getName().hashCode();
+                       result = 37 * result + getSignature().hashCode();
+                       result = 37 * result + getDeclaringType().hashCode();
+                       hashCode = result;
+               }
+               return hashCode;
+       }
+
+       public int compareTo(Object other) {
+               Member o = (Member) other;
+               int i = getName().compareTo(o.getName());
+               if (i != 0)
+                       return i;
+               return getSignature().compareTo(o.getSignature());
+       }
+
+       public String toString() {
+               StringBuffer buf = new StringBuffer();
+               buf.append(returnType.getName());
+               buf.append(' ');
+               buf.append(declaringType.getName());
+               buf.append('.');
+               buf.append(name);
+               if (kind != FIELD) {
+                       buf.append("(");
+                       if (parameterTypes.length != 0) {
+                               buf.append(parameterTypes[0]);
+                               for (int i = 1, len = parameterTypes.length; i < len; i++) {
+                                       buf.append(", ");
+                                       buf.append(parameterTypes[i].getName());
+                               }
+                       }
+                       buf.append(")");
+               }
+               return buf.toString();
+       }
+
+       public MemberKind getKind() {
+               return kind;
+       }
+
+       public UnresolvedType getDeclaringType() {
+               return declaringType;
+       }
+
+       public UnresolvedType getReturnType() {
+               return returnType;
+       }
+
+       public UnresolvedType getGenericReturnType() {
+               return getReturnType();
+       }
+
+       public UnresolvedType[] getGenericParameterTypes() {
+               return getParameterTypes();
+       }
+
+       public final UnresolvedType getType() {
+               return returnType;
+       }
+
+       public String getName() {
+               return name;
+       }
+
+       public UnresolvedType[] getParameterTypes() {
+               return parameterTypes;
+       }
+
+       public String getSignature() {
+               return signature;
+       }
+
+       public int getArity() {
+               return parameterTypes.length;
+       }
+
+       public String getParameterSignature() {
+               if (paramSignature != null)
+                       return paramSignature;
+               StringBuffer sb = new StringBuffer();
+               sb.append("(");
+               for (int i = 0; i < parameterTypes.length; i++) {
+                       UnresolvedType tx = parameterTypes[i];
+                       sb.append(tx.getSignature());
+               }
+               sb.append(")");
+               paramSignature = sb.toString();
+               return paramSignature;
+       }
+
+       // OPTIMIZE see next line. Why the hell are they in here if we only know it
+       // once resolution has occurred...
+       // ---- things we know only with resolution
+
+       public int getModifiers(World world) {
+               ResolvedMember resolved = resolve(world);
+               if (resolved == null) {
+                       reportDidntFindMember(world);
+                       return 0;
+               }
+               return resolved.getModifiers();
+       }
+
+       public UnresolvedType[] getExceptions(World world) {
+               ResolvedMember resolved = resolve(world);
+               if (resolved == null) {
+                       reportDidntFindMember(world);
+                       return UnresolvedType.NONE;
+               }
+               return resolved.getExceptions();
+       }
+
+       public final boolean isStatic() {
+               return Modifier.isStatic(modifiers);
+       }
+
+       public final boolean isInterface() {
+               return Modifier.isInterface(modifiers);
+       }
+
+       public final boolean isPrivate() {
+               return Modifier.isPrivate(modifiers);
+       }
+
+       public boolean canBeParameterized() {
+               return false;
+       }
+
+       public int getModifiers() {
+               return modifiers;
+       }
+
+       public AnnotationAJ[] getAnnotations() {
+               throw new UnsupportedOperationException(
+                               "You should resolve this member '" + this
+                                               + "' and call getAnnotations() on the result...");
+       }
+
+       // ---- fields 'n' stuff
+
+       public Collection/* ResolvedType */getDeclaringTypes(World world) {
+               ResolvedType myType = getDeclaringType().resolve(world);
+               Collection ret = new HashSet();
+               if (kind == CONSTRUCTOR) {
+                       // this is wrong if the member doesn't exist, but that doesn't
+                       // matter
+                       ret.add(myType);
+               } else if (isStatic() || kind == FIELD) {
+                       walkUpStatic(ret, myType);
+               } else {
+                       walkUp(ret, myType);
+               }
+
+               return ret;
+       }
+
+       private boolean walkUp(Collection acc, ResolvedType curr) {
+               if (acc.contains(curr))
+                       return true;
+
+               boolean b = false;
+               for (Iterator i = curr.getDirectSupertypes(); i.hasNext();) {
+                       b |= walkUp(acc, (ResolvedType) i.next());
+               }
+
+               if (!b && curr.isParameterizedType()) {
+                       b = walkUp(acc, curr.getGenericType());
+               }
+
+               if (!b) {
+                       b = curr.lookupMemberNoSupers(this) != null;
+               }
+               if (b)
+                       acc.add(curr);
+               return b;
+       }
+
+       private boolean walkUpStatic(Collection acc, ResolvedType curr) {
+               if (curr.lookupMemberNoSupers(this) != null) {
+                       acc.add(curr);
+                       return true;
+               } else {
+                       boolean b = false;
+                       for (Iterator i = curr.getDirectSupertypes(); i.hasNext();) {
+                               b |= walkUpStatic(acc, (ResolvedType) i.next());
+                       }
+                       if (!b && curr.isParameterizedType()) {
+                               b = walkUpStatic(acc, curr.getGenericType());
+                       }
+                       if (b)
+                               acc.add(curr);
+                       return b;
+               }
+       }
+
+       public String[] getParameterNames(World world) {
+               ResolvedMember resolved = resolve(world);
+               if (resolved == null) {
+                       reportDidntFindMember(world);
+                       return null;
+               }
+               return resolved.getParameterNames();
+       }
+
+       /**
+        * All the signatures that a join point with this member as its signature
+        * has.
+        */
+       public Iterator getJoinPointSignatures(World inAWorld) {
+               if (joinPointSignatures == null) {
+                       joinPointSignatures = new JoinPointSignatureIterator(this, inAWorld);
+               }
+               joinPointSignatures.reset();
+               return joinPointSignatures;
+       }
+
+       /**
+        * Raises an [Xlint:cantFindType] message if the declaring type cannot be
+        * found or an [Xlint:unresolvableMember] message if the type can be found
+        * (bug 149908)
+        */
+       private void reportDidntFindMember(World world) {
+               if (reportedCantFindDeclaringType || reportedUnresolvableMember)
+                       return;
+               ResolvedType rType = getDeclaringType().resolve(world);
+               if (rType.isMissing()) {
+                       world.getLint().cantFindType.signal(WeaverMessages.format(
+                                       WeaverMessages.CANT_FIND_TYPE, rType.getName()), null);
+                       reportedCantFindDeclaringType = true;
+               } else {
+                       world.getLint().unresolvableMember.signal(getName(), null);
+                       reportedUnresolvableMember = true;
+               }
+       }
+
+       public void wipeJoinpointSignatures() {
+               joinPointSignatures = null;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/MemberKind.java b/org.aspectj.matcher/src/org/aspectj/weaver/MemberKind.java
new file mode 100644 (file)
index 0000000..7a5e009
--- /dev/null
@@ -0,0 +1,37 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+package org.aspectj.weaver;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import org.aspectj.util.TypeSafeEnum;
+
+public class MemberKind extends TypeSafeEnum {
+    public MemberKind(String name, int key) { super(name, key); }
+    
+    public static MemberKind read(DataInputStream s) throws IOException {
+        int key = s.readByte();
+        switch(key) {
+            case 1: return Member.METHOD;
+            case 2: return Member.FIELD;
+            case 3: return Member.CONSTRUCTOR;
+            case 4: return Member.STATIC_INITIALIZATION;
+            case 5: return Member.POINTCUT;
+            case 6: return Member.ADVICE;
+            case 7: return Member.HANDLER;
+            case 8: return Member.MONITORENTER;
+            case 9: return Member.MONITOREXIT;
+        }
+        throw new BCException("Unexpected memberkind, should be (1-9) but was " + key);
+    }
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/MethodDelegateTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/MethodDelegateTypeMunger.java
new file mode 100644 (file)
index 0000000..3ecac98
--- /dev/null
@@ -0,0 +1,202 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: 
+ *     Alexandre Vasseur     initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.weaver.patterns.TypePattern;
+
+/**
+ * Type munger for @AspectJ ITD declare parents ie with an interface AND an implementation.
+ * Given the aspect that has a field public static Interface fieldI = ... // impl.
+ * we will weave in the Interface' methods and delegate to the aspect public static field fieldI
+ *
+ * Note: this munger DOES NOT handles the interface addition to the target classes - a regular Parent kinded munger
+ * must be added in coordination.
+ */
+public class MethodDelegateTypeMunger extends ResolvedTypeMunger {
+
+    private final UnresolvedType aspect;
+
+    /**
+     * The mixin impl (no arg ctor)
+     */
+    private final String implClassName;
+
+    /**
+     * Type pattern this munger applies to
+     */
+    private final TypePattern typePattern;
+
+    /**
+     * Construct a new type munger for @AspectJ ITD
+     *
+     * @param signature
+     * @param aspect
+     * @param implClassName
+     * @param typePattern
+     */
+    public MethodDelegateTypeMunger(ResolvedMember signature, UnresolvedType aspect, String implClassName, TypePattern typePattern) {
+        super(MethodDelegate, signature);
+        this.aspect = aspect;
+        this.typePattern = typePattern;
+        this.implClassName = implClassName;
+    }
+
+    public boolean equals(Object other) {
+       if (!(other instanceof MethodDelegateTypeMunger)) return false;
+       MethodDelegateTypeMunger o = (MethodDelegateTypeMunger)other;
+       return ((o.aspect == null) ? (aspect == null ) : aspect.equals(o.aspect))
+                       && ((o.typePattern == null) ? (typePattern == null ) : typePattern.equals(o.typePattern))
+                       && ((o.implClassName == null) ? (implClassName == null) : implClassName.equals(o.implClassName));
+    }
+
+    private volatile int hashCode = 0;
+    public int hashCode() {
+       if (hashCode == 0) {
+               int result = 17;
+           result = 37*result + ((aspect == null) ? 0 : aspect.hashCode());
+           result = 37*result + ((typePattern == null) ? 0 : typePattern.hashCode());
+           result = 37*result + ((implClassName == null) ? 0 : implClassName.hashCode());
+           hashCode = result;
+               }
+           return hashCode;
+    }
+    
+    public ResolvedMember getDelegate(ResolvedType targetType) {
+        return AjcMemberMaker.itdAtDeclareParentsField(
+                targetType,
+                signature.getDeclaringType(),
+                aspect
+        );
+    }
+
+    public String getImplClassName() {
+        return implClassName;
+    }
+
+    public void write(DataOutputStream s) throws IOException {
+        kind.write(s);
+        signature.write(s);
+        aspect.write(s);
+        s.writeUTF(implClassName);
+        typePattern.write(s);
+    }
+
+    public static ResolvedTypeMunger readMethod(VersionedDataInputStream s, ISourceContext context) throws IOException {
+        ResolvedMemberImpl signature = ResolvedMemberImpl.readResolvedMember(s, context);
+        UnresolvedType aspect = UnresolvedType.read(s);
+        String implClassName = s.readUTF();
+        TypePattern tp = TypePattern.read(s, context);
+        return new MethodDelegateTypeMunger(signature, aspect, implClassName, tp);
+    }
+
+    /**
+     * Match based on given type pattern, only classes can be matched
+     *
+     * @param matchType
+     * @param aspectType
+     * @return true if match
+     */
+    public boolean matches(ResolvedType matchType, ResolvedType aspectType) {
+        // match only on class
+        if (matchType.isEnum() || matchType.isInterface() || matchType.isAnnotation()) {
+            return false;
+        }
+
+        return typePattern.matchesStatically(matchType);
+    }
+
+    /**
+     * Needed for reweavable
+     *
+     * @return true
+     */
+    public boolean changesPublicSignature() {
+        return true;
+    }
+
+    public static class FieldHostTypeMunger extends ResolvedTypeMunger {
+
+        private UnresolvedType aspect;
+
+        /**
+         * Type pattern this munger applies to
+         */
+        private final TypePattern typePattern;
+
+        /**
+         * Construct a new type munger for @AspectJ ITD
+         *
+         * @param field
+         * @param aspect
+         * @param typePattern
+         */
+        public FieldHostTypeMunger(ResolvedMember field, UnresolvedType aspect, TypePattern typePattern) {
+            super(FieldHost, field);
+            this.aspect = aspect;
+            this.typePattern = typePattern;
+        }
+
+        public boolean equals(Object other) {
+               if (!(other instanceof FieldHostTypeMunger)) return false;
+               FieldHostTypeMunger o = (FieldHostTypeMunger)other;
+               return ((o.aspect == null) ? (aspect == null ) : aspect.equals(o.aspect))
+                               && ((o.typePattern == null) ? (typePattern == null ) : typePattern.equals(o.typePattern));
+        }
+
+        public int hashCode() {
+               int result = 17;
+           result = 37*result + ((aspect == null) ? 0 : aspect.hashCode());
+           result = 37*result + ((typePattern == null) ? 0 : typePattern.hashCode());
+           return result;
+        }
+        
+        public void write(DataOutputStream s) throws IOException {
+            kind.write(s);
+            signature.write(s);
+            aspect.write(s);
+            typePattern.write(s);
+        }
+
+        public static ResolvedTypeMunger readFieldHost(VersionedDataInputStream s, ISourceContext context) throws IOException {
+            ResolvedMemberImpl signature = ResolvedMemberImpl.readResolvedMember(s, context);
+            UnresolvedType aspect = UnresolvedType.read(s);
+            TypePattern tp = TypePattern.read(s, context);
+            return new FieldHostTypeMunger(signature, aspect, tp);
+        }
+
+        /**
+         * Match based on given type pattern, only classes can be matched
+         *
+         * @param matchType
+         * @param aspectType
+         * @return true if match
+         */
+        public boolean matches(ResolvedType matchType, ResolvedType aspectType) {
+            // match only on class
+            if (matchType.isEnum() || matchType.isInterface() || matchType.isAnnotation()) {
+                return false;
+            }
+
+            return typePattern.matchesStatically(matchType);
+        }
+
+        public boolean changesPublicSignature() {
+            return false;
+        }
+
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/MissingResolvedTypeWithKnownSignature.java b/org.aspectj.matcher/src/org/aspectj/weaver/MissingResolvedTypeWithKnownSignature.java
new file mode 100644 (file)
index 0000000..96cda71
--- /dev/null
@@ -0,0 +1,212 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.context.CompilationAndWeavingContext;
+
+/**
+ * When we try to resolve a type in the world that we require to be present,
+ * and then fail to find it, we return an instance of this class. This class 
+ * defers the production of the "can't find type error" until the first time
+ * that someone asks a question that can't be answered solely from the signature.
+ * This enables the weaver to be more tolerant of missing types.
+ *
+ */
+public class MissingResolvedTypeWithKnownSignature extends ResolvedType {
+
+       private static ResolvedMember[] NO_MEMBERS = new ResolvedMember[0];
+       private static ResolvedType[] NO_TYPES = new ResolvedType[0];
+       private boolean issuedCantFindTypeError = false;
+       private boolean issuedJoinPointWarning = false;
+       private boolean issuedMissingInterfaceWarning = false;
+       
+       /**
+        * @param signature
+        * @param world
+        */
+       public MissingResolvedTypeWithKnownSignature(String signature, World world) {
+               super(signature, world);
+       }
+
+       public boolean isMissing() { return true; }
+       
+       /**
+        * @param signature
+        * @param signatureErasure
+        * @param world
+        */
+       public MissingResolvedTypeWithKnownSignature(String signature,
+                       String signatureErasure, World world) {
+               super(signature, signatureErasure, world);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.ResolvedType#getDeclaredFields()
+        */
+       public ResolvedMember[] getDeclaredFields() {
+               raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_FIELDS);
+               return NO_MEMBERS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.ResolvedType#getDeclaredMethods()
+        */
+       public ResolvedMember[] getDeclaredMethods() {
+               raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_METHODS);
+               return NO_MEMBERS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.ResolvedType#getDeclaredInterfaces()
+        */
+       public ResolvedType[] getDeclaredInterfaces() {
+               raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_INTERFACES);
+               return NO_TYPES;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.ResolvedType#getDeclaredPointcuts()
+        */
+       public ResolvedMember[] getDeclaredPointcuts() {
+               raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_POINTCUTS);
+               return NO_MEMBERS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.ResolvedType#getSuperclass()
+        */
+       public ResolvedType getSuperclass() {
+               raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_SUPERCLASS);
+               return ResolvedType.MISSING;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.ResolvedType#getModifiers()
+        */
+       public int getModifiers() {
+               raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_MODIFIERS);
+               return 0;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.ResolvedType#getSourceContext()
+        */
+       public ISourceContext getSourceContext() {
+               return new ISourceContext() {
+
+                       public ISourceLocation makeSourceLocation(IHasPosition position) {
+                               return null;
+                       }
+
+                       public ISourceLocation makeSourceLocation(int line, int offset) {
+                               return null;
+                       }
+
+                       public int getOffset() {
+                               return 0;
+                       }
+                       
+                       public void tidy() {}
+                       
+               };
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.ResolvedType#isAssignableFrom(org.aspectj.weaver.ResolvedType)
+        */
+       public boolean isAssignableFrom(ResolvedType other) {
+               raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_ASSIGNABLE,other.getName());
+               return false;
+       }
+       
+       public boolean isAssignableFrom(ResolvedType other, boolean allowMissing) {
+               if (allowMissing) return false;
+               else return isAssignableFrom(other);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.ResolvedType#isCoerceableFrom(org.aspectj.weaver.ResolvedType)
+        */
+       public boolean isCoerceableFrom(ResolvedType other) {
+               raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_COERCEABLE,other.getName());
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.AnnotatedElement#hasAnnotation(org.aspectj.weaver.UnresolvedType)
+        */
+       public boolean hasAnnotation(UnresolvedType ofType) {
+               raiseCantFindType(WeaverMessages.CANT_FIND_TYPE_ANNOTATION);
+               return false;
+       }
+       
+       public List getInterTypeMungers() {
+               return Collections.EMPTY_LIST;
+       }
+       
+       public List getInterTypeMungersIncludingSupers() {
+               return Collections.EMPTY_LIST;
+       }
+       
+       public List getInterTypeParentMungers() {
+               return Collections.EMPTY_LIST;
+       }
+       
+       public List getInterTypeParentMungersIncludingSupers() {
+               return Collections.EMPTY_LIST;
+       }
+       
+       protected void collectInterTypeMungers(List collector) {
+               return;
+       }
+       
+       public void raiseWarningOnJoinPointSignature(String signature) {
+               if (issuedJoinPointWarning) return;
+               String message = WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_JOINPOINT,getName(),signature);
+               message += "\n" + CompilationAndWeavingContext.getCurrentContext();
+               world.getLint().cantFindTypeAffectingJoinPointMatch.signal(message,null);
+//             MessageUtil.warn(world.getMessageHandler(),message); 
+               issuedJoinPointWarning = true;          
+       }
+       
+       public void raiseWarningOnMissingInterfaceWhilstFindingMethods() {
+               if (issuedMissingInterfaceWarning) return;
+               String message = WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_INTERFACE_METHODS,getName(),signature);
+               message += "\n" + CompilationAndWeavingContext.getCurrentContext();
+               world.getLint().cantFindTypeAffectingJoinPointMatch.signal(message,null);
+               //MessageUtil.warn(world.getMessageHandler(),message); 
+               issuedMissingInterfaceWarning = true;                           
+       }
+       
+       private void raiseCantFindType(String key) {
+               if (issuedCantFindTypeError) return;
+               String message = WeaverMessages.format(key,getName());
+               message += "\n" + CompilationAndWeavingContext.getCurrentContext();
+               world.getLint().cantFindType.signal(message,null);
+//             MessageUtil.error(world.getMessageHandler(),message);
+               issuedCantFindTypeError = true;
+       }
+
+       private void raiseCantFindType(String key,String insert) {
+               if (issuedCantFindTypeError) return;
+               String message = WeaverMessages.format(key,getName(),insert);
+               message += "\n" + CompilationAndWeavingContext.getCurrentContext();
+               world.getLint().cantFindType.signal(message,null);
+//             MessageUtil.error(world.getMessageHandler(),message);
+               issuedCantFindTypeError = true;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/NameMangler.java b/org.aspectj.matcher/src/org/aspectj/weaver/NameMangler.java
new file mode 100644 (file)
index 0000000..5da734a
--- /dev/null
@@ -0,0 +1,334 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+
+public class NameMangler {
+
+       // public static final char[] AJC_DOLLAR_PREFIX = { 'a', 'j', 'c', '$' };
+       // public static final char[] CLINIT = { '<', 'c', 'l', 'i', 'n', 'i', 't', '>' };
+       public static final String PREFIX = "ajc$";
+       // public static final char[] INIT = { '<', 'i', 'n', 'i', 't', '>' };
+       public static final String ITD_PREFIX = PREFIX + "interType$";
+       // public static final char[] METHOD_ASPECTOF = {'a', 's', 'p','e','c','t','O','f'};
+       // public static final char[] METHOD_HASASPECT = { 'h', 'a', 's', 'A', 's', 'p', 'e', 'c', 't' };
+       // public static final char[] STATIC_INITIALIZER = { '<', 'c', 'l', 'i', 'n', 'i', 't', '>' };
+
+       public static final String CFLOW_STACK_TYPE = "org.aspectj.runtime.internal.CFlowStack";
+       public static final String CFLOW_COUNTER_TYPE = "org.aspectj.runtime.internal.CFlowCounter";
+
+       public static final UnresolvedType CFLOW_STACK_UNRESOLVEDTYPE = UnresolvedType
+                       .forSignature("Lorg/aspectj/runtime/internal/CFlowStack;");
+
+       public static final UnresolvedType CFLOW_COUNTER_UNRESOLVEDTYPE = UnresolvedType
+                       .forSignature("Lorg/aspectj/runtime/internal/CFlowCounter;");
+
+       public static final String SOFT_EXCEPTION_TYPE = "org.aspectj.lang.SoftException";
+
+       public static final String PERSINGLETON_FIELD_NAME = PREFIX + "perSingletonInstance";
+       public static final String PERCFLOW_FIELD_NAME = PREFIX + "perCflowStack";
+       // public static final String PERTHIS_FIELD_NAME = PREFIX + "perSingletonInstance";
+
+       // -----
+       public static final String PERCFLOW_PUSH_METHOD = PREFIX + "perCflowPush";
+
+       public static final String PEROBJECT_BIND_METHOD = PREFIX + "perObjectBind";
+
+       // PTWIMPL Method and field names
+       public static final String PERTYPEWITHIN_GETINSTANCE_METHOD = PREFIX + "getInstance";
+       public static final String PERTYPEWITHIN_CREATEASPECTINSTANCE_METHOD = PREFIX + "createAspectInstance";
+       public static final String PERTYPEWITHIN_WITHINTYPEFIELD = PREFIX + "withinType";
+       public static final String PERTYPEWITHIN_GETWITHINTYPENAME_METHOD = "getWithinTypeName";
+
+       public static final String AJC_PRE_CLINIT_NAME = PREFIX + "preClinit";
+
+       public static final String AJC_POST_CLINIT_NAME = PREFIX + "postClinit";
+
+       public static final String INITFAILURECAUSE_FIELD_NAME = PREFIX + "initFailureCause";
+
+       public static boolean isSyntheticMethod(String methodName, boolean declaredInAspect) {
+               if (methodName.startsWith(PREFIX)) {
+                       // it's synthetic unless it is an advice method
+                       if (methodName.startsWith("ajc$before") || methodName.startsWith("ajc$after")) {
+                               return false;
+                       } else if (methodName.startsWith("ajc$around")) {
+                               // around advice method is not synthetic, but generated proceed is...
+                               return (methodName.endsWith("proceed"));
+                       } else if (methodName.startsWith("ajc$interMethod$")) {
+                               return false; // body of an itd-m
+                       }
+                       return true;
+               } else if (methodName.indexOf("_aroundBody") != -1) {
+                       return true;
+               }
+               // these aren't the droids you're looking for...move along...... pr148727
+               // else if (declaredInAspect) {
+               // if (methodName.equals("aspectOf") || methodName.equals("hasAspect")) {
+               // return true;
+               // }
+               // }
+               return false;
+       }
+
+       public static String perObjectInterfaceGet(UnresolvedType aspectType) {
+               return makeName(aspectType.getNameAsIdentifier(), "perObjectGet");
+       }
+
+       public static String perObjectInterfaceSet(UnresolvedType aspectType) {
+               return makeName(aspectType.getNameAsIdentifier(), "perObjectSet");
+       }
+
+       public static String perObjectInterfaceField(UnresolvedType aspectType) {
+               return makeName(aspectType.getNameAsIdentifier(), "perObjectField");
+       }
+
+       // PTWIMPL method names that must include aspect type
+       public static String perTypeWithinFieldForTarget(UnresolvedType aspectType) {
+               return makeName(aspectType.getNameAsIdentifier(), "ptwAspectInstance");
+       }
+
+       public static String perTypeWithinLocalAspectOf(UnresolvedType aspectType) {
+               return makeName(aspectType.getNameAsIdentifier(), "localAspectOf");
+       }
+
+       public static String itdAtDeclareParentsField(UnresolvedType aspectType, UnresolvedType itdType) {
+               return makeName("instance", aspectType.getNameAsIdentifier(), itdType.getNameAsIdentifier());
+       }
+
+       public static String privilegedAccessMethodForMethod(String name, UnresolvedType objectType, UnresolvedType aspectType) {
+               return makeName("privMethod", aspectType.getNameAsIdentifier(), objectType.getNameAsIdentifier(), name);
+       }
+
+       public static String privilegedAccessMethodForFieldGet(String name, UnresolvedType objectType, UnresolvedType aspectType) {
+               return makeName("privFieldGet", aspectType.getNameAsIdentifier(), objectType.getNameAsIdentifier(), name);
+       }
+
+       public static String privilegedAccessMethodForFieldSet(String name, UnresolvedType objectType, UnresolvedType aspectType) {
+               return makeName("privFieldSet", aspectType.getNameAsIdentifier(), objectType.getNameAsIdentifier(), name);
+       }
+
+       public static String inlineAccessMethodForMethod(String name, UnresolvedType objectType, UnresolvedType aspectType) {
+               return makeName("inlineAccessMethod", aspectType.getNameAsIdentifier(), objectType.getNameAsIdentifier(), name);
+       }
+
+       public static String inlineAccessMethodForFieldGet(String name, UnresolvedType objectType, UnresolvedType aspectType) {
+               return makeName("inlineAccessFieldGet", aspectType.getNameAsIdentifier(), objectType.getNameAsIdentifier(), name);
+       }
+
+       public static String inlineAccessMethodForFieldSet(String name, UnresolvedType objectType, UnresolvedType aspectType) {
+               return makeName("inlineAccessFieldSet", aspectType.getNameAsIdentifier(), objectType.getNameAsIdentifier(), name);
+       }
+
+       /**
+        * The name of methods corresponding to advice declarations Of the form:
+        * "ajc$[AdviceKind]$[AspectName]$[NumberOfAdviceInAspect]$[PointcutHash]"
+        */
+       public static String adviceName(String nameAsIdentifier, AdviceKind kind, int adviceSeqNumber, int pcdHash) {
+               String newname = makeName(kind.getName(), nameAsIdentifier, Integer.toString(adviceSeqNumber), Integer.toHexString(pcdHash));
+               return newname;
+       }
+
+       /**
+        * This field goes on top-most implementers of the interface the field is declared onto
+        */
+       public static String interFieldInterfaceField(UnresolvedType aspectType, UnresolvedType interfaceType, String name) {
+               return makeName("interField", aspectType.getNameAsIdentifier(), interfaceType.getNameAsIdentifier(), name);
+       }
+
+       /**
+        * This instance method goes on the interface the field is declared onto as well as its top-most implementors
+        */
+       public static String interFieldInterfaceSetter(UnresolvedType aspectType, UnresolvedType interfaceType, String name) {
+               return makeName("interFieldSet", aspectType.getNameAsIdentifier(), interfaceType.getNameAsIdentifier(), name);
+       }
+
+       /**
+        * This instance method goes on the interface the field is declared onto as well as its top-most implementors
+        */
+       public static String interFieldInterfaceGetter(UnresolvedType aspectType, UnresolvedType interfaceType, String name) {
+               return makeName("interFieldGet", aspectType.getNameAsIdentifier(), interfaceType.getNameAsIdentifier(), name);
+       }
+
+       /**
+        * This static method goes on the aspect that declares the inter-type field
+        */
+       public static String interFieldSetDispatcher(UnresolvedType aspectType, UnresolvedType onType, String name) {
+               return makeName("interFieldSetDispatch", aspectType.getNameAsIdentifier(), onType.getNameAsIdentifier(), name);
+       }
+
+       /**
+        * This static method goes on the aspect that declares the inter-type field
+        */
+       public static String interFieldGetDispatcher(UnresolvedType aspectType, UnresolvedType onType, String name) {
+               return makeName("interFieldGetDispatch", aspectType.getNameAsIdentifier(), onType.getNameAsIdentifier(), name);
+       }
+
+       /**
+        * This field goes on the class the field is declared onto
+        */
+       public static String interFieldClassField(int modifiers, UnresolvedType aspectType, UnresolvedType classType, String name) {
+               if (Modifier.isPublic(modifiers))
+                       return name;
+               // ??? might want to handle case where aspect and class are in same package similar to public
+               return makeName("interField", makeVisibilityName(modifiers, aspectType), name);
+       }
+
+       // /**
+       // * This static method goes on the aspect that declares the inter-type field
+       // */
+       // public static String classFieldSetDispatcher(UnresolvedType aspectType, UnresolvedType classType, String name) {
+       // return makeName("interFieldSetDispatch", aspectType.getNameAsIdentifier(),
+       // classType.getNameAsIdentifier(), name);
+       // }
+       //
+       // /**
+       // * This static method goes on the aspect that declares the inter-type field
+       // */
+       // public static String classFieldGetDispatcher(UnresolvedType aspectType, UnresolvedType classType, String name)
+       // {
+       // return makeName(
+       // "interFieldGetDispatch",
+       // aspectType.getNameAsIdentifier(),
+       // classType.getNameAsIdentifier(),
+       // name);
+       // }
+
+       /**
+        * This static void method goes on the aspect that declares the inter-type field and is called from the appropriate place
+        * (target's initializer, or clinit, or topmost implementer's inits), to initialize the field;
+        */
+
+       public static String interFieldInitializer(UnresolvedType aspectType, UnresolvedType classType, String name) {
+               return makeName("interFieldInit", aspectType.getNameAsIdentifier(), classType.getNameAsIdentifier(), name);
+       }
+
+       // ----
+
+       /**
+        * This method goes on the target type of the inter-type method. (and possibly the topmost-implemeters, if the target type is an
+        * interface)
+        */
+       public static String interMethod(int modifiers, UnresolvedType aspectType, UnresolvedType classType, String name) {
+               if (Modifier.isPublic(modifiers))
+                       return name;
+               // ??? might want to handle case where aspect and class are in same package similar to public
+               return makeName("interMethodDispatch2", makeVisibilityName(modifiers, aspectType), name);
+       }
+
+       /**
+        * This static method goes on the declaring aspect of the inter-type method.
+        */
+       public static String interMethodDispatcher(UnresolvedType aspectType, UnresolvedType classType, String name) {
+               return makeName("interMethodDispatch1", aspectType.getNameAsIdentifier(), classType.getNameAsIdentifier(), name);
+       }
+
+       /**
+        * This static method goes on the declaring aspect of the inter-type method.
+        */
+       public static String interMethodBody(UnresolvedType aspectType, UnresolvedType classType, String name) {
+               return makeName("interMethod", aspectType.getNameAsIdentifier(), classType.getNameAsIdentifier(), name);
+       }
+
+       // ----
+
+       /**
+        * This static method goes on the declaring aspect of the inter-type constructor.
+        */
+       public static String preIntroducedConstructor(UnresolvedType aspectType, UnresolvedType targetType) {
+               return makeName("preInterConstructor", aspectType.getNameAsIdentifier(), targetType.getNameAsIdentifier());
+       }
+
+       /**
+        * This static method goes on the declaring aspect of the inter-type constructor.
+        */
+       public static String postIntroducedConstructor(UnresolvedType aspectType, UnresolvedType targetType) {
+               return makeName("postInterConstructor", aspectType.getNameAsIdentifier(), targetType.getNameAsIdentifier());
+       }
+
+       // ----
+
+       /**
+        * This static method goes on the target class of the inter-type method.
+        */
+       public static String superDispatchMethod(UnresolvedType classType, String name) {
+               return makeName("superDispatch", classType.getNameAsIdentifier(), name);
+       }
+
+       /**
+        * This static method goes on the target class of the inter-type method.
+        */
+       public static String protectedDispatchMethod(UnresolvedType classType, String name) {
+               return makeName("protectedDispatch", classType.getNameAsIdentifier(), name);
+       }
+
+       // ----
+
+       private static String makeVisibilityName(int modifiers, UnresolvedType aspectType) {
+               if (Modifier.isPrivate(modifiers)) {
+                       return aspectType.getOutermostType().getNameAsIdentifier();
+               } else if (Modifier.isProtected(modifiers)) {
+                       throw new RuntimeException("protected inter-types not allowed");
+               } else if (Modifier.isPublic(modifiers)) {
+                       return "";
+               } else {
+                       return aspectType.getPackageNameAsIdentifier();
+               }
+       }
+
+       private static String makeName(String s1, String s2) {
+               return "ajc$" + s1 + "$" + s2;
+       }
+
+       public static String makeName(String s1, String s2, String s3) {
+               return "ajc$" + s1 + "$" + s2 + "$" + s3;
+       }
+
+       public static String makeName(String s1, String s2, String s3, String s4) {
+               return "ajc$" + s1 + "$" + s2 + "$" + s3 + "$" + s4;
+       }
+
+       public static String cflowStack(CrosscuttingMembers xcut) {
+               return makeName("cflowStack", Integer.toHexString(xcut.getCflowEntries().size()));
+       }
+
+       public static String cflowCounter(CrosscuttingMembers xcut) {
+               return makeName("cflowCounter", Integer.toHexString(xcut.getCflowEntries().size()));
+       }
+
+       public static String makeClosureClassName(UnresolvedType enclosingType, int index) {
+               return enclosingType.getName() + "$AjcClosure" + index;
+       }
+
+       public static String aroundCallbackMethodName(Member shadowSig, String suffixTag) {
+               StringBuffer ret = new StringBuffer();
+               ret.append(getExtractableName(shadowSig)).append("_aroundBody").append(suffixTag);
+               return ret.toString();
+       }
+
+       public static String getExtractableName(Member shadowSignature) {
+               String name = shadowSignature.getName();
+               MemberKind kind = shadowSignature.getKind();
+               if (kind == Member.CONSTRUCTOR)
+                       return "init$";
+               else if (kind == Member.STATIC_INITIALIZATION)
+                       return "clinit$";
+               else
+                       return name;
+       }
+
+       public static String proceedMethodName(String adviceMethodName) {
+               return adviceMethodName + "proceed";
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/NewConstructorTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/NewConstructorTypeMunger.java
new file mode 100644 (file)
index 0000000..21a055c
--- /dev/null
@@ -0,0 +1,144 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+
+public class NewConstructorTypeMunger extends ResolvedTypeMunger {
+       private ResolvedMember syntheticConstructor;
+       private ResolvedMember explicitConstructor;
+
+
+       public NewConstructorTypeMunger(
+               ResolvedMember signature,
+               ResolvedMember syntheticConstructor,
+               ResolvedMember explicitConstructor,
+               Set superMethodsCalled,
+               List typeVariableAliases) {
+               super(Constructor, signature);
+               this.syntheticConstructor = syntheticConstructor;
+               this.typeVariableAliases = typeVariableAliases;
+               this.explicitConstructor = explicitConstructor;
+               this.setSuperMethodsCalled(superMethodsCalled);
+
+       }
+       
+    public boolean equals(Object other) {
+       if (!(other instanceof NewConstructorTypeMunger)) return false;
+       NewConstructorTypeMunger o = (NewConstructorTypeMunger)other;   
+       return ((o.syntheticConstructor == null) ? (syntheticConstructor == null ) 
+                               : syntheticConstructor.equals(o.syntheticConstructor))
+                       & ((o.explicitConstructor == null) ? (explicitConstructor == null ) 
+                               : explicitConstructor.equals(o.explicitConstructor));
+    }
+
+    private volatile int hashCode = 0;
+    public int hashCode() {
+       if (hashCode == 0) {
+               int result = 17;
+           result = 37*result + ((syntheticConstructor == null) ? 0 : syntheticConstructor.hashCode());
+           result = 37*result + ((explicitConstructor == null) ? 0 : explicitConstructor.hashCode());
+           hashCode = result;
+               }
+           return hashCode;
+    }
+       
+       // doesnt seem required....
+//     public ResolvedMember getDispatchMethod(UnresolvedType aspectType) {
+//             return AjcMemberMaker.interMethodBody(signature, aspectType);
+//     }
+
+       public void write(DataOutputStream s) throws IOException {
+               kind.write(s);
+               signature.write(s);
+               syntheticConstructor.write(s);
+               explicitConstructor.write(s);
+               writeSuperMethodsCalled(s);
+               writeSourceLocation(s);
+               writeOutTypeAliases(s);
+       }
+       
+       public static ResolvedTypeMunger readConstructor(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               ISourceLocation sloc = null;
+               ResolvedMember sig           = ResolvedMemberImpl.readResolvedMember(s, context);
+               ResolvedMember syntheticCtor = ResolvedMemberImpl.readResolvedMember(s, context);
+               ResolvedMember explicitCtor  = ResolvedMemberImpl.readResolvedMember(s, context);
+               Set superMethodsCalled       = readSuperMethodsCalled(s);
+               sloc                         = readSourceLocation(s);
+               List typeVarAliases          = readInTypeAliases(s);
+               ResolvedTypeMunger munger = new NewConstructorTypeMunger(sig,syntheticCtor,explicitCtor,superMethodsCalled,typeVarAliases);
+               if (sloc!=null) munger.setSourceLocation(sloc);
+               return munger;
+       }
+
+       public ResolvedMember getExplicitConstructor() {
+               return explicitConstructor;
+       }
+
+       public ResolvedMember getSyntheticConstructor() {
+               return syntheticConstructor;
+       }
+
+       public void setExplicitConstructor(ResolvedMember explicitConstructor) {
+               this.explicitConstructor = explicitConstructor;
+               // reset hashCode so that its recalculated with new value
+               hashCode = 0;
+       }
+       
+       public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedType aspectType) {
+               ResolvedMember ret = getSyntheticConstructor();
+               if (ResolvedType.matches(ret, member)) return getSignature();
+               return super.getMatchingSyntheticMember(member, aspectType);
+       }
+       
+       public void check(World world) {
+               if (getSignature().getDeclaringType().resolve(world).isAspect()) {
+                       world.showMessage(IMessage.ERROR, 
+                                       WeaverMessages.format(WeaverMessages.ITD_CONS_ON_ASPECT),
+                                       getSignature().getSourceLocation(), null);
+               }
+       }
+
+       /**
+     * see ResolvedTypeMunger.parameterizedFor(ResolvedType)
+     */
+       public ResolvedTypeMunger parameterizedFor(ResolvedType target) {
+               ResolvedType genericType = target;
+               if (target.isRawType() || target.isParameterizedType()) genericType = genericType.getGenericType();
+               ResolvedMember parameterizedSignature = null;
+               // If we are parameterizing it for a generic type, we just need to 'swap the letters' from the ones used 
+               // in the original ITD declaration to the ones used in the actual target type declaration.
+               if (target.isGenericType()) {
+                       TypeVariable vars[] = target.getTypeVariables();
+                       UnresolvedTypeVariableReferenceType[] varRefs = new UnresolvedTypeVariableReferenceType[vars.length];
+                       for (int i = 0; i < vars.length; i++) {
+                               varRefs[i] = new UnresolvedTypeVariableReferenceType(vars[i]);
+                       }
+                       parameterizedSignature = getSignature().parameterizedWith(varRefs,genericType,true,typeVariableAliases);
+               } else {
+                 // For raw and 'normal' parameterized targets  (e.g. Interface, Interface<String>)
+                 parameterizedSignature = getSignature().parameterizedWith(target.getTypeParameters(),genericType,target.isParameterizedType(),typeVariableAliases);
+               }
+               NewConstructorTypeMunger nctm = new NewConstructorTypeMunger(parameterizedSignature,syntheticConstructor,explicitConstructor,getSuperMethodsCalled(),typeVariableAliases);
+               nctm.setSourceLocation(getSourceLocation());
+               return nctm;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/NewFieldTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/NewFieldTypeMunger.java
new file mode 100644 (file)
index 0000000..19ed670
--- /dev/null
@@ -0,0 +1,124 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.aspectj.bridge.ISourceLocation;
+
+public class NewFieldTypeMunger extends ResolvedTypeMunger {
+
+       public NewFieldTypeMunger(ResolvedMember signature, Set superMethodsCalled, List typeVariableAliases) {
+               super(Field, signature);
+               this.typeVariableAliases = typeVariableAliases;
+               signature.setAnnotatedElsewhere(true);
+               this.setSuperMethodsCalled(superMethodsCalled);
+       }
+
+       public ResolvedMember getInitMethod(UnresolvedType aspectType) {
+               return AjcMemberMaker.interFieldInitializer(signature, aspectType);
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               kind.write(s);
+               signature.write(s);
+               writeSuperMethodsCalled(s);
+               writeSourceLocation(s);
+               writeOutTypeAliases(s);
+       }
+
+       public static ResolvedTypeMunger readField(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               ISourceLocation sloc = null;
+               ResolvedMember fieldSignature = ResolvedMemberImpl.readResolvedMember(s, context);
+               Set superMethodsCalled        = readSuperMethodsCalled(s);
+               sloc                          = readSourceLocation(s);
+               List aliases                  = readInTypeAliases(s);
+               ResolvedTypeMunger munger = new NewFieldTypeMunger(fieldSignature,superMethodsCalled,aliases);
+               if (sloc!=null) munger.setSourceLocation(sloc);
+               return munger;
+       }
+       
+       public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedType aspectType) {
+               //??? might give a field where a method is expected     
+               ResolvedType onType = aspectType.getWorld().resolve(getSignature().getDeclaringType());
+               if (onType.isRawType()) onType = onType.getGenericType();
+               
+               ResolvedMember ret = AjcMemberMaker.interFieldGetDispatcher(getSignature(), aspectType);
+               if (ResolvedType.matches(ret, member)) return getSignature();
+               ret = AjcMemberMaker.interFieldSetDispatcher(getSignature(), aspectType);
+               if (ResolvedType.matches(ret, member)) return getSignature();
+               ret = AjcMemberMaker.interFieldInterfaceGetter(getSignature(), onType, aspectType);
+               if (ResolvedType.matches(ret, member)) return getSignature();
+               ret = AjcMemberMaker.interFieldInterfaceSetter(getSignature(), onType, aspectType);
+               if (ResolvedType.matches(ret, member)) return getSignature();
+               return super.getMatchingSyntheticMember(member, aspectType);
+       }
+
+       /**
+     * see ResolvedTypeMunger.parameterizedFor(ResolvedType)
+     */
+       public ResolvedTypeMunger parameterizedFor(ResolvedType target) {
+               ResolvedType genericType = target;
+               if (target.isRawType() || target.isParameterizedType()) genericType = genericType.getGenericType();
+               ResolvedMember parameterizedSignature = null;
+               // If we are parameterizing it for a generic type, we just need to 'swap the letters' from the ones used 
+               // in the original ITD declaration to the ones used in the actual target type declaration.
+               if (target.isGenericType()) {
+                       TypeVariable vars[] = target.getTypeVariables();
+                       UnresolvedTypeVariableReferenceType[] varRefs = new UnresolvedTypeVariableReferenceType[vars.length];
+                       for (int i = 0; i < vars.length; i++) {
+                               varRefs[i] = new UnresolvedTypeVariableReferenceType(vars[i]);
+                       }
+                       parameterizedSignature = getSignature().parameterizedWith(varRefs,genericType,true,typeVariableAliases);
+               } else {
+                 // For raw and 'normal' parameterized targets  (e.g. Interface, Interface<String>)
+                 parameterizedSignature = getSignature().parameterizedWith(target.getTypeParameters(),genericType,target.isParameterizedType(),typeVariableAliases);
+               }
+               NewFieldTypeMunger nftm = new NewFieldTypeMunger(parameterizedSignature,getSuperMethodsCalled(),typeVariableAliases);
+           nftm.setDeclaredSignature(getSignature());
+           nftm.setSourceLocation(getSourceLocation());
+           return nftm;
+       }
+
+       public ResolvedTypeMunger parameterizeWith(Map m, World w) {
+               ResolvedMember parameterizedSignature = getSignature().parameterizedWith(m,w);
+               NewFieldTypeMunger nftm = new NewFieldTypeMunger(parameterizedSignature,getSuperMethodsCalled(),typeVariableAliases);
+               nftm.setDeclaredSignature(getSignature());
+               nftm.setSourceLocation(getSourceLocation());
+               return nftm;
+       }
+
+    public boolean equals(Object other) {
+        if (! (other instanceof NewFieldTypeMunger)) return false;
+        NewFieldTypeMunger o = (NewFieldTypeMunger) other;
+        return kind.equals(o.kind)
+                       && ((o.signature == null) ? (signature == null ) : signature.equals(o.signature))
+                       && ((o.declaredSignature == null) ? (declaredSignature == null ) : declaredSignature.equals(o.declaredSignature))
+                       && ((o.typeVariableAliases == null) ? (typeVariableAliases == null ) : typeVariableAliases.equals(o.typeVariableAliases));
+    }
+          
+    public int hashCode() {
+       int result = 17;
+        result = 37*result + kind.hashCode();
+        result = 37*result + ((signature == null) ? 0 : signature.hashCode());
+        result = 37*result + ((declaredSignature == null) ? 0 : declaredSignature.hashCode());
+        result = 37*result + ((typeVariableAliases == null) ? 0 : typeVariableAliases.hashCode());
+        return result;
+    }
+       
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/NewMethodTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/NewMethodTypeMunger.java
new file mode 100644 (file)
index 0000000..2fa3a57
--- /dev/null
@@ -0,0 +1,146 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.aspectj.bridge.ISourceLocation;
+
+public class NewMethodTypeMunger extends ResolvedTypeMunger {
+
+       public NewMethodTypeMunger(ResolvedMember signature, Set superMethodsCalled, List typeVariableAliases) {
+               super(Method, signature);
+               this.typeVariableAliases = typeVariableAliases;
+               this.setSuperMethodsCalled(superMethodsCalled);
+       }
+
+       public ResolvedMember getInterMethodBody(UnresolvedType aspectType) {
+               return AjcMemberMaker.interMethodBody(signature, aspectType);
+       }
+
+       /**
+        * If the munger has a declared signature
+        */
+       public ResolvedMember getDeclaredInterMethodBody(UnresolvedType aspectType, World w) {
+               if (declaredSignature != null) {
+                       ResolvedMember rm = declaredSignature.parameterizedWith(null, signature.getDeclaringType().resolve(w), false,
+                                       getTypeVariableAliases());
+                       return AjcMemberMaker.interMethodBody(rm, aspectType);
+               } else {
+                       return AjcMemberMaker.interMethodBody(signature, aspectType);
+               }
+       }
+
+       // public ResolvedMember getInterMethodDispatcher(UnresolvedType aspectType) {
+       // return AjcMemberMaker.interMethodDispatcher(signature, aspectType);
+       // }
+
+       public ResolvedMember getDeclaredInterMethodDispatcher(UnresolvedType aspectType, World w) {
+               if (declaredSignature != null) {
+                       ResolvedMember rm = declaredSignature.parameterizedWith(null, signature.getDeclaringType().resolve(w), false,
+                                       getTypeVariableAliases());
+                       return AjcMemberMaker.interMethodDispatcher(rm, aspectType);
+               } else {
+                       return AjcMemberMaker.interMethodDispatcher(signature, aspectType);
+               }
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               kind.write(s);
+               signature.write(s);
+               writeSuperMethodsCalled(s);
+               writeSourceLocation(s);
+               writeOutTypeAliases(s);
+       }
+
+       public static ResolvedTypeMunger readMethod(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               ISourceLocation sloc = null;
+               ResolvedMemberImpl rmImpl = ResolvedMemberImpl.readResolvedMember(s, context);
+               Set superMethodsCalled = readSuperMethodsCalled(s);
+               sloc = readSourceLocation(s);
+               List typeVarAliases = readInTypeAliases(s);
+
+               ResolvedTypeMunger munger = new NewMethodTypeMunger(rmImpl, superMethodsCalled, typeVarAliases);
+               if (sloc != null)
+                       munger.setSourceLocation(sloc);
+               return munger;
+       }
+
+       public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedType aspectType) {
+               ResolvedMember ret = AjcMemberMaker.interMethodDispatcher(getSignature(), aspectType);
+               if (ResolvedType.matches(ret, member))
+                       return getSignature();
+               return super.getMatchingSyntheticMember(member, aspectType);
+       }
+
+       /**
+        * see ResolvedTypeMunger.parameterizedFor(ResolvedType)
+        */
+       public ResolvedTypeMunger parameterizedFor(ResolvedType target) {
+               ResolvedType genericType = target;
+               if (target.isRawType() || target.isParameterizedType())
+                       genericType = genericType.getGenericType();
+               ResolvedMember parameterizedSignature = null;
+               // If we are parameterizing it for a generic type, we just need to 'swap the letters' from the ones used
+               // in the original ITD declaration to the ones used in the actual target type declaration.
+               if (target.isGenericType()) {
+                       TypeVariable vars[] = target.getTypeVariables();
+                       UnresolvedTypeVariableReferenceType[] varRefs = new UnresolvedTypeVariableReferenceType[vars.length];
+                       for (int i = 0; i < vars.length; i++) {
+                               varRefs[i] = new UnresolvedTypeVariableReferenceType(vars[i]);
+                       }
+                       parameterizedSignature = getSignature().parameterizedWith(varRefs, genericType, true, typeVariableAliases);
+               } else {
+                       // For raw and 'normal' parameterized targets (e.g. Interface, Interface<String>)
+                       parameterizedSignature = getSignature().parameterizedWith(target.getTypeParameters(), genericType,
+                                       target.isParameterizedType(), typeVariableAliases);
+               }
+               NewMethodTypeMunger nmtm = new NewMethodTypeMunger(parameterizedSignature, getSuperMethodsCalled(), typeVariableAliases);
+               nmtm.setDeclaredSignature(getSignature());
+               nmtm.setSourceLocation(getSourceLocation());
+               return nmtm;
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof NewMethodTypeMunger))
+                       return false;
+               NewMethodTypeMunger o = (NewMethodTypeMunger) other;
+               return kind.equals(o.kind)
+                               && ((o.signature == null) ? (signature == null) : signature.equals(o.signature))
+                               && ((o.declaredSignature == null) ? (declaredSignature == null) : declaredSignature.equals(o.declaredSignature))
+                               && ((o.typeVariableAliases == null) ? (typeVariableAliases == null) : typeVariableAliases
+                                               .equals(o.typeVariableAliases));
+       }
+
+       public int hashCode() {
+               int result = 17;
+               result = 37 * result + kind.hashCode();
+               result = 37 * result + ((signature == null) ? 0 : signature.hashCode());
+               result = 37 * result + ((declaredSignature == null) ? 0 : declaredSignature.hashCode());
+               result = 37 * result + ((typeVariableAliases == null) ? 0 : typeVariableAliases.hashCode());
+               return result;
+       }
+
+       public ResolvedTypeMunger parameterizeWith(Map m, World w) {
+               ResolvedMember parameterizedSignature = getSignature().parameterizedWith(m, w);
+               NewMethodTypeMunger nmtm = new NewMethodTypeMunger(parameterizedSignature, getSuperMethodsCalled(), typeVariableAliases);
+               nmtm.setDeclaredSignature(getSignature());
+               nmtm.setSourceLocation(getSourceLocation());
+               return nmtm;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/NewParentTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/NewParentTypeMunger.java
new file mode 100644 (file)
index 0000000..cc8ac44
--- /dev/null
@@ -0,0 +1,51 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class NewParentTypeMunger extends ResolvedTypeMunger {
+       ResolvedType newParent;
+       
+       public NewParentTypeMunger(ResolvedType newParent) {
+               super(Parent, null);
+               this.newParent = newParent;
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               throw new RuntimeException("unimplemented");
+       }
+
+
+       public ResolvedType getNewParent() {
+               return newParent;
+       }
+
+    public boolean equals(Object other) {
+        if (! (other instanceof NewParentTypeMunger)) return false;
+        NewParentTypeMunger o = (NewParentTypeMunger) other;
+        return newParent.equals(o.newParent);
+    }
+          
+    private volatile int hashCode = 0;
+    public int hashCode() {
+           if (hashCode == 0) {
+               int result = 17;
+               result = 37*result + newParent.hashCode();
+               hashCode = result;
+           }
+        return hashCode;
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/PerObjectInterfaceTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/PerObjectInterfaceTypeMunger.java
new file mode 100644 (file)
index 0000000..05e0077
--- /dev/null
@@ -0,0 +1,91 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     PARC                 initial implementation
+ *     Alexandre Vasseur    rearchitected for #75442 finer grained matching
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import org.aspectj.weaver.patterns.PerFromSuper;
+import org.aspectj.weaver.patterns.PerObject;
+import org.aspectj.weaver.patterns.PerThisOrTargetPointcutVisitor;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.patterns.TypePattern;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class PerObjectInterfaceTypeMunger extends ResolvedTypeMunger {
+
+    private final UnresolvedType interfaceType;
+    private final Pointcut testPointcut;
+    private TypePattern lazyTestTypePattern;
+    
+    public boolean equals(Object other) {
+       if (other==null || !(other instanceof PerObjectInterfaceTypeMunger)) return false;
+               PerObjectInterfaceTypeMunger o = (PerObjectInterfaceTypeMunger)other;
+       return ((testPointcut == null) ? (o.testPointcut == null ) : testPointcut.equals(o.testPointcut))
+                       && ((lazyTestTypePattern == null) ? (o.lazyTestTypePattern == null ) : lazyTestTypePattern.equals(o.lazyTestTypePattern));
+    }
+
+    private volatile int hashCode = 0;
+    public int hashCode() {
+       if (hashCode == 0) {
+               int result = 17;
+           result = 37*result + ((testPointcut == null) ? 0 : testPointcut.hashCode());
+           result = 37*result + ((lazyTestTypePattern == null) ? 0 : lazyTestTypePattern.hashCode());
+           hashCode = result;
+               }
+           return hashCode;
+    }
+    
+    public PerObjectInterfaceTypeMunger(UnresolvedType aspectType, Pointcut testPointcut) {
+        super(PerObjectInterface, null);
+        this.testPointcut = testPointcut;
+        this.interfaceType = AjcMemberMaker.perObjectInterfaceType(aspectType);
+    }
+
+    private TypePattern getTestTypePattern(ResolvedType aspectType) {
+        if (lazyTestTypePattern == null) {
+            final boolean isPerThis;
+            if (aspectType.getPerClause() instanceof PerFromSuper) {
+                PerFromSuper ps = (PerFromSuper) aspectType.getPerClause();
+                isPerThis = ((PerObject) ps.lookupConcretePerClause(aspectType)).isThis();
+            } else {
+                isPerThis = ((PerObject) aspectType.getPerClause()).isThis();
+            }
+            PerThisOrTargetPointcutVisitor v = new PerThisOrTargetPointcutVisitor(!isPerThis, aspectType);
+            lazyTestTypePattern = v.getPerTypePointcut(testPointcut);
+            // reset hashCode so that its recalculated with the new lazyTestTypePattern
+            hashCode = 0;
+        }
+        return lazyTestTypePattern;
+    }
+
+    public void write(DataOutputStream s) throws IOException {
+        throw new RuntimeException("shouldn't be serialized");
+    }
+
+    public UnresolvedType getInterfaceType() {
+        return interfaceType;
+    }
+
+    public Pointcut getTestPointcut() {
+        return testPointcut;
+    }
+
+    public boolean matches(ResolvedType matchType, ResolvedType aspectType) {
+        if (matchType.isInterface()) return false;
+        return getTestTypePattern(aspectType).matchesStatically(matchType);
+    }
+    
+    public boolean isLateMunger() {
+       return true;
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/PerTypeWithinTargetTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/PerTypeWithinTargetTypeMunger.java
new file mode 100644 (file)
index 0000000..029354b
--- /dev/null
@@ -0,0 +1,81 @@
+/* *******************************************************************
+ * Copyright (c) 2005 IBM, Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.patterns.PerTypeWithin;
+import org.aspectj.weaver.patterns.Pointcut;
+
+// PTWIMPL Target type munger adds the localAspectOf() method
+public class PerTypeWithinTargetTypeMunger extends ResolvedTypeMunger {
+       private UnresolvedType aspectType;
+       private PerTypeWithin testPointcut;
+
+       public PerTypeWithinTargetTypeMunger(UnresolvedType aspectType, PerTypeWithin testPointcut) {
+               super(PerTypeWithinInterface, null);
+               this.aspectType    = aspectType;
+               this.testPointcut  = testPointcut;
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof PerTypeWithinTargetTypeMunger)) return false;
+               PerTypeWithinTargetTypeMunger o = (PerTypeWithinTargetTypeMunger)other;
+               return ((o.testPointcut == null) ? (testPointcut == null ) : testPointcut.equals(o.testPointcut))
+                               && ((o.aspectType == null) ? (aspectType == null ) : aspectType.equals(o.aspectType));
+       }
+
+       private volatile int hashCode = 0;
+       public int hashCode() {
+               if (hashCode == 0) {
+                       int result = 17;
+                   result = 37*result + ((testPointcut == null) ? 0 : testPointcut.hashCode());
+                   result = 37*result + ((aspectType == null) ? 0 : aspectType.hashCode());
+                   hashCode = result;
+               }
+           return hashCode;
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               throw new RuntimeException("shouldn't be serialized");
+       }
+       
+       public UnresolvedType getAspectType() {
+               return aspectType;
+       }
+
+       public Pointcut getTestPointcut() {
+               return testPointcut;
+       }
+       
+       // This is a lexical within() so if you say PerTypeWithin(Test) and matchType is an
+       // inner type (e.g. Test$NestedType) then it should match successfully
+       // Does not match if the target is an interface
+       public boolean matches(ResolvedType matchType, ResolvedType aspectType) {
+               return isWithinType(matchType).alwaysTrue() && 
+                      !matchType.isInterface();
+       }
+       
+       private FuzzyBoolean isWithinType(ResolvedType type) {
+               while (type != null) {
+                       if (testPointcut.getTypePattern().matchesStatically(type)) {
+                               return FuzzyBoolean.YES;
+                       }
+                       type = type.getDeclaringType();
+               }
+               return FuzzyBoolean.NO;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/PoliceExtensionUse.java b/org.aspectj.matcher/src/org/aspectj/weaver/PoliceExtensionUse.java
new file mode 100644 (file)
index 0000000..e35a9b8
--- /dev/null
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM 
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Andy Clement - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.weaver;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.weaver.patterns.AbstractPatternNodeVisitor;
+import org.aspectj.weaver.patterns.AndPointcut;
+import org.aspectj.weaver.patterns.KindedPointcut;
+import org.aspectj.weaver.patterns.NotPointcut;
+import org.aspectj.weaver.patterns.OrPointcut;
+import org.aspectj.weaver.patterns.Pointcut;
+
+/**
+ * Walks a pointcut and determines if the synchronization related designators have been used: lock() or unlock()
+ */
+public class PoliceExtensionUse extends AbstractPatternNodeVisitor {
+
+       private boolean synchronizationDesignatorEncountered;
+       private World world;
+       private Pointcut p;
+
+       public PoliceExtensionUse(World w, Pointcut p) {
+               this.world = w;
+               this.p = p;
+               this.synchronizationDesignatorEncountered = false;
+       }
+
+       public boolean synchronizationDesignatorEncountered() {
+               return synchronizationDesignatorEncountered;
+       }
+
+       public Object visit(KindedPointcut node, Object data) {
+               if (world == null)
+                       return super.visit(node, data); // error scenario can sometimes lead to this LazyClassGen.toLongString()
+               if (node.getKind() == Shadow.SynchronizationLock || node.getKind() == Shadow.SynchronizationUnlock)
+                       synchronizationDesignatorEncountered = true;
+               // Check it!
+               if (!world.isJoinpointSynchronizationEnabled()) {
+                       if (node.getKind() == Shadow.SynchronizationLock) {
+                               IMessage m = MessageUtil.warn(
+                                               "lock() pointcut designator cannot be used without the option -Xjoinpoints:synchronization", p
+                                                               .getSourceLocation());
+                               world.getMessageHandler().handleMessage(m);
+                       } else if (node.getKind() == Shadow.SynchronizationUnlock) {
+                               IMessage m = MessageUtil.warn(
+                                               "unlock() pointcut designator cannot be used without the option -Xjoinpoints:synchronization", p
+                                                               .getSourceLocation());
+                               world.getMessageHandler().handleMessage(m);
+                       }
+               }
+               return super.visit(node, data);
+       }
+
+       public Object visit(AndPointcut node, Object data) {
+               node.getLeft().accept(this, data);
+               node.getRight().accept(this, data);
+               return node;
+       }
+
+       public Object visit(NotPointcut node, Object data) {
+               node.getNegatedPointcut().accept(this, data);
+               return node;
+       }
+
+       public Object visit(OrPointcut node, Object data) {
+               node.getLeft().accept(this, data);
+               node.getRight().accept(this, data);
+               return node;
+       }
+
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Position.java b/org.aspectj.matcher/src/org/aspectj/weaver/Position.java
new file mode 100644 (file)
index 0000000..710958d
--- /dev/null
@@ -0,0 +1,32 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+public class Position implements IHasPosition {
+       private int start, end;
+       
+       public Position(int start, int end) {
+               this.start = start;
+               this.end = end;
+       }
+
+       public int getEnd() {
+               return end;
+       }
+
+       public int getStart() {
+               return start;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/PrivilegedAccessMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/PrivilegedAccessMunger.java
new file mode 100644 (file)
index 0000000..ca9152b
--- /dev/null
@@ -0,0 +1,69 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class PrivilegedAccessMunger extends ResolvedTypeMunger {
+       public PrivilegedAccessMunger(ResolvedMember member) {
+               super(PrivilegedAccess, member);
+       }
+       
+
+       public void write(DataOutputStream s) throws IOException {
+               throw new RuntimeException("shouldn't be serialized");
+       }
+
+       public ResolvedMember getMember() {
+               return getSignature();
+       }
+
+       public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedType aspectType) {
+               ResolvedMember ret;
+               if (getSignature().getKind() == Member.FIELD) {
+                       ret = AjcMemberMaker.privilegedAccessMethodForFieldGet(aspectType, getSignature());
+                       if (ResolvedType.matches(ret, member)) return getSignature();
+                       ret = AjcMemberMaker.privilegedAccessMethodForFieldSet(aspectType, getSignature());
+                       if (ResolvedType.matches(ret, member)) return getSignature();
+               } else {
+                       //System.err.println("sig: " + getSignature());
+                       ret = AjcMemberMaker.privilegedAccessMethodForMethod(aspectType, getSignature());
+                       if (ResolvedType.matches(ret, member)) return getSignature();
+               }
+               return null;
+       }
+
+    public boolean equals(Object other) {
+        if (! (other instanceof PrivilegedAccessMunger)) return false;
+        PrivilegedAccessMunger o = (PrivilegedAccessMunger) other;
+        return kind.equals(o.kind)
+                       && ((o.signature == null) ? (signature == null ) : signature.equals(o.signature))
+                       && ((o.declaredSignature == null) ? (declaredSignature == null ) : declaredSignature.equals(o.declaredSignature))
+                       && ((o.typeVariableAliases == null) ? (typeVariableAliases == null ) : typeVariableAliases.equals(o.typeVariableAliases));
+    }
+          
+    public int hashCode() {
+       int result = 17;
+        result = 37*result + kind.hashCode();
+        result = 37*result + ((signature == null) ? 0 : signature.hashCode());
+        result = 37*result + ((declaredSignature == null) ? 0 : declaredSignature.hashCode());
+        result = 37*result + ((typeVariableAliases == null) ? 0 : typeVariableAliases.hashCode());
+        return result;
+    }
+       
+       public boolean existsToSupportShadowMunging() {
+               return true;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceType.java b/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceType.java
new file mode 100644 (file)
index 0000000..8961e21
--- /dev/null
@@ -0,0 +1,810 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ *     Andy Clement - June 2005 - separated out from ResolvedType
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.weaver.patterns.Declare;
+import org.aspectj.weaver.patterns.PerClause;
+
+/**
+ * A reference type represents some 'real' type, not a primitive, not an array - but a real type, for example java.util.List. Each
+ * ReferenceType has a delegate that is the underlying artifact - either an eclipse artifact or a bcel artifact. If the type
+ * represents a raw type (i.e. there is a generic form) then the genericType field is set to point to the generic type. If it is for
+ * a parameterized type then the generic type is also set to point to the generic form.
+ */
+public class ReferenceType extends ResolvedType {
+
+       /**
+        * For generic types, this list holds references to all the derived raw and parameterized versions. We need this so that if the
+        * generic delegate is swapped during incremental compilation, the delegate of the derivatives is swapped also.
+        */
+       private final List/* ReferenceType */derivativeTypes = new ArrayList();
+
+       /**
+        * For parameterized types (or the raw type) - this field points to the actual reference type from which they are derived.
+        */
+       ReferenceType genericType = null;
+
+       ReferenceTypeDelegate delegate = null;
+       int startPos = 0;
+       int endPos = 0;
+
+       // cached values for members
+       ResolvedMember[] parameterizedMethods = null;
+       ResolvedMember[] parameterizedFields = null;
+       ResolvedMember[] parameterizedPointcuts = null;
+       ResolvedType[] parameterizedInterfaces = null;
+       Collection parameterizedDeclares = null;
+       Collection parameterizedTypeMungers = null;
+
+       // ??? should set delegate before any use
+       public ReferenceType(String signature, World world) {
+               super(signature, world);
+       }
+
+       public ReferenceType(String signature, String signatureErasure, World world) {
+               super(signature, signatureErasure, world);
+       }
+
+       public static ReferenceType fromTypeX(UnresolvedType tx, World world) {
+               ReferenceType rt = new ReferenceType(tx.getErasureSignature(), world);
+               rt.typeKind = tx.typeKind;
+               return rt;
+       }
+
+       /**
+        * Constructor used when creating a parameterized type.
+        */
+       public ReferenceType(ResolvedType theGenericType, ResolvedType[] theParameters, World aWorld) {
+               super(makeParameterizedSignature(theGenericType, theParameters), theGenericType.signatureErasure, aWorld);
+               ReferenceType genericReferenceType = (ReferenceType) theGenericType;
+               this.typeParameters = theParameters;
+               this.genericType = genericReferenceType;
+               this.typeKind = TypeKind.PARAMETERIZED;
+               this.delegate = genericReferenceType.getDelegate();
+               genericReferenceType.addDependentType(this);
+       }
+
+       /**
+        * Constructor used when creating a raw type.
+        */
+       // public ReferenceType(
+       // ResolvedType theGenericType,
+       // World aWorld) {
+       // super(theGenericType.getErasureSignature(),
+       // theGenericType.getErasureSignature(),
+       // aWorld);
+       // ReferenceType genericReferenceType = (ReferenceType) theGenericType;
+       // this.typeParameters = null;
+       // this.genericType = genericReferenceType;
+       // this.typeKind = TypeKind.RAW;
+       // this.delegate = genericReferenceType.getDelegate();
+       // genericReferenceType.addDependentType(this);
+       // }
+       private void addDependentType(ReferenceType dependent) {
+               this.derivativeTypes.add(dependent);
+       }
+
+       public String getSignatureForAttribute() {
+               if (genericType == null || typeParameters == null)
+                       return getSignature();
+               return makeDeclaredSignature(genericType, typeParameters);
+       }
+
+       /**
+        * Create a reference type for a generic type
+        */
+       public ReferenceType(UnresolvedType genericType, World world) {
+               super(genericType.getSignature(), world);
+               typeKind = TypeKind.GENERIC;
+       }
+
+       public boolean isClass() {
+               return delegate.isClass();
+       }
+
+       public boolean isGenericType() {
+               return !isParameterizedType() && !isRawType() && delegate.isGeneric();
+       }
+
+       public String getGenericSignature() {
+               String sig = delegate.getDeclaredGenericSignature();
+               return (sig == null) ? "" : sig;
+       }
+
+       public AnnotationAJ[] getAnnotations() {
+               return delegate.getAnnotations();
+       }
+
+       public void addAnnotation(AnnotationAJ annotationX) {
+               delegate.addAnnotation(annotationX);
+       }
+
+       public boolean hasAnnotation(UnresolvedType ofType) {
+               return delegate.hasAnnotation(ofType);
+       }
+
+       public ResolvedType[] getAnnotationTypes() {
+               if (delegate == null) {
+                       throw new BCException("Unexpected null delegate for type " + this.getName());
+               }
+               return delegate.getAnnotationTypes();
+       }
+
+       public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
+               AnnotationAJ[] axs = delegate.getAnnotations();
+               if (axs == null) {
+                       return null;
+               }
+               for (int i = 0; i < axs.length; i++) {
+                       if (axs[i].getTypeSignature().equals(ofType.getSignature())) {
+                               return axs[i];
+                       }
+               }
+               return null;
+       }
+
+       public boolean isAspect() {
+               return delegate.isAspect();
+       }
+
+       public boolean isAnnotationStyleAspect() {
+               return delegate.isAnnotationStyleAspect();
+       }
+
+       public boolean isEnum() {
+               return delegate.isEnum();
+       }
+
+       public boolean isAnnotation() {
+               return delegate.isAnnotation();
+       }
+
+       public boolean isAnonymous() {
+               return delegate.isAnonymous();
+       }
+
+       public boolean isNested() {
+               return delegate.isNested();
+       }
+
+       public ResolvedType getOuterClass() {
+               return delegate.getOuterClass();
+       }
+
+       public String getRetentionPolicy() {
+               return delegate.getRetentionPolicy();
+       }
+
+       public boolean isAnnotationWithRuntimeRetention() {
+               return delegate.isAnnotationWithRuntimeRetention();
+       }
+
+       public boolean canAnnotationTargetType() {
+               return delegate.canAnnotationTargetType();
+       }
+
+       public AnnotationTargetKind[] getAnnotationTargetKinds() {
+               return delegate.getAnnotationTargetKinds();
+       }
+
+       // true iff the statement "this = (ThisType) other" would compile
+       public boolean isCoerceableFrom(ResolvedType o) {
+               ResolvedType other = o.resolve(world);
+
+               if (this.isAssignableFrom(other) || other.isAssignableFrom(this)) {
+                       return true;
+               }
+
+               if (this.isParameterizedType() && other.isParameterizedType()) {
+                       return isCoerceableFromParameterizedType(other);
+               }
+
+               if (!this.isInterface() && !other.isInterface()) {
+                       return false;
+               }
+               if (this.isFinal() || other.isFinal()) {
+                       return false;
+               }
+               // ??? needs to be Methods, not just declared methods? JLS 5.5 unclear
+               ResolvedMember[] a = getDeclaredMethods();
+               ResolvedMember[] b = other.getDeclaredMethods(); // ??? is this cast
+               // always safe
+               for (int ai = 0, alen = a.length; ai < alen; ai++) {
+                       for (int bi = 0, blen = b.length; bi < blen; bi++) {
+                               if (!b[bi].isCompatibleWith(a[ai]))
+                                       return false;
+                       }
+               }
+               return true;
+       }
+
+       private final boolean isCoerceableFromParameterizedType(ResolvedType other) {
+               if (!other.isParameterizedType())
+                       return false;
+               ResolvedType myRawType = (ResolvedType) getRawType();
+               ResolvedType theirRawType = (ResolvedType) other.getRawType();
+               if (myRawType == theirRawType) {
+                       if (getTypeParameters().length == other.getTypeParameters().length) {
+                               // there's a chance it can be done
+                               ResolvedType[] myTypeParameters = getResolvedTypeParameters();
+                               ResolvedType[] theirTypeParameters = other.getResolvedTypeParameters();
+                               for (int i = 0; i < myTypeParameters.length; i++) {
+                                       if (myTypeParameters[i] != theirTypeParameters[i]) {
+                                               // thin ice now... but List<String> may still be
+                                               // coerceable from e.g. List<T>
+                                               if (myTypeParameters[i].isGenericWildcard()) {
+                                                       BoundedReferenceType wildcard = (BoundedReferenceType) myTypeParameters[i];
+                                                       if (!wildcard.canBeCoercedTo(theirTypeParameters[i]))
+                                                               return false;
+                                               } else if (myTypeParameters[i].isTypeVariableReference()) {
+                                                       TypeVariableReferenceType tvrt = (TypeVariableReferenceType) myTypeParameters[i];
+                                                       TypeVariable tv = tvrt.getTypeVariable();
+                                                       tv.resolve(world);
+                                                       if (!tv.canBeBoundTo(theirTypeParameters[i]))
+                                                               return false;
+                                               } else if (theirTypeParameters[i].isTypeVariableReference()) {
+                                                       TypeVariableReferenceType tvrt = (TypeVariableReferenceType) theirTypeParameters[i];
+                                                       TypeVariable tv = tvrt.getTypeVariable();
+                                                       tv.resolve(world);
+                                                       if (!tv.canBeBoundTo(myTypeParameters[i]))
+                                                               return false;
+                                               } else {
+                                                       return false;
+                                               }
+                                       }
+                               }
+                               return true;
+                       }
+               } else {
+                       // we do this walk for situations like the following:
+                       // Base<T>, Sub<S,T> extends Base<S>
+                       // is Sub<Y,Z> coerceable from Base<X> ???
+                       for (Iterator i = getDirectSupertypes(); i.hasNext();) {
+                               ReferenceType parent = (ReferenceType) i.next();
+                               if (parent.isCoerceableFromParameterizedType(other))
+                                       return true;
+                       }
+               }
+               return false;
+       }
+
+       public boolean isAssignableFrom(ResolvedType other) {
+               return isAssignableFrom(other, false);
+       }
+
+       // true iff the statement "this = other" would compile.
+       public boolean isAssignableFrom(ResolvedType other, boolean allowMissing) {
+               if (other.isPrimitiveType()) {
+                       if (!world.isInJava5Mode())
+                               return false;
+                       if (ResolvedType.validBoxing.contains(this.getSignature() + other.getSignature()))
+                               return true;
+               }
+               if (this == other)
+                       return true;
+               if (this.getSignature().equals(ResolvedType.OBJECT.getSignature()))
+                       return true;
+
+               if ((this.isRawType() || this.isGenericType()) && other.isParameterizedType()) {
+                       if (isAssignableFrom((ResolvedType) other.getRawType()))
+                               return true;
+               }
+               if (this.isRawType() && other.isGenericType()) {
+                       if (isAssignableFrom((ResolvedType) other.getRawType()))
+                               return true;
+               }
+               if (this.isGenericType() && other.isRawType()) {
+                       if (isAssignableFrom(other.getGenericType()))
+                               return true;
+               }
+
+               if (this.isParameterizedType()) {
+                       // look at wildcards...
+                       if (((ReferenceType) this.getRawType()).isAssignableFrom(other)) {
+                               boolean wildcardsAllTheWay = true;
+                               ResolvedType[] myParameters = this.getResolvedTypeParameters();
+                               for (int i = 0; i < myParameters.length; i++) {
+                                       if (!myParameters[i].isGenericWildcard()) {
+                                               wildcardsAllTheWay = false;
+                                       } else {
+                                               BoundedReferenceType boundedRT = (BoundedReferenceType) myParameters[i];
+                                               if (boundedRT.isExtends() || boundedRT.isSuper()) {
+                                                       wildcardsAllTheWay = false;
+                                               }
+                                       }
+                               }
+                               if (wildcardsAllTheWay && !other.isParameterizedType())
+                                       return true;
+                               // we have to match by parameters one at a time
+                               ResolvedType[] theirParameters = other.getResolvedTypeParameters();
+                               boolean parametersAssignable = true;
+                               if (myParameters.length == theirParameters.length) {
+                                       for (int i = 0; i < myParameters.length; i++) {
+                                               if (myParameters[i] == theirParameters[i])
+                                                       continue;
+                                               if (myParameters[i].isAssignableFrom(theirParameters[i], allowMissing)) {
+                                                       continue;
+                                               }
+                                               if (!myParameters[i].isGenericWildcard()) {
+                                                       parametersAssignable = false;
+                                                       break;
+                                               } else {
+                                                       BoundedReferenceType wildcardType = (BoundedReferenceType) myParameters[i];
+                                                       if (!wildcardType.alwaysMatches(theirParameters[i])) {
+                                                               parametersAssignable = false;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       parametersAssignable = false;
+                               }
+                               if (parametersAssignable)
+                                       return true;
+                       }
+               }
+
+               if (isTypeVariableReference() && !other.isTypeVariableReference()) { // eg
+                       // .
+                       // this
+                       // =
+                       // T
+                       // other
+                       // =
+                       // Ljava
+                       // /
+                       // lang
+                       // /
+                       // Object
+                       // ;
+                       TypeVariable aVar = ((TypeVariableReference) this).getTypeVariable();
+                       return aVar.resolve(world).canBeBoundTo(other);
+               }
+
+               if (other.isTypeVariableReference()) {
+                       TypeVariableReferenceType otherType = (TypeVariableReferenceType) other;
+                       if (this instanceof TypeVariableReference) {
+                               return ((TypeVariableReference) this).getTypeVariable().resolve(world).canBeBoundTo(
+                                               otherType.getTypeVariable().getFirstBound().resolve(world));// pr171952
+                               // return
+                               // ((TypeVariableReference)this).getTypeVariable()==otherType
+                               // .getTypeVariable();
+                       } else {
+                               // FIXME asc should this say canBeBoundTo??
+                               return this.isAssignableFrom(otherType.getTypeVariable().getFirstBound().resolve(world));
+                       }
+               }
+
+               if (allowMissing && other.isMissing())
+                       return false;
+
+               for (Iterator i = other.getDirectSupertypes(); i.hasNext();) {
+                       if (this.isAssignableFrom((ResolvedType) i.next(), allowMissing))
+                               return true;
+               }
+               return false;
+       }
+
+       public ISourceContext getSourceContext() {
+               return delegate.getSourceContext();
+       }
+
+       public ISourceLocation getSourceLocation() {
+               ISourceContext isc = delegate.getSourceContext();
+               return isc.makeSourceLocation(new Position(startPos, endPos));
+       }
+
+       public boolean isExposedToWeaver() {
+               return (delegate == null) || delegate.isExposedToWeaver(); // ??? where
+               // does this
+               // belong
+       }
+
+       public WeaverStateInfo getWeaverState() {
+               return delegate.getWeaverState();
+       }
+
+       public ResolvedMember[] getDeclaredFields() {
+               if (parameterizedFields != null)
+                       return parameterizedFields;
+               if (isParameterizedType() || isRawType()) {
+                       ResolvedMember[] delegateFields = delegate.getDeclaredFields();
+                       parameterizedFields = new ResolvedMember[delegateFields.length];
+                       for (int i = 0; i < delegateFields.length; i++) {
+                               parameterizedFields[i] = delegateFields[i].parameterizedWith(getTypesForMemberParameterization(), this,
+                                               isParameterizedType());
+                       }
+                       return parameterizedFields;
+               } else {
+                       return delegate.getDeclaredFields();
+               }
+       }
+
+       /**
+        * Find out from the generic signature the true signature of any interfaces I implement. If I am parameterized, these may then
+        * need to be parameterized before returning.
+        */
+       public ResolvedType[] getDeclaredInterfaces() {
+               if (parameterizedInterfaces != null)
+                       return parameterizedInterfaces;
+               if (isParameterizedType()) {
+                       ResolvedType[] delegateInterfaces = delegate.getDeclaredInterfaces();
+                       // UnresolvedType[] paramTypes =
+                       // getTypesForMemberParameterization();
+                       parameterizedInterfaces = new ResolvedType[delegateInterfaces.length];
+                       for (int i = 0; i < delegateInterfaces.length; i++) {
+                               // We may have to sub/super set the set of parametertypes if the
+                               // implemented interface
+                               // needs more or less than this type does. (pr124803/pr125080)
+
+                               if (delegateInterfaces[i].isParameterizedType()) {
+                                       parameterizedInterfaces[i] = delegateInterfaces[i].parameterize(getMemberParameterizationMap()).resolve(world);
+                               } else {
+                                       parameterizedInterfaces[i] = delegateInterfaces[i];
+                               }
+                       }
+                       return parameterizedInterfaces;
+               } else if (isRawType()) {
+                       ResolvedType[] delegateInterfaces = delegate.getDeclaredInterfaces();
+                       UnresolvedType[] paramTypes = getTypesForMemberParameterization();
+                       parameterizedInterfaces = new ResolvedType[delegateInterfaces.length];
+                       for (int i = 0; i < parameterizedInterfaces.length; i++) {
+                               parameterizedInterfaces[i] = delegateInterfaces[i];
+                               if (parameterizedInterfaces[i].isGenericType()) {
+                                       // a generic supertype of a raw type is replaced by its raw
+                                       // equivalent
+                                       parameterizedInterfaces[i] = parameterizedInterfaces[i].getRawType().resolve(getWorld());
+                               } else if (parameterizedInterfaces[i].isParameterizedType()) {
+                                       // a parameterized supertype collapses any type vars to
+                                       // their upper bounds
+                                       UnresolvedType[] toUseForParameterization = determineThoseTypesToUse(parameterizedInterfaces[i], paramTypes);
+                                       parameterizedInterfaces[i] = parameterizedInterfaces[i].parameterizedWith(toUseForParameterization);
+                               }
+                       }
+                       return parameterizedInterfaces;
+               }
+               return delegate.getDeclaredInterfaces();
+       }
+
+       /**
+        * Locates the named type variable in the list of those on this generic type and returns the type parameter from the second list
+        * supplied. Returns null if it can't be found
+        */
+       // private UnresolvedType findTypeParameterInList(String name,
+       // TypeVariable[] tvarsOnThisGenericType, UnresolvedType[]
+       // paramTypes) {
+       // int position = -1;
+       // for (int i = 0; i < tvarsOnThisGenericType.length; i++) {
+       // TypeVariable tv = tvarsOnThisGenericType[i];
+       // if (tv.getName().equals(name)) position = i;
+       // }
+       // if (position == -1 ) return null;
+       // return paramTypes[position];
+       // }
+       /**
+        * It is possible this type has multiple type variables but the interface we are about to parameterize only uses a subset - this
+        * method determines the subset to use by looking at the type variable names used. For example: <code>
+        * class Foo<T extends String,E extends Number> implements SuperInterface<T> {}
+        * </code> where <code>
+        * interface SuperInterface<Z> {}
+        * </code> In that
+        * example, a use of the 'Foo' raw type should know that it implements the SuperInterface<String>.
+        */
+       private UnresolvedType[] determineThoseTypesToUse(ResolvedType parameterizedInterface, UnresolvedType[] paramTypes) {
+               // What are the type parameters for the supertype?
+               UnresolvedType[] tParms = parameterizedInterface.getTypeParameters();
+               UnresolvedType[] retVal = new UnresolvedType[tParms.length];
+
+               // Go through the supertypes type parameters, if any of them is a type
+               // variable, use the
+               // real type variable on the declaring type.
+
+               // it is possibly overkill to look up the type variable - ideally the
+               // entry in the type parameter list for the
+               // interface should be the a ref to the type variable in the current
+               // type ... but I'm not 100% confident right now.
+               for (int i = 0; i < tParms.length; i++) {
+                       UnresolvedType tParm = tParms[i];
+                       if (tParm.isTypeVariableReference()) {
+                               TypeVariableReference tvrt = (TypeVariableReference) tParm;
+                               TypeVariable tv = tvrt.getTypeVariable();
+                               int rank = getRank(tv.getName());
+                               // -1 probably means it is a reference to a type variable on the
+                               // outer generic type (see pr129566)
+                               if (rank != -1) {
+                                       retVal[i] = paramTypes[rank];
+                               } else {
+                                       retVal[i] = tParms[i];
+                               }
+                       } else {
+                               retVal[i] = tParms[i];
+                       }
+
+               }
+               return retVal;
+       }
+
+       /**
+        * Returns the position within the set of type variables for this type for the specified type variable name. Returns -1 if there
+        * is no type variable with the specified name.
+        */
+       private int getRank(String tvname) {
+               TypeVariable[] thisTypesTVars = getGenericType().getTypeVariables();
+               for (int i = 0; i < thisTypesTVars.length; i++) {
+                       TypeVariable tv = thisTypesTVars[i];
+                       if (tv.getName().equals(tvname))
+                               return i;
+               }
+               return -1;
+       }
+
+       public ResolvedMember[] getDeclaredMethods() {
+               if (parameterizedMethods != null)
+                       return parameterizedMethods;
+               if (isParameterizedType() || isRawType()) {
+                       ResolvedMember[] delegateMethods = delegate.getDeclaredMethods();
+                       UnresolvedType[] parameters = getTypesForMemberParameterization();
+                       parameterizedMethods = new ResolvedMember[delegateMethods.length];
+                       for (int i = 0; i < delegateMethods.length; i++) {
+                               parameterizedMethods[i] = delegateMethods[i].parameterizedWith(parameters, this, isParameterizedType());
+                       }
+                       return parameterizedMethods;
+               } else {
+                       return delegate.getDeclaredMethods();
+               }
+       }
+
+       public ResolvedMember[] getDeclaredPointcuts() {
+               if (parameterizedPointcuts != null)
+                       return parameterizedPointcuts;
+               if (isParameterizedType()) {
+                       ResolvedMember[] delegatePointcuts = delegate.getDeclaredPointcuts();
+                       parameterizedPointcuts = new ResolvedMember[delegatePointcuts.length];
+                       for (int i = 0; i < delegatePointcuts.length; i++) {
+                               parameterizedPointcuts[i] = delegatePointcuts[i].parameterizedWith(getTypesForMemberParameterization(), this,
+                                               isParameterizedType());
+                       }
+                       return parameterizedPointcuts;
+               } else {
+                       return delegate.getDeclaredPointcuts();
+               }
+       }
+
+       private UnresolvedType[] getTypesForMemberParameterization() {
+               UnresolvedType[] parameters = null;
+               if (isParameterizedType()) {
+                       parameters = getTypeParameters();
+               } else if (isRawType()) {
+                       // raw type, use upper bounds of type variables on generic type
+                       TypeVariable[] tvs = getGenericType().getTypeVariables();
+                       parameters = new UnresolvedType[tvs.length];
+                       for (int i = 0; i < tvs.length; i++) {
+                               parameters[i] = tvs[i].getFirstBound();
+                       }
+               }
+               return parameters;
+       }
+
+       public UnresolvedType getRawType() {
+               return super.getRawType().resolve(getWorld());
+       }
+
+       public TypeVariable[] getTypeVariables() {
+               if (this.typeVariables == null) {
+                       this.typeVariables = delegate.getTypeVariables();
+                       for (int i = 0; i < this.typeVariables.length; i++) {
+                               this.typeVariables[i].resolve(world);
+                       }
+               }
+               return this.typeVariables;
+       }
+
+       public PerClause getPerClause() {
+               PerClause pclause = delegate.getPerClause();
+               if (isParameterizedType()) { // could cache the result here...
+                       Map parameterizationMap = getAjMemberParameterizationMap();
+                       pclause = (PerClause) pclause.parameterizeWith(parameterizationMap, world);
+               }
+               return pclause;
+       }
+
+       public Collection getDeclares() {
+               if (parameterizedDeclares != null)
+                       return parameterizedDeclares;
+               Collection declares = null;
+               if (ajMembersNeedParameterization()) {
+                       Collection genericDeclares = delegate.getDeclares();
+                       parameterizedDeclares = new ArrayList();
+                       Map parameterizationMap = getAjMemberParameterizationMap();
+                       for (Iterator iter = genericDeclares.iterator(); iter.hasNext();) {
+                               Declare declareStatement = (Declare) iter.next();
+                               parameterizedDeclares.add(declareStatement.parameterizeWith(parameterizationMap, world));
+                       }
+                       declares = parameterizedDeclares;
+               } else {
+                       declares = delegate.getDeclares();
+               }
+               for (Iterator iter = declares.iterator(); iter.hasNext();) {
+                       Declare d = (Declare) iter.next();
+                       d.setDeclaringType(this);
+               }
+               return declares;
+       }
+
+       protected Collection getTypeMungers() {
+               return delegate.getTypeMungers();
+       }
+
+       // GENERICITDFIX
+       // // Map parameterizationMap = getAjMemberParameterizationMap();
+       //              
+       // // if (parameterizedTypeMungers != null) return parameterizedTypeMungers;
+       // Collection ret = null;
+       // if (ajMembersNeedParameterization()) {
+       // Collection genericDeclares = delegate.getTypeMungers();
+       // parameterizedTypeMungers = new ArrayList();
+       // Map parameterizationMap = getAjMemberParameterizationMap();
+       // for (Iterator iter = genericDeclares.iterator(); iter.hasNext();) {
+       // ConcreteTypeMunger munger = (ConcreteTypeMunger)iter.next();
+       // parameterizedTypeMungers.add(munger.parameterizeWith(parameterizationMap,
+       // world));
+       // }
+       // ret = parameterizedTypeMungers;
+       // } else {
+       // ret = delegate.getTypeMungers();
+       // }
+       // return ret;
+       // }
+
+       protected Collection getPrivilegedAccesses() {
+               return delegate.getPrivilegedAccesses();
+       }
+
+       public int getModifiers() {
+               return delegate.getModifiers();
+       }
+
+       public ResolvedType getSuperclass() {
+               ResolvedType ret = null;
+               try {
+                       world.setTypeVariableLookupScope(this);
+                       ret = delegate.getSuperclass();
+               } finally {
+                       world.setTypeVariableLookupScope(null);
+               }
+               if (this.isParameterizedType() && ret.isParameterizedType()) {
+                       ret = ret.parameterize(getMemberParameterizationMap()).resolve(getWorld());
+               }
+               return ret;
+       }
+
+       public ReferenceTypeDelegate getDelegate() {
+               return delegate;
+       }
+
+       public void setDelegate(ReferenceTypeDelegate delegate) {
+               // Don't copy from BcelObjectType to EclipseSourceType - the context may
+               // be tidied (result null'd) after previous weaving
+               if (this.delegate != null && this.delegate.copySourceContext()
+                               && this.delegate.getSourceContext() != SourceContextImpl.UNKNOWN_SOURCE_CONTEXT)
+                       ((AbstractReferenceTypeDelegate) delegate).setSourceContext(this.delegate.getSourceContext());
+               this.delegate = delegate;
+               for (Iterator it = this.derivativeTypes.iterator(); it.hasNext();) {
+                       ReferenceType dependent = (ReferenceType) it.next();
+                       dependent.setDelegate(delegate);
+               }
+
+               // If we are raw, we have a generic type - we should ensure it uses the
+               // same delegate
+               if (isRawType() && getGenericType() != null) {
+                       ReferenceType genType = (ReferenceType) getGenericType();
+                       if (genType.getDelegate() != delegate) { // avoids circular updates
+                               genType.setDelegate(delegate);
+                       }
+               }
+               clearParameterizationCaches();
+       }
+
+       private void clearParameterizationCaches() {
+               parameterizedFields = null;
+               parameterizedInterfaces = null;
+               parameterizedMethods = null;
+               parameterizedPointcuts = null;
+       }
+
+       public int getEndPos() {
+               return endPos;
+       }
+
+       public int getStartPos() {
+               return startPos;
+       }
+
+       public void setEndPos(int endPos) {
+               this.endPos = endPos;
+       }
+
+       public void setStartPos(int startPos) {
+               this.startPos = startPos;
+       }
+
+       public boolean doesNotExposeShadowMungers() {
+               return delegate.doesNotExposeShadowMungers();
+       }
+
+       public String getDeclaredGenericSignature() {
+               return delegate.getDeclaredGenericSignature();
+       }
+
+       public void setGenericType(ReferenceType rt) {
+               genericType = rt;
+               // Should we 'promote' this reference type from simple to raw?
+               // makes sense if someone is specifying that it has a generic form
+               if (typeKind == TypeKind.SIMPLE) {
+                       typeKind = TypeKind.RAW;
+                       signatureErasure = signature;
+               }
+       }
+
+       public void demoteToSimpleType() {
+               genericType = null;
+               typeKind = TypeKind.SIMPLE;
+               signatureErasure = null;
+       }
+
+       public ResolvedType getGenericType() {
+               if (isGenericType())
+                       return this;
+               return genericType;
+       }
+
+       /**
+        * a parameterized signature starts with a "P" in place of the "L", see the comment on signatures in UnresolvedType.
+        * 
+        * @param aGenericType
+        * @param someParameters
+        * @return
+        */
+       private static String makeParameterizedSignature(ResolvedType aGenericType, ResolvedType[] someParameters) {
+               String rawSignature = aGenericType.getErasureSignature();
+               StringBuffer ret = new StringBuffer();
+               ret.append(PARAMETERIZED_TYPE_IDENTIFIER);
+               ret.append(rawSignature.substring(1, rawSignature.length() - 1));
+               ret.append("<");
+               for (int i = 0; i < someParameters.length; i++) {
+                       ret.append(someParameters[i].getSignature());
+               }
+               ret.append(">;");
+               return ret.toString();
+       }
+
+       private static String makeDeclaredSignature(ResolvedType aGenericType, UnresolvedType[] someParameters) {
+               StringBuffer ret = new StringBuffer();
+               String rawSig = aGenericType.getErasureSignature();
+               ret.append(rawSig.substring(0, rawSig.length() - 1));
+               ret.append("<");
+               for (int i = 0; i < someParameters.length; i++) {
+                       ret.append(((ReferenceType) someParameters[i]).getSignatureForAttribute());
+               }
+               ret.append(">;");
+               return ret.toString();
+       }
+
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceTypeDelegate.java b/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceTypeDelegate.java
new file mode 100644 (file)
index 0000000..ec9d839
--- /dev/null
@@ -0,0 +1,105 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ *     Andy Clement - June 2005 - separated out from ResolvedType
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.util.Collection;
+
+import org.aspectj.weaver.patterns.PerClause;
+
+/**
+ * Abstraction over a type - a reference type is Object and a descendant of Object, other types (int/etc) are considered primitive
+ * types. Abstract implementation provided by AbstractReferenceTypeDelegate.
+ */
+public interface ReferenceTypeDelegate {
+
+       // TODO asc move to proxy
+       public void addAnnotation(AnnotationAJ annotationX);
+
+       public void ensureDelegateConsistent(); // Required evil because of mutator
+
+       // methods in delegates :( (see
+       // pr85132)
+
+       public boolean isAspect();
+
+       public boolean isAnnotationStyleAspect();
+
+       public boolean isInterface();
+
+       public boolean isEnum();
+
+       public boolean isAnnotation();
+
+       public String getRetentionPolicy();
+
+       public boolean canAnnotationTargetType();
+
+       public AnnotationTargetKind[] getAnnotationTargetKinds();
+
+       public boolean isAnnotationWithRuntimeRetention();
+
+       public boolean isClass();
+
+       public boolean isGeneric();
+
+       public boolean isAnonymous();
+
+       public boolean isNested();
+
+       public boolean isExposedToWeaver();
+
+       public boolean hasAnnotation(UnresolvedType ofType);
+
+       public AnnotationAJ[] getAnnotations();
+
+       public ResolvedType[] getAnnotationTypes();
+
+       public ResolvedMember[] getDeclaredFields();
+
+       public ResolvedType[] getDeclaredInterfaces();
+
+       public ResolvedMember[] getDeclaredMethods();
+
+       public ResolvedMember[] getDeclaredPointcuts();
+
+       public TypeVariable[] getTypeVariables();
+
+       public PerClause getPerClause();
+
+       public Collection getDeclares();
+
+       public Collection getTypeMungers();
+
+       public Collection getPrivilegedAccesses();
+
+       public int getModifiers();
+
+       public ResolvedType getSuperclass();
+
+       public WeaverStateInfo getWeaverState();
+
+       public ReferenceType getResolvedTypeX();
+
+       public boolean doesNotExposeShadowMungers();
+
+       public ISourceContext getSourceContext();
+
+       public String getSourcefilename();
+
+       public String getDeclaredGenericSignature();
+
+       public ResolvedType getOuterClass();
+
+       public boolean copySourceContext();
+
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMember.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMember.java
new file mode 100644 (file)
index 0000000..3cbf33e
--- /dev/null
@@ -0,0 +1,191 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ *               2005 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation
+ *     AMC      extracted as interface 
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.ISourceLocation;
+
+public interface ResolvedMember extends Member, AnnotatedElement,
+               TypeVariableDeclaringElement {
+
+       public static final ResolvedMember[] NONE = new ResolvedMember[0];
+
+       public int getModifiers(World world);
+
+       public int getModifiers();
+
+       public UnresolvedType[] getExceptions(World world);
+
+       public UnresolvedType[] getExceptions();
+
+       public ShadowMunger getAssociatedShadowMunger();
+
+       public boolean isAjSynthetic();
+
+       public boolean isCompatibleWith(Member am);
+
+       public boolean hasAnnotations();
+
+       public boolean hasAnnotation(UnresolvedType ofType);
+
+       public AnnotationAJ[] getAnnotations();
+
+       public ResolvedType[] getAnnotationTypes();
+
+       public void setAnnotationTypes(UnresolvedType[] annotationtypes);
+
+       public void addAnnotation(AnnotationAJ annotation);
+
+       public boolean isBridgeMethod();
+
+       public boolean isVarargsMethod();
+
+       public boolean isSynthetic();
+
+       public void write(DataOutputStream s) throws IOException;
+
+       public ISourceContext getSourceContext(World world);
+
+       public String[] getParameterNames();
+
+       public void setParameterNames(String[] names);
+
+       public AnnotationAJ[][] getParameterAnnotations();
+
+       public ResolvedType[][] getParameterAnnotationTypes();
+
+       public String getAnnotationDefaultValue();
+
+       public String getParameterSignatureErased();
+
+       public String getSignatureErased();
+
+       public String[] getParameterNames(World world);
+
+       public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature();
+
+       public ISourceLocation getSourceLocation();
+
+       public int getEnd();
+
+       public ISourceContext getSourceContext();
+
+       public int getStart();
+
+       public void setPosition(int sourceStart, int sourceEnd);
+
+       public void setSourceContext(ISourceContext sourceContext);
+
+       public boolean isAbstract();
+
+       public boolean isPublic();
+
+       public boolean isProtected();
+
+       public boolean isNative();
+
+       public boolean isDefault();
+
+       public boolean isVisible(ResolvedType fromType);
+
+       public void setCheckedExceptions(UnresolvedType[] checkedExceptions);
+
+       public void setAnnotatedElsewhere(boolean b);
+
+       public boolean isAnnotatedElsewhere();
+
+       // like toString but include generic signature info
+       public String toGenericString();
+
+       public String toDebugString();
+
+       public boolean hasBackingGenericMember();
+
+       public ResolvedMember getBackingGenericMember();
+
+       /**
+        * Get the UnresolvedType for the return type, taking generic signature into
+        * account
+        */
+       public UnresolvedType getGenericReturnType();
+
+       /**
+        * Get the TypeXs of the parameter types, taking generic signature into
+        * account
+        */
+       public UnresolvedType[] getGenericParameterTypes();
+
+       // return a resolved member in which all type variables in the signature of
+       // this
+       // member have been replaced with the given bindings.
+       // the isParameterized flag tells us whether we are creating a raw type
+       // version or not
+       // if isParameterized List<T> will turn into List<String> (for example),
+       // but if !isParameterized List<T> will turn into List.
+       public ResolvedMemberImpl parameterizedWith(
+                       UnresolvedType[] typeParameters, ResolvedType newDeclaringType,
+                       boolean isParameterized);
+
+       // this variant allows for aliases for type variables (i.e. allowing them to
+       // have another name)
+       // this is used for processing ITDs that share type variables with their
+       // target generic type
+       public ResolvedMemberImpl parameterizedWith(
+                       UnresolvedType[] typeParameters, ResolvedType newDeclaringType,
+                       boolean isParameterized, List aliases);
+
+       public void setTypeVariables(TypeVariable[] types);
+
+       public TypeVariable[] getTypeVariables();
+
+       // /**
+       // * If this member is defined by a parameterized super-type, return the
+       // erasure
+       // * of that member.
+       // * For example:
+       // * interface I<T> { T foo(T aTea); }
+       // * class C implements I<String> {
+       // * String foo(String aString) { return "something"; }
+       // * }
+       // * The resolved member for C.foo has signature String foo(String). The
+       // * erasure of that member is Object foo(Object) -- use upper bound of type
+       // * variable.
+       // * A type is a supertype of itself.
+       // */
+       // public ResolvedMember getErasure();
+
+       /**
+        * Returns true if this member matches the other. The matching takes into
+        * account name and parameter types only. When comparing parameter types, we
+        * allow any type variable to match any other type variable regardless of
+        * bounds.
+        */
+       public boolean matches(ResolvedMember aCandidateMatch);
+
+       public void resetName(String newName);
+
+       public void resetKind(MemberKind newKind);
+
+       public void resetModifiers(int newModifiers);
+
+       public void resetReturnTypeToObjectArray();
+
+       public void evictWeavingState();
+
+       public ResolvedMember parameterizedWith(Map m, World w);
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMemberImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMemberImpl.java
new file mode 100644 (file)
index 0000000..2bdd416
--- /dev/null
@@ -0,0 +1,1156 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.aspectj.bridge.ISourceLocation;
+
+/**
+ * This is the declared member, i.e. it will always correspond to an actual method/... declaration
+ */
+public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, AnnotatedElement, TypeVariableDeclaringElement,
+               ResolvedMember {
+
+       private String[] parameterNames = null;
+       protected UnresolvedType[] checkedExceptions = UnresolvedType.NONE;
+       /**
+        * if this member is a parameterized version of a member in a generic type, then this field holds a reference to the member we
+        * parameterize.
+        */
+       protected ResolvedMember backingGenericMember = null;
+
+       protected Set annotationTypes = null;
+       protected ResolvedType[][] parameterAnnotationTypes = null;
+
+       // Some members are 'created' to represent other things (for example ITDs).
+       // These
+       // members have their annotations stored elsewhere, and this flag indicates
+       // that is
+       // the case. It is up to the caller to work out where that is!
+       // Once determined the caller may choose to stash the annotations in this
+       // member...
+       private boolean isAnnotatedElsewhere = false; // this field is not
+       // serialized.
+       private boolean isAjSynthetic = false;
+
+       // generic methods have type variables
+       protected TypeVariable[] typeVariables;
+
+       // these three fields hold the source location of this member
+       protected int start, end;
+       protected ISourceContext sourceContext = null;
+
+       // XXX deprecate this in favor of the constructor below
+       public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name,
+                       UnresolvedType[] parameterTypes) {
+               super(kind, declaringType, modifiers, returnType, name, parameterTypes);
+       }
+
+       public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name,
+                       UnresolvedType[] parameterTypes, UnresolvedType[] checkedExceptions) {
+               super(kind, declaringType, modifiers, returnType, name, parameterTypes);
+               this.checkedExceptions = checkedExceptions;
+       }
+
+       public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name,
+                       UnresolvedType[] parameterTypes, UnresolvedType[] checkedExceptions, ResolvedMember backingGenericMember) {
+               this(kind, declaringType, modifiers, returnType, name, parameterTypes, checkedExceptions);
+               this.backingGenericMember = backingGenericMember;
+               this.isAjSynthetic = backingGenericMember.isAjSynthetic();
+       }
+
+       public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, String name, String signature) {
+               super(kind, declaringType, modifiers, name, signature);
+       }
+
+       /**
+        * Compute the full set of signatures for a member. This walks up the hierarchy giving the ResolvedMember in each defining type
+        * in the hierarchy. A shadowMember can be created with a target type (declaring type) that does not actually define the member.
+        * This is ok as long as the member is inherited in the declaring type. Each declaring type in the line to the actual declaring
+        * type is added as an additional signature. For example:
+        * 
+        * class A { void foo(); } class B extends A {}
+        * 
+        * shadowMember : void B.foo()
+        * 
+        * gives { void B.foo(), void A.foo() }
+        * 
+        * @param joinPointSignature
+        * @param inAWorld
+        */
+       public static JoinPointSignature[] getJoinPointSignatures(Member joinPointSignature, World inAWorld) {
+
+               // Walk up hierarchy creating one member for each type up to and
+               // including the
+               // first defining type
+               ResolvedType originalDeclaringType = joinPointSignature.getDeclaringType().resolve(inAWorld);
+               ResolvedMemberImpl firstDefiningMember = (ResolvedMemberImpl) joinPointSignature.resolve(inAWorld);
+               if (firstDefiningMember == null) {
+                       return new JoinPointSignature[0];
+               }
+               // declaringType can be unresolved if we matched a synthetic member
+               // generated by Aj...
+               // should be fixed elsewhere but add this resolve call on the end for
+               // now so that we can
+               // focus on one problem at a time...
+               ResolvedType firstDefiningType = firstDefiningMember.getDeclaringType().resolve(inAWorld);
+               if (firstDefiningType != originalDeclaringType) {
+                       if (joinPointSignature.getKind() == Member.CONSTRUCTOR) {
+                               return new JoinPointSignature[0];
+                       }
+                       // else if (shadowMember.isStatic()) {
+                       // return new ResolvedMember[] {firstDefiningMember};
+                       // }
+               }
+
+               List declaringTypes = new ArrayList();
+               accumulateTypesInBetween(originalDeclaringType, firstDefiningType, declaringTypes);
+               Set memberSignatures = new HashSet();
+               for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) {
+                       ResolvedType declaringType = (ResolvedType) iter.next();
+                       ResolvedMember member = firstDefiningMember.withSubstituteDeclaringType(declaringType);
+                       memberSignatures.add(member);
+               }
+
+               if (shouldWalkUpHierarchyFor(firstDefiningMember)) {
+                       // now walk up the hierarchy from the firstDefiningMember and
+                       // include the signature for
+                       // every type between the firstDefiningMember and the root defining
+                       // member.
+                       Iterator superTypeIterator = firstDefiningType.getDirectSupertypes();
+                       List typesAlreadyVisited = new ArrayList();
+                       accumulateMembersMatching(firstDefiningMember, superTypeIterator, typesAlreadyVisited, memberSignatures);
+               }
+
+               JoinPointSignature[] ret = new JoinPointSignature[memberSignatures.size()];
+               memberSignatures.toArray(ret);
+               return ret;
+       }
+
+       private static boolean shouldWalkUpHierarchyFor(Member aMember) {
+               if (aMember.getKind() == Member.CONSTRUCTOR)
+                       return false;
+               if (aMember.getKind() == Member.FIELD)
+                       return false;
+               if (aMember.isStatic())
+                       return false;
+               return true;
+       }
+
+       /**
+        * Build a list containing every type between subtype and supertype, inclusively.
+        */
+       private static void accumulateTypesInBetween(ResolvedType subType, ResolvedType superType, List types) {
+               types.add(subType);
+               if (subType == superType) {
+                       return;
+               } else {
+                       for (Iterator iter = subType.getDirectSupertypes(); iter.hasNext();) {
+                               ResolvedType parent = (ResolvedType) iter.next();
+                               if (superType.isAssignableFrom(parent)) {
+                                       accumulateTypesInBetween(parent, superType, types);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * We have a resolved member, possibly with type parameter references as parameters or return type. We need to find all its
+        * ancestor members. When doing this, a type parameter matches regardless of bounds (bounds can be narrowed down the hierarchy).
+        */
+       private static void accumulateMembersMatching(ResolvedMemberImpl memberToMatch, Iterator typesToLookIn,
+                       List typesAlreadyVisited, Set foundMembers) {
+               while (typesToLookIn.hasNext()) {
+                       ResolvedType toLookIn = (ResolvedType) typesToLookIn.next();
+                       if (!typesAlreadyVisited.contains(toLookIn)) {
+                               typesAlreadyVisited.add(toLookIn);
+                               ResolvedMemberImpl foundMember = (ResolvedMemberImpl) toLookIn.lookupResolvedMember(memberToMatch, true);
+                               if (foundMember != null && isVisibleTo(memberToMatch, foundMember)) {
+                                       List declaringTypes = new ArrayList();
+                                       // declaring type can be unresolved if the member can from
+                                       // an ITD...
+                                       ResolvedType resolvedDeclaringType = foundMember.getDeclaringType().resolve(toLookIn.getWorld());
+                                       accumulateTypesInBetween(toLookIn, resolvedDeclaringType, declaringTypes);
+                                       for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) {
+                                               ResolvedType declaringType = (ResolvedType) iter.next();
+                                               // typesAlreadyVisited.add(declaringType);
+                                               ResolvedMember member = foundMember.withSubstituteDeclaringType(declaringType);
+                                               foundMembers.add(member);
+                                       }
+                                       if (toLookIn.isParameterizedType() && (foundMember.backingGenericMember != null)) {
+                                               foundMembers.add(new JoinPointSignature(foundMember.backingGenericMember, foundMember.declaringType
+                                                               .resolve(toLookIn.getWorld())));
+                                       }
+                                       accumulateMembersMatching(foundMember, toLookIn.getDirectSupertypes(), typesAlreadyVisited, foundMembers);
+                                       // if this was a parameterized type, look in the generic
+                                       // type that backs it too
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Returns true if the parent member is visible to the child member In the same declaring type this is always true, otherwise if
+        * parent is private it is false.
+        * 
+        * @param childMember
+        * @param parentMember
+        * @return
+        */
+       private static boolean isVisibleTo(ResolvedMember childMember, ResolvedMember parentMember) {
+               if (childMember.getDeclaringType().equals(parentMember.getDeclaringType()))
+                       return true;
+               if (Modifier.isPrivate(parentMember.getModifiers())) {
+                       return false;
+               } else {
+                       return true;
+               }
+       }
+
+       // ----
+
+       public final int getModifiers(World world) {
+               return modifiers;
+       }
+
+       public final int getModifiers() {
+               return modifiers;
+       }
+
+       // ----
+
+       public final UnresolvedType[] getExceptions(World world) {
+               return getExceptions();
+       }
+
+       public UnresolvedType[] getExceptions() {
+               return checkedExceptions;
+       }
+
+       public ShadowMunger getAssociatedShadowMunger() {
+               return null;
+       }
+
+       // ??? true or false?
+       public boolean isAjSynthetic() {
+               return isAjSynthetic;
+       }
+
+       protected void setAjSynthetic(boolean b) {
+               isAjSynthetic = b;
+       }
+
+       public boolean hasAnnotations() {
+               return (annotationTypes != null);
+       }
+
+       /**
+        * Check if this member has an annotation of the specified type. If the member has a backing generic member then this member
+        * represents a parameterization of a member in a generic type and the annotations available on the backing generic member
+        * should be used.
+        * 
+        * @param ofType the type of the annotation being searched for
+        * @return true if the annotation is found on this member or its backing generic member
+        */
+       public boolean hasAnnotation(UnresolvedType ofType) {
+               // The ctors don't allow annotations to be specified ... yet - but
+               // that doesn't mean it is an error to call this method.
+               // Normally the weaver will be working with subtypes of
+               // this type - BcelField/BcelMethod
+               if (backingGenericMember != null) {
+                       if (annotationTypes != null) {
+                               throw new BCException("Unexpectedly found a backing generic member and a local set of annotations");
+                       }
+                       return backingGenericMember.hasAnnotation(ofType);
+               }
+               if (annotationTypes == null) {
+                       return false;
+               }
+               return annotationTypes.contains(ofType);
+       }
+
+       public ResolvedType[] getAnnotationTypes() {
+               // The ctors don't allow annotations to be specified ... yet - but
+               // that doesn't mean it is an error to call this method.
+               // Normally the weaver will be working with subtypes of
+               // this type - BcelField/BcelMethod
+               if (backingGenericMember != null) {
+                       if (annotationTypes != null) {
+                               throw new BCException("Unexpectedly found a backing generic member and a local set of annotations");
+                       }
+                       return backingGenericMember.getAnnotationTypes();
+               }
+               if (annotationTypes == null)
+                       return null;
+               return (ResolvedType[]) annotationTypes.toArray(new ResolvedType[] {});
+       }
+
+       public String getAnnotationDefaultValue() {
+               throw new UnsupportedOperationException(
+                               "You should resolve this member and call getAnnotationDefaultValue() on the result...");
+       }
+
+       public AnnotationAJ[] getAnnotations() {
+               if (backingGenericMember != null)
+                       return backingGenericMember.getAnnotations();
+               return super.getAnnotations();
+       }
+
+       public void setAnnotationTypes(UnresolvedType[] annotationtypes) {
+               if (annotationTypes == null)
+                       annotationTypes = new HashSet();
+               for (int i = 0; i < annotationtypes.length; i++) {
+                       UnresolvedType typeX = annotationtypes[i];
+                       annotationTypes.add(typeX);
+               }
+       }
+
+       public ResolvedType[][] getParameterAnnotationTypes() {
+               if (parameterAnnotationTypes == null)
+                       return null;
+               return parameterAnnotationTypes;
+       }
+
+       public AnnotationAJ[][] getParameterAnnotations() {
+               if (backingGenericMember != null)
+                       return backingGenericMember.getParameterAnnotations();
+               throw new BCException("Cannot return parameter annotations for a " + this.getClass().getName() + " member");
+               // return super.getParameterAnnotations();
+       }
+
+       public void addAnnotation(AnnotationAJ annotation) {
+               // FIXME asc only allows for annotation types, not instances - should
+               // it?
+               if (annotationTypes == null)
+                       annotationTypes = new HashSet();
+               annotationTypes.add(annotation.getType());
+       }
+
+       public boolean isBridgeMethod() {
+               return (modifiers & Constants.ACC_BRIDGE) != 0 && getKind().equals(METHOD);
+       }
+
+       public boolean isVarargsMethod() {
+               return (modifiers & Constants.ACC_VARARGS) != 0;
+       }
+
+       public void setVarargsMethod() {
+               modifiers = modifiers | Constants.ACC_VARARGS;
+       }
+
+       public boolean isSynthetic() {
+               // See Bcelmethod.isSynthetic() which takes account of preJava5
+               // Synthetic modifier
+               return (modifiers & 4096) != 0; // do we know better?
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               getKind().write(s);
+               getDeclaringType().write(s);
+               s.writeInt(modifiers);
+               s.writeUTF(getName());
+               s.writeUTF(getSignature());
+               UnresolvedType.writeArray(getExceptions(), s);
+
+               s.writeInt(getStart());
+               s.writeInt(getEnd());
+               s.writeBoolean(isVarargsMethod());
+
+               // Write out any type variables...
+               if (typeVariables == null) {
+                       s.writeInt(0);
+               } else {
+                       s.writeInt(typeVariables.length);
+                       for (int i = 0; i < typeVariables.length; i++) {
+                               typeVariables[i].write(s);
+                       }
+               }
+               String gsig = getGenericSignature();
+               if (getSignature().equals(gsig)) {
+                       s.writeBoolean(false);
+               } else {
+                       s.writeBoolean(true);
+                       s.writeInt(parameterTypes.length);
+                       for (int i = 0; i < parameterTypes.length; i++) {
+                               UnresolvedType array_element = parameterTypes[i];
+                               array_element.write(s);
+                       }
+                       returnType.write(s);
+               }
+       }
+
+       /**
+        * Return the member generic signature that would be suitable for inclusion in a class file Signature attribute. For: <T>
+        * List<String> getThem(T t) {} we would create: <T:Ljava/lang/Object;>(TT;)Ljava/util/List<Ljava/lang/String;>;;
+        * 
+        * @return the generic signature for the member that could be inserted into a class file
+        */
+       public String getSignatureForAttribute() {
+               StringBuffer sb = new StringBuffer();
+               if (typeVariables != null) {
+                       sb.append("<");
+                       for (int i = 0; i < typeVariables.length; i++) {
+                               sb.append(typeVariables[i].getSignatureForAttribute()); // need
+                               // a
+                               // 'getSignatureForAttribute()'
+                       }
+                       sb.append(">");
+               }
+               sb.append("(");
+               for (int i = 0; i < parameterTypes.length; i++) {
+                       ResolvedType ptype = (ResolvedType) parameterTypes[i];
+                       sb.append(ptype.getSignatureForAttribute());
+               }
+               sb.append(")");
+               sb.append(((ResolvedType) returnType).getSignatureForAttribute());
+               return sb.toString();
+       }
+
+       public String getGenericSignature() {
+               StringBuffer sb = new StringBuffer();
+               if (typeVariables != null) {
+                       sb.append("<");
+                       for (int i = 0; i < typeVariables.length; i++) {
+                               sb.append(typeVariables[i].getSignature());
+                       }
+                       sb.append(">");
+               }
+               sb.append("(");
+               for (int i = 0; i < parameterTypes.length; i++) {
+                       UnresolvedType ptype = parameterTypes[i];
+                       sb.append(ptype.getSignature());
+               }
+               sb.append(")");
+               sb.append(returnType.getSignature());
+               return sb.toString();
+       }
+
+       public static void writeArray(ResolvedMember[] members, DataOutputStream s) throws IOException {
+               s.writeInt(members.length);
+               for (int i = 0, len = members.length; i < len; i++) {
+                       members[i].write(s);
+               }
+       }
+
+       public static ResolvedMemberImpl readResolvedMember(VersionedDataInputStream s, ISourceContext sourceContext)
+                       throws IOException {
+
+               ResolvedMemberImpl m = new ResolvedMemberImpl(MemberKind.read(s), UnresolvedType.read(s), s.readInt(), s.readUTF(), s
+                               .readUTF());
+               m.checkedExceptions = UnresolvedType.readArray(s);
+
+               m.start = s.readInt();
+               m.end = s.readInt();
+               m.sourceContext = sourceContext;
+
+               if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
+
+                       if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150M4) {
+                               boolean isvarargs = s.readBoolean();
+                               if (isvarargs)
+                                       m.setVarargsMethod();
+                       }
+
+                       int tvcount = s.readInt();
+                       if (tvcount != 0) {
+                               m.typeVariables = new TypeVariable[tvcount];
+                               for (int i = 0; i < tvcount; i++) {
+                                       m.typeVariables[i] = TypeVariable.read(s);
+                                       m.typeVariables[i].setDeclaringElement(m);
+                               }
+                       }
+                       if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150M4) {
+                               boolean hasAGenericSignature = s.readBoolean();
+                               if (hasAGenericSignature) {
+                                       int ps = s.readInt();
+                                       UnresolvedType[] params = new UnresolvedType[ps];
+                                       for (int i = 0; i < params.length; i++) {
+                                               params[i] = TypeFactory.createTypeFromSignature(s.readUTF());
+                                       }
+                                       UnresolvedType rt = TypeFactory.createTypeFromSignature(s.readUTF());
+                                       m.parameterTypes = params;
+                                       m.returnType = rt;
+                               }
+                       }
+               }
+               return m;
+       }
+
+       public static ResolvedMember[] readResolvedMemberArray(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               int len = s.readInt();
+               ResolvedMember[] members = new ResolvedMember[len];
+               for (int i = 0; i < len; i++) {
+                       members[i] = ResolvedMemberImpl.readResolvedMember(s, context);
+               }
+               return members;
+       }
+
+       // OPTIMIZE dont like how resolve(world) on ResolvedMemberImpl does
+       // something different to world.resolve(member)
+       public ResolvedMember resolve(World world) {
+               // make sure all the pieces of a resolvedmember really are resolved
+               try {
+                       if (typeVariables != null && typeVariables.length > 0) {
+                               for (int i = 0; i < typeVariables.length; i++) {
+                                       typeVariables[i] = typeVariables[i].resolve(world);
+                               }
+                       }
+                       world.setTypeVariableLookupScope(this);
+                       if (annotationTypes != null) {
+                               Set r = new HashSet();
+                               for (Iterator iter = annotationTypes.iterator(); iter.hasNext();) {
+                                       UnresolvedType element = (UnresolvedType) iter.next();
+                                       r.add(world.resolve(element));
+                               }
+                               annotationTypes = r;
+                       }
+                       declaringType = declaringType.resolve(world);
+                       if (declaringType.isRawType())
+                               declaringType = ((ReferenceType) declaringType).getGenericType();
+
+                       if (parameterTypes != null && parameterTypes.length > 0) {
+                               for (int i = 0; i < parameterTypes.length; i++) {
+                                       parameterTypes[i] = parameterTypes[i].resolve(world);
+                               }
+                       }
+
+                       returnType = returnType.resolve(world);
+
+               } finally {
+                       world.setTypeVariableLookupScope(null);
+               }
+               return this;
+       }
+
+       public ISourceContext getSourceContext(World world) {
+               return getDeclaringType().resolve(world).getSourceContext();
+       }
+
+       public String[] getParameterNames() {
+               return parameterNames;
+       }
+
+       public final void setParameterNames(String[] pnames) {
+               parameterNames = pnames;
+       }
+
+       public final String[] getParameterNames(World world) {
+               return getParameterNames();
+       }
+
+       public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature() {
+               return null;
+       }
+
+       public ISourceLocation getSourceLocation() {
+               // System.out.println("get context: " + this + " is " + sourceContext);
+               if (getSourceContext() == null) {
+                       // System.err.println("no context: " + this);
+                       return null;
+               }
+               return getSourceContext().makeSourceLocation(this);
+       }
+
+       public int getEnd() {
+               return end;
+       }
+
+       public ISourceContext getSourceContext() {
+               return sourceContext;
+       }
+
+       public int getStart() {
+               return start;
+       }
+
+       public void setPosition(int sourceStart, int sourceEnd) {
+               this.start = sourceStart;
+               this.end = sourceEnd;
+       }
+
+       public void setDeclaringType(ReferenceType rt) {
+               declaringType = rt;
+       }
+
+       public void setSourceContext(ISourceContext sourceContext) {
+               this.sourceContext = sourceContext;
+       }
+
+       public boolean isAbstract() {
+               return Modifier.isAbstract(modifiers);
+       }
+
+       public boolean isPublic() {
+               return Modifier.isPublic(modifiers);
+       }
+
+       public boolean isProtected() {
+               return Modifier.isProtected(modifiers);
+       }
+
+       public boolean isNative() {
+               return Modifier.isNative(modifiers);
+       }
+
+       public boolean isDefault() {
+               return !(isPublic() || isProtected() || isPrivate());
+       }
+
+       public boolean isVisible(ResolvedType fromType) {
+               World world = fromType.getWorld();
+               return ResolvedType.isVisible(getModifiers(), getDeclaringType().resolve(world), fromType);
+       }
+
+       public void setCheckedExceptions(UnresolvedType[] checkedExceptions) {
+               this.checkedExceptions = checkedExceptions;
+       }
+
+       public void setAnnotatedElsewhere(boolean b) {
+               isAnnotatedElsewhere = b;
+       }
+
+       public boolean isAnnotatedElsewhere() {
+               return isAnnotatedElsewhere;
+       }
+
+       /**
+        * Get the UnresolvedType for the return type, taking generic signature into account
+        */
+       public UnresolvedType getGenericReturnType() {
+               return getReturnType();
+       }
+
+       /**
+        * Get the TypeXs of the parameter types, taking generic signature into account
+        */
+       public UnresolvedType[] getGenericParameterTypes() {
+               return getParameterTypes();
+       }
+
+       public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType,
+                       boolean isParameterized) {
+               return parameterizedWith(typeParameters, newDeclaringType, isParameterized, null);
+       }
+
+       /**
+        * Return a resolvedmember in which all the type variables in the signature have been replaced with the given bindings. The
+        * 'isParameterized' flag tells us whether we are creating a raw type version or not. if (isParameterized) then List<T> will
+        * turn into List<String> (for example) - if (!isParameterized) then List<T> will turn into List.
+        */
+       public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType,
+                       boolean isParameterized, List aliases) {
+               if (// isParameterized && <-- might need this bit...
+               !getDeclaringType().isGenericType()) {
+                       throw new IllegalStateException("Can't ask to parameterize a member of non-generic type: " + getDeclaringType()
+                                       + "  kind(" + getDeclaringType().typeKind + ")");
+               }
+               TypeVariable[] typeVariables = getDeclaringType().getTypeVariables();
+               if (isParameterized && (typeVariables.length != typeParameters.length)) {
+                       throw new IllegalStateException("Wrong number of type parameters supplied");
+               }
+               Map typeMap = new HashMap();
+               boolean typeParametersSupplied = typeParameters != null && typeParameters.length > 0;
+               if (typeVariables != null) {
+                       // If no 'replacements' were supplied in the typeParameters array
+                       // then collapse
+                       // type variables to their first bound.
+                       for (int i = 0; i < typeVariables.length; i++) {
+                               UnresolvedType ut = (!typeParametersSupplied ? typeVariables[i].getFirstBound() : typeParameters[i]);
+                               typeMap.put(typeVariables[i].getName(), ut);
+                       }
+               }
+               // For ITDs on generic types that use type variables from the target
+               // type, the aliases
+               // record the alternative names used throughout the ITD expression that
+               // must map to
+               // the same value as the type variables real name.
+               if (aliases != null) {
+                       int posn = 0;
+                       for (Iterator iter = aliases.iterator(); iter.hasNext();) {
+                               String typeVariableAlias = (String) iter.next();
+                               typeMap.put(typeVariableAlias, (!typeParametersSupplied ? typeVariables[posn].getFirstBound()
+                                               : typeParameters[posn]));
+                               posn++;
+                       }
+               }
+
+               UnresolvedType parameterizedReturnType = parameterize(getGenericReturnType(), typeMap, isParameterized);
+               UnresolvedType[] parameterizedParameterTypes = new UnresolvedType[getGenericParameterTypes().length];
+               UnresolvedType[] genericParameterTypes = getGenericParameterTypes();
+               for (int i = 0; i < parameterizedParameterTypes.length; i++) {
+                       parameterizedParameterTypes[i] = parameterize(genericParameterTypes[i], typeMap, isParameterized);
+               }
+               ResolvedMemberImpl ret = new ResolvedMemberImpl(getKind(), newDeclaringType, getModifiers(), parameterizedReturnType,
+                               getName(), parameterizedParameterTypes, getExceptions(), this);
+               ret.setTypeVariables(getTypeVariables());
+               ret.setSourceContext(getSourceContext());
+               ret.setPosition(getStart(), getEnd());
+               ret.setParameterNames(getParameterNames());
+               return ret;
+       }
+
+       /**
+        * Replace occurrences of type variables in the signature with values contained in the map. The map is of the form
+        * A=String,B=Integer and so a signature List<A> Foo.m(B i) {} would become List<String> Foo.m(Integer i) {}
+        */
+       public ResolvedMember parameterizedWith(Map m, World w) {
+               // if (//isParameterized && <-- might need this bit...
+               // !getDeclaringType().isGenericType()) {
+               // throw new IllegalStateException(
+               // "Can't ask to parameterize a member of non-generic type: "
+               // +getDeclaringType()+"  kind("+
+               // getDeclaringType().typeKind+")");
+               // }
+               declaringType = declaringType.resolve(w);
+               if (declaringType.isRawType())
+                       declaringType = ((ResolvedType) declaringType).getGenericType();
+               // TypeVariable[] typeVariables = getDeclaringType().getTypeVariables();
+               // if (isParameterized && (typeVariables.length !=
+               // typeParameters.length)) {
+               // throw new
+               // IllegalStateException("Wrong number of type parameters supplied");
+               // }
+               // Map typeMap = new HashMap();
+               // boolean typeParametersSupplied = typeParameters!=null &&
+               // typeParameters.length>0;
+               // if (typeVariables!=null) {
+               // // If no 'replacements' were supplied in the typeParameters array
+               // then collapse
+               // // type variables to their first bound.
+               // for (int i = 0; i < typeVariables.length; i++) {
+               // UnresolvedType ut =
+               // (!typeParametersSupplied?typeVariables[i].getFirstBound
+               // ():typeParameters[i]);
+               // typeMap.put(typeVariables[i].getName(),ut);
+               // }
+               // }
+               // // For ITDs on generic types that use type variables from the target
+               // type, the aliases
+               // // record the alternative names used throughout the ITD expression
+               // that must map to
+               // // the same value as the type variables real name.
+               // if (aliases!=null) {
+               // int posn = 0;
+               // for (Iterator iter = aliases.iterator(); iter.hasNext();) {
+               // String typeVariableAlias = (String) iter.next();
+               // typeMap.put(typeVariableAlias,(!typeParametersSupplied?typeVariables[
+               // posn].getFirstBound():typeParameters[posn]));
+               // posn++;
+               // }
+               // }
+
+               UnresolvedType parameterizedReturnType = parameterize(getGenericReturnType(), m, true, w);
+               UnresolvedType[] parameterizedParameterTypes = new UnresolvedType[getGenericParameterTypes().length];
+               UnresolvedType[] genericParameterTypes = getGenericParameterTypes();
+               for (int i = 0; i < parameterizedParameterTypes.length; i++) {
+                       parameterizedParameterTypes[i] = parameterize(genericParameterTypes[i], m, true, w);
+               }
+               ResolvedMemberImpl ret = new ResolvedMemberImpl(getKind(), declaringType, getModifiers(), parameterizedReturnType,
+                               getName(), parameterizedParameterTypes, getExceptions(), this);
+               ret.setTypeVariables(getTypeVariables());
+               ret.setSourceContext(getSourceContext());
+               ret.setPosition(getStart(), getEnd());
+               ret.setParameterNames(getParameterNames());
+               return ret;
+       }
+
+       public void setTypeVariables(TypeVariable[] tvars) {
+               typeVariables = tvars;
+       }
+
+       public TypeVariable[] getTypeVariables() {
+               return typeVariables;
+       }
+
+       protected UnresolvedType parameterize(UnresolvedType aType, Map typeVariableMap, boolean inParameterizedType) {
+               return parameterize(aType, typeVariableMap, inParameterizedType, null);
+       }
+
+       protected UnresolvedType parameterize(UnresolvedType aType, Map typeVariableMap, boolean inParameterizedType, World w) {
+               if (aType instanceof TypeVariableReference) {
+                       String variableName = ((TypeVariableReference) aType).getTypeVariable().getName();
+                       if (!typeVariableMap.containsKey(variableName)) {
+                               return aType; // if the type variable comes from the method (and
+                               // not the type) thats OK
+                       }
+                       return (UnresolvedType) typeVariableMap.get(variableName);
+               } else if (aType.isParameterizedType()) {
+                       if (inParameterizedType) {
+                               // if (!(getDeclaringType() instanceof ResolvedType)) {
+                               // int stop = 1;
+                               // }
+                               // if (aType!=null) {// instanceof UnresolvedType) {
+                               if (w != null)
+                                       aType = aType.resolve(w);
+                               else {
+                                       aType = aType.resolve(((ResolvedType) getDeclaringType()).getWorld());
+                               }
+                               // }
+                               return aType.parameterize(typeVariableMap);
+                       } else {
+                               return aType.getRawType();
+                       }
+               } else if (aType.isArray()) {
+                       // The component type might be a type variable (pr150095)
+                       int dims = 1;
+                       String sig = aType.getSignature();
+                       // while (sig.charAt(dims) == '[')
+                       // dims++;
+                       UnresolvedType arrayType = null;
+                       UnresolvedType componentSig = UnresolvedType.forSignature(sig.substring(dims));
+                       UnresolvedType parameterizedComponentSig = parameterize(componentSig, typeVariableMap, inParameterizedType);
+                       if (parameterizedComponentSig.isTypeVariableReference()
+                                       && parameterizedComponentSig instanceof UnresolvedTypeVariableReferenceType
+                                       && typeVariableMap.containsKey(((UnresolvedTypeVariableReferenceType) parameterizedComponentSig)
+                                                       .getTypeVariable().getName())) { // pr250632
+                               // TODO ASC bah, this code is rubbish - i should fix it properly
+                               StringBuffer newsig = new StringBuffer();
+                               newsig.append("[T");
+                               newsig.append(((UnresolvedTypeVariableReferenceType) parameterizedComponentSig).getTypeVariable().getName());
+                               newsig.append(";");
+                               arrayType = UnresolvedType.forSignature(newsig.toString());
+                       } else {
+                               arrayType = ResolvedType.makeArray(parameterizedComponentSig, dims);
+                       }
+                       return arrayType;
+               }
+               return aType;
+       }
+
+       /**
+        * If this member is defined by a parameterized super-type, return the erasure of that member. For example: interface I<T> { T
+        * foo(T aTea); } class C implements I<String> { String foo(String aString) { return "something"; } } The resolved member for
+        * C.foo has signature String foo(String). The erasure of that member is Object foo(Object) -- use upper bound of type variable.
+        * A type is a supertype of itself.
+        */
+       // public ResolvedMember getErasure() {
+       // if (calculatedMyErasure) return myErasure;
+       // calculatedMyErasure = true;
+       // ResolvedType resolvedDeclaringType = (ResolvedType) getDeclaringType();
+       // // this next test is fast, and the result is cached.
+       // if (!resolvedDeclaringType.hasParameterizedSuperType()) {
+       // return null;
+       // } else {
+       // // we have one or more parameterized super types.
+       // // this member may be defined by one of them... we need to find out.
+       // Collection declaringTypes =
+       // this.getDeclaringTypes(resolvedDeclaringType.getWorld());
+       // for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) {
+       // ResolvedType aDeclaringType = (ResolvedType) iter.next();
+       // if (aDeclaringType.isParameterizedType()) {
+       // // we've found the (a?) parameterized type that defines this member.
+       // // now get the erasure of it
+       // ResolvedMemberImpl matchingMember = (ResolvedMemberImpl)
+       // aDeclaringType.lookupMemberNoSupers(this);
+       // if (matchingMember != null && matchingMember.backingGenericMember !=
+       // null) {
+       // myErasure = matchingMember.backingGenericMember;
+       // return myErasure;
+       // }
+       // }
+       // }
+       // }
+       // return null;
+       // }
+       //      
+       // private ResolvedMember myErasure = null;
+       // private boolean calculatedMyErasure = false;
+       public boolean hasBackingGenericMember() {
+               return backingGenericMember != null;
+       }
+
+       public ResolvedMember getBackingGenericMember() {
+               return backingGenericMember;
+       }
+
+       /**
+        * For ITDs, we use the default factory methods to build a resolved member, then alter a couple of characteristics using this
+        * method - this is safe.
+        */
+       public void resetName(String newName) {
+               this.name = newName;
+       }
+
+       public void resetKind(MemberKind newKind) {
+               this.kind = newKind;
+       }
+
+       public void resetModifiers(int newModifiers) {
+               this.modifiers = newModifiers;
+       }
+
+       public void resetReturnTypeToObjectArray() {
+               returnType = UnresolvedType.OBJECTARRAY;
+       }
+
+       /**
+        * Returns a copy of this member but with the declaring type swapped. Copy only needs to be shallow.
+        * 
+        * @param newDeclaringType
+        */
+       public JoinPointSignature withSubstituteDeclaringType(ResolvedType newDeclaringType) {
+               JoinPointSignature ret = new JoinPointSignature(this, newDeclaringType);
+               return ret;
+       }
+
+       /**
+        * Returns true if this member matches the other. The matching takes into account name and parameter types only. When comparing
+        * parameter types, we allow any type variable to match any other type variable regardless of bounds.
+        */
+       public boolean matches(ResolvedMember aCandidateMatch) {
+               ResolvedMemberImpl candidateMatchImpl = (ResolvedMemberImpl) aCandidateMatch;
+               if (!getName().equals(aCandidateMatch.getName()))
+                       return false;
+               UnresolvedType[] myParameterTypes = getGenericParameterTypes();
+               UnresolvedType[] candidateParameterTypes = aCandidateMatch.getGenericParameterTypes();
+               if (myParameterTypes.length != candidateParameterTypes.length)
+                       return false;
+               String myParameterSignature = getParameterSigWithBoundsRemoved();
+               String candidateParameterSignature = candidateMatchImpl.getParameterSigWithBoundsRemoved();
+               if (myParameterSignature.equals(candidateParameterSignature)) {
+                       return true;
+               } else {
+                       // try erasure
+                       myParameterSignature = getParameterSignatureErased();
+                       candidateParameterSignature = candidateMatchImpl.getParameterSignatureErased();
+                       return myParameterSignature.equals(candidateParameterSignature);
+               }
+       }
+
+       /**
+        * converts e.g. <T extends Number>.... List<T> to just Ljava/util/List<T;>; whereas the full signature would be
+        * Ljava/util/List<T:Ljava/lang/Number;>;
+        */
+       private String myParameterSignatureWithBoundsRemoved = null;
+       /**
+        * converts e.g. <T extends Number>.... List<T> to just Ljava/util/List;
+        */
+       private String myParameterSignatureErasure = null;
+
+       // does NOT produce a meaningful java signature, but does give a unique
+       // string suitable for
+       // comparison.
+       private String getParameterSigWithBoundsRemoved() {
+               if (myParameterSignatureWithBoundsRemoved != null)
+                       return myParameterSignatureWithBoundsRemoved;
+               StringBuffer sig = new StringBuffer();
+               UnresolvedType[] myParameterTypes = getGenericParameterTypes();
+               for (int i = 0; i < myParameterTypes.length; i++) {
+                       appendSigWithTypeVarBoundsRemoved(myParameterTypes[i], sig, new HashSet());
+               }
+               myParameterSignatureWithBoundsRemoved = sig.toString();
+               return myParameterSignatureWithBoundsRemoved;
+       }
+
+       /**
+        * Return the erased form of the signature with bounds collapsed for type variables, etc. Does not include the return type, @see
+        * getParam
+        */
+       public String getParameterSignatureErased() {
+               if (myParameterSignatureErasure != null)
+                       return myParameterSignatureErasure;
+               StringBuffer sig = new StringBuffer();
+               UnresolvedType[] myParameterTypes = getParameterTypes();
+               for (int i = 0; i < myParameterTypes.length; i++) {
+                       UnresolvedType thisParameter = myParameterTypes[i];
+                       if (thisParameter.isTypeVariableReference()) {
+                               TypeVariableReferenceType typeVariableRT = (TypeVariableReferenceType) thisParameter;
+                               sig.append(typeVariableRT.getUpperBound().getSignature());
+                       } else {
+                               sig.append(thisParameter.getErasureSignature());
+                       }
+               }
+               myParameterSignatureErasure = sig.toString();
+               return myParameterSignatureErasure;
+       }
+
+       public String getSignatureErased() {
+               StringBuffer sb = new StringBuffer();
+               sb.append("(");
+               sb.append(getParameterSignatureErased());
+               sb.append(")");
+               sb.append(getReturnType().getErasureSignature());
+               return sb.toString();
+       }
+
+       // does NOT produce a meaningful java signature, but does give a unique
+       // string suitable for
+       // comparison.
+       public static void appendSigWithTypeVarBoundsRemoved(UnresolvedType aType, StringBuffer toBuffer, Set alreadyUsedTypeVars) {
+               if (aType.isTypeVariableReference()) {
+                       TypeVariableReferenceType typeVariableRT = (TypeVariableReferenceType) aType;
+                       // pr204505
+                       if (alreadyUsedTypeVars.contains(aType)) {
+                               toBuffer.append("...");
+                       } else {
+                               alreadyUsedTypeVars.add(aType);
+                               appendSigWithTypeVarBoundsRemoved(typeVariableRT.getUpperBound(), toBuffer, alreadyUsedTypeVars);
+                       }
+                       // toBuffer.append("T;");
+               } else if (aType.isParameterizedType()) {
+                       toBuffer.append(aType.getRawType().getSignature());
+                       toBuffer.append("<");
+                       for (int i = 0; i < aType.getTypeParameters().length; i++) {
+                               appendSigWithTypeVarBoundsRemoved(aType.getTypeParameters()[i], toBuffer, alreadyUsedTypeVars);
+                       }
+                       toBuffer.append(">;");
+               } else {
+                       toBuffer.append(aType.getSignature());
+               }
+       }
+
+       /**
+        * Useful for writing tests, returns *everything* we know about this member.
+        */
+       public String toDebugString() {
+               StringBuffer r = new StringBuffer();
+
+               // modifiers
+               int mods = modifiers;
+               if ((mods & 4096) > 0)
+                       mods = mods - 4096; // remove synthetic (added in the ASM case but
+               // not in the BCEL case...)
+               if ((mods & 512) > 0)
+                       mods = mods - 512; // remove interface (added in the BCEL case but
+               // not in the ASM case...)
+               if ((mods & 131072) > 0)
+                       mods = mods - 131072; // remove deprecated (added in the ASM case
+               // but not in the BCEL case...)
+               String modsStr = Modifier.toString(mods);
+               if (modsStr.length() != 0)
+                       r.append(modsStr).append("(" + mods + ")").append(" ");
+
+               // type variables
+               if (typeVariables != null && typeVariables.length > 0) {
+                       r.append("<");
+                       for (int i = 0; i < typeVariables.length; i++) {
+                               if (i > 0)
+                                       r.append(",");
+                               TypeVariable t = typeVariables[i];
+                               r.append(t.toDebugString());
+                       }
+                       r.append("> ");
+               }
+
+               // 'declaring' type
+               r.append(getGenericReturnType().toDebugString());
+               r.append(' ');
+
+               // name
+               r.append(declaringType.getName());
+               r.append('.');
+               r.append(name);
+
+               // parameter signature if a method
+               if (kind != FIELD) {
+                       r.append("(");
+                       UnresolvedType[] params = getGenericParameterTypes();
+                       boolean parameterNamesExist = showParameterNames && parameterNames != null && parameterNames.length == params.length;
+                       if (params.length != 0) {
+                               for (int i = 0, len = params.length; i < len; i++) {
+                                       if (i > 0)
+                                               r.append(", ");
+                                       r.append(params[i].toDebugString());
+                                       if (parameterNamesExist)
+                                               r.append(" ").append(parameterNames[i]);
+                               }
+                       }
+                       r.append(")");
+               }
+               return r.toString();
+       }
+
+       // SECRETAPI - controlling whether parameter names come out in the debug
+       // string (for testing purposes)
+       public static boolean showParameterNames = true;
+
+       public String toGenericString() {
+               StringBuffer buf = new StringBuffer();
+               buf.append(getGenericReturnType().getSimpleName());
+               buf.append(' ');
+               buf.append(declaringType.getName());
+               buf.append('.');
+               buf.append(name);
+               if (kind != FIELD) {
+                       buf.append("(");
+                       UnresolvedType[] params = getGenericParameterTypes();
+                       if (params.length != 0) {
+                               buf.append(params[0].getSimpleName());
+                               for (int i = 1, len = params.length; i < len; i++) {
+                                       buf.append(", ");
+                                       buf.append(params[i].getSimpleName());
+                               }
+                       }
+                       buf.append(")");
+               }
+               return buf.toString();
+       }
+
+       public boolean isCompatibleWith(Member am) {
+               if (kind != METHOD || am.getKind() != METHOD)
+                       return true;
+               if (!name.equals(am.getName()))
+                       return true;
+               if (!equalTypes(getParameterTypes(), am.getParameterTypes()))
+                       return true;
+               return getReturnType().equals(am.getReturnType());
+       }
+
+       private static boolean equalTypes(UnresolvedType[] a, UnresolvedType[] b) {
+               int len = a.length;
+               if (len != b.length)
+                       return false;
+               for (int i = 0; i < len; i++) {
+                       if (!a[i].equals(b[i]))
+                               return false;
+               }
+               return true;
+       }
+
+       public TypeVariable getTypeVariableNamed(String name) {
+               // Check locally...
+               if (typeVariables != null) {
+                       for (int i = 0; i < typeVariables.length; i++) {
+                               if (typeVariables[i].getName().equals(name))
+                                       return typeVariables[i];
+                       }
+               }
+               // check the declaring type!
+               return declaringType.getTypeVariableNamed(name);
+
+               // Do generic aspects with ITDs that share type variables with the
+               // aspect and the target type and have their own tvars cause
+               // this to be messier?
+       }
+
+       public void evictWeavingState() {
+       }
+
+       public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
+               throw new UnsupportedOperationException("You should resolve this member and call getAnnotationOfType() on the result...");
+       }
+
+       public boolean isEquivalentTo(Object other) {
+               return this.equals(other);
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedPointcutDefinition.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedPointcutDefinition.java
new file mode 100644 (file)
index 0000000..55e2741
--- /dev/null
@@ -0,0 +1,165 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.aspectj.weaver.patterns.Pointcut;
+
+
+public class ResolvedPointcutDefinition extends ResolvedMemberImpl {
+       private Pointcut pointcut;
+
+    public ResolvedPointcutDefinition(
+        UnresolvedType declaringType,
+        int modifiers,
+        String name,
+        UnresolvedType[] parameterTypes,
+        Pointcut pointcut)
+    {
+        this(declaringType, modifiers, name, parameterTypes, ResolvedType.VOID, pointcut);
+    }
+
+    /**
+     * An instance which can be given a specific returnType, used f.e. in if() pointcut for @AJ
+     * 
+     * @param declaringType
+     * @param modifiers
+     * @param name
+     * @param parameterTypes
+     * @param returnType
+     * @param pointcut
+     */
+    public ResolvedPointcutDefinition(
+               UnresolvedType declaringType,
+               int modifiers,
+               String name,
+               UnresolvedType[] parameterTypes,
+        UnresolvedType returnType,
+               Pointcut pointcut)
+    {
+               super(
+                       POINTCUT,
+                       declaringType,
+                       modifiers,
+                       returnType,
+                       name,
+                       parameterTypes);
+               this.pointcut = pointcut;
+               //XXXpointcut.assertState(Pointcut.RESOLVED);
+               checkedExceptions = UnresolvedType.NONE;
+       }
+       
+       // ----
+
+       public void write(DataOutputStream s) throws IOException {
+               getDeclaringType().write(s);
+               s.writeInt(getModifiers());
+               s.writeUTF(getName());
+               UnresolvedType.writeArray(getParameterTypes(), s);
+               pointcut.write(s);
+       }
+       
+       public static ResolvedPointcutDefinition read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               ResolvedPointcutDefinition rpd =
+                 new ResolvedPointcutDefinition(
+                       UnresolvedType.read(s),
+                       s.readInt(),
+                       s.readUTF(),
+                       UnresolvedType.readArray(s),
+                       Pointcut.read(s, context));
+               rpd.setSourceContext(context); // whilst we have a source context, let's remember it
+               return rpd;
+       }
+       
+       public String toString() {
+               StringBuffer buf = new StringBuffer();
+               buf.append("pointcut ");
+               buf.append((getDeclaringType()==null?"<nullDeclaringType>":getDeclaringType().getName()));
+               buf.append(".");
+               buf.append(getName());
+               buf.append("(");
+               for (int i=0; i < getParameterTypes().length; i++) {
+                       if (i > 0) buf.append(", ");
+                       buf.append(getParameterTypes()[i].toString());
+               }
+               buf.append(")");
+               //buf.append(pointcut);
+               
+               return buf.toString();
+       }
+       
+       public Pointcut getPointcut() {
+               return pointcut;
+       }
+       
+       public boolean isAjSynthetic() {
+               return true;
+       }
+       
+       /**
+        * Called when asking a parameterized super-aspect for its pointcuts.
+        */
+       public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType, boolean isParameterized) {
+               TypeVariable[] typeVariables = getDeclaringType().resolve(newDeclaringType.getWorld()).getTypeVariables();
+               if (isParameterized && (typeVariables.length != typeParameters.length)) {
+                       throw new IllegalStateException("Wrong number of type parameters supplied");
+               }
+               Map typeMap = new HashMap();
+               boolean typeParametersSupplied = typeParameters!=null && typeParameters.length>0;
+               if (typeVariables!=null) {
+                       // If no 'replacements' were supplied in the typeParameters array then collapse
+                       // type variables to their first bound.
+                       for (int i = 0; i < typeVariables.length; i++) {
+                               UnresolvedType ut = (!typeParametersSupplied?typeVariables[i].getFirstBound():typeParameters[i]);
+                               typeMap.put(typeVariables[i].getName(),ut);
+                       }
+               }
+               UnresolvedType parameterizedReturnType = parameterize(getGenericReturnType(),typeMap,isParameterized);
+               UnresolvedType[] parameterizedParameterTypes = new UnresolvedType[getGenericParameterTypes().length];
+               for (int i = 0; i < parameterizedParameterTypes.length; i++) {
+                       parameterizedParameterTypes[i] = 
+                               parameterize(getGenericParameterTypes()[i], typeMap,isParameterized);
+               }
+               ResolvedPointcutDefinition ret = new ResolvedPointcutDefinition(
+                                       newDeclaringType,
+                                       getModifiers(),
+                                       getName(),
+                                       parameterizedParameterTypes,
+                                       parameterizedReturnType,
+                                       pointcut.parameterizeWith(typeMap,newDeclaringType.getWorld())
+                               );
+               ret.setTypeVariables(getTypeVariables());
+               ret.setSourceContext(getSourceContext());
+               ret.setPosition(getStart(),getEnd());
+               ret.setParameterNames(getParameterNames());
+               return ret;
+               //return this;
+       }
+       
+       // for testing
+       public static final ResolvedPointcutDefinition DUMMY =
+           new ResolvedPointcutDefinition(UnresolvedType.OBJECT, 0, "missing", 
+                                       UnresolvedType.NONE, Pointcut.makeMatchesNothing(Pointcut.RESOLVED));
+       
+       public static final ResolvedPointcutDefinition[] NO_POINTCUTS = new ResolvedPointcutDefinition[]{};
+
+       public void setPointcut(Pointcut pointcut) {
+               this.pointcut = pointcut;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java
new file mode 100644 (file)
index 0000000..670eb3a
--- /dev/null
@@ -0,0 +1,2201 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ *     Alexandre Vasseur    @AspectJ ITDs
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.Message;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.patterns.Declare;
+import org.aspectj.weaver.patterns.PerClause;
+
+public abstract class ResolvedType extends UnresolvedType implements AnnotatedElement {
+
+       public static final ResolvedType[] EMPTY_RESOLVED_TYPE_ARRAY = new ResolvedType[0];
+       public static final String PARAMETERIZED_TYPE_IDENTIFIER = "P";
+
+       // Set during a type pattern match call - this currently used to hold the
+       // annotations
+       // that may be attached to a type when it used as a parameter
+       public ResolvedType[] temporaryAnnotationTypes;
+       private ResolvedType[] resolvedTypeParams;
+       private String binaryPath;
+
+       protected World world;
+
+       protected ResolvedType(String signature, World world) {
+               super(signature);
+               this.world = world;
+       }
+
+       protected ResolvedType(String signature, String signatureErasure, World world) {
+               super(signature, signatureErasure);
+               this.world = world;
+       }
+
+       // ---- things that don't require a world
+
+       /**
+        * Returns an iterator through ResolvedType objects representing all the direct supertypes of this type. That is, through the
+        * superclass, if any, and all declared interfaces.
+        */
+       public final Iterator getDirectSupertypes() {
+               Iterator ifacesIterator = Iterators.array(getDeclaredInterfaces());
+               ResolvedType superclass = getSuperclass();
+               if (superclass == null) {
+                       return ifacesIterator;
+               } else {
+                       return Iterators.snoc(ifacesIterator, superclass);
+               }
+       }
+
+       public abstract ResolvedMember[] getDeclaredFields();
+
+       public abstract ResolvedMember[] getDeclaredMethods();
+
+       public abstract ResolvedType[] getDeclaredInterfaces();
+
+       public abstract ResolvedMember[] getDeclaredPointcuts();
+
+       /**
+        * Returns a ResolvedType object representing the superclass of this type, or null. If this represents a java.lang.Object, a
+        * primitive type, or void, this method returns null.
+        */
+       public abstract ResolvedType getSuperclass();
+
+       /**
+        * Returns the modifiers for this type.
+        * <p/>
+        * See {@link Class#getModifiers()} for a description of the weirdness of this methods on primitives and arrays.
+        * 
+        * @param world the {@link World} in which the lookup is made.
+        * @return an int representing the modifiers for this type
+        * @see java.lang.reflect.Modifier
+        */
+       public abstract int getModifiers();
+
+       // return true if this resolved type couldn't be found (but we know it's
+       // name maybe)
+       public boolean isMissing() {
+               return false;
+       }
+
+       // FIXME asc I wonder if in some circumstances MissingWithKnownSignature
+       // should not be considered
+       // 'really' missing as some code can continue based solely on the signature
+       public static boolean isMissing(UnresolvedType unresolved) {
+               if (unresolved instanceof ResolvedType) {
+                       ResolvedType resolved = (ResolvedType) unresolved;
+                       return resolved.isMissing();
+               } else
+                       return (unresolved == MISSING);
+       }
+
+       public ResolvedType[] getAnnotationTypes() {
+               return EMPTY_RESOLVED_TYPE_ARRAY;
+       }
+
+       public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
+               return null;
+       }
+
+       // public final UnresolvedType getSuperclass(World world) {
+       // return getSuperclass();
+       // }
+
+       // This set contains pairs of types whose signatures are concatenated
+       // together, this means with a fast lookup we can tell if two types
+       // are equivalent.
+       protected static Set validBoxing = new HashSet();
+
+       static {
+               validBoxing.add("Ljava/lang/Byte;B");
+               validBoxing.add("Ljava/lang/Character;C");
+               validBoxing.add("Ljava/lang/Double;D");
+               validBoxing.add("Ljava/lang/Float;F");
+               validBoxing.add("Ljava/lang/Integer;I");
+               validBoxing.add("Ljava/lang/Long;J");
+               validBoxing.add("Ljava/lang/Short;S");
+               validBoxing.add("Ljava/lang/Boolean;Z");
+               validBoxing.add("BLjava/lang/Byte;");
+               validBoxing.add("CLjava/lang/Character;");
+               validBoxing.add("DLjava/lang/Double;");
+               validBoxing.add("FLjava/lang/Float;");
+               validBoxing.add("ILjava/lang/Integer;");
+               validBoxing.add("JLjava/lang/Long;");
+               validBoxing.add("SLjava/lang/Short;");
+               validBoxing.add("ZLjava/lang/Boolean;");
+       }
+
+       // utilities
+       public ResolvedType getResolvedComponentType() {
+               return null;
+       }
+
+       public World getWorld() {
+               return world;
+       }
+
+       // ---- things from object
+
+       public final boolean equals(Object other) {
+               if (other instanceof ResolvedType) {
+                       return this == other;
+               } else {
+                       return super.equals(other);
+               }
+       }
+
+       // ---- difficult things
+
+       /**
+        * returns an iterator through all of the fields of this type, in order for checking from JVM spec 2ed 5.4.3.2. This means that
+        * the order is
+        * <p/>
+        * <ul>
+        * <li>fields from current class</li>
+        * <li>recur into direct superinterfaces</li>
+        * <li>recur into superclass</li>
+        * </ul>
+        * <p/>
+        * We keep a hashSet of interfaces that we've visited so we don't spiral out into 2^n land.
+        */
+       public Iterator getFields() {
+               final Iterators.Filter dupFilter = Iterators.dupFilter();
+               Iterators.Getter typeGetter = new Iterators.Getter() {
+                       public Iterator get(Object o) {
+                               return dupFilter.filter(((ResolvedType) o).getDirectSupertypes());
+                       }
+               };
+               Iterators.Getter fieldGetter = new Iterators.Getter() {
+                       public Iterator get(Object o) {
+                               return Iterators.array(((ResolvedType) o).getDeclaredFields());
+                       }
+               };
+               return Iterators.mapOver(Iterators.recur(this, typeGetter), fieldGetter);
+       }
+
+       /**
+        * returns an iterator through all of the methods of this type, in order for checking from JVM spec 2ed 5.4.3.3. This means that
+        * the order is
+        * <p/>
+        * <ul>
+        * <li>methods from current class</li>
+        * <li>recur into superclass, all the way up, not touching interfaces</li>
+        * <li>recur into all superinterfaces, in some unspecified order</li>
+        * </ul>
+        * <p/>
+        * We keep a hashSet of interfaces that we've visited so we don't spiral out into 2^n land. NOTE: Take a look at the javadoc on
+        * getMethodsWithoutIterator() to see if you are sensitive to a quirk in getMethods()
+        */
+       public Iterator getMethods() {
+               final Iterators.Filter dupFilter = Iterators.dupFilter();
+               Iterators.Getter ifaceGetter = new Iterators.Getter() {
+                       public Iterator get(Object o) {
+                               return dupFilter.filter(Iterators.array(((ResolvedType) o).getDeclaredInterfaces()));
+                       }
+               };
+               Iterators.Getter methodGetter = new Iterators.Getter() {
+                       public Iterator get(Object o) {
+                               return Iterators.array(((ResolvedType) o).getDeclaredMethods());
+                       }
+               };
+               return Iterators.mapOver(Iterators.append(new Iterator() {
+                       ResolvedType curr = ResolvedType.this;
+
+                       public boolean hasNext() {
+                               return curr != null;
+                       }
+
+                       public Object next() {
+                               ResolvedType ret = curr;
+                               curr = curr.getSuperclass();
+                               return ret;
+                       }
+
+                       public void remove() {
+                               throw new UnsupportedOperationException();
+                       }
+               }, Iterators.recur(this, ifaceGetter)), methodGetter);
+       }
+
+       /**
+        * Return a list of methods, first those declared on this class, then those declared on the superclass (recurse) and then those
+        * declared on the superinterfaces. The getMethods() call above doesn't quite work the same as it will (through the iterator)
+        * return methods declared on *this* class twice, once at the start and once at the end - I couldn't debug that problem, so
+        * created this alternative.
+        */
+       public List getMethodsWithoutIterator(boolean includeITDs, boolean allowMissing) {
+               List methods = new ArrayList();
+               Set knowninterfaces = new HashSet();
+               addAndRecurse(knowninterfaces, methods, this, includeITDs, allowMissing);
+               return methods;
+       }
+
+       private void addAndRecurse(Set knowninterfaces, List collector, ResolvedType rtx, boolean includeITDs, boolean allowMissing) {
+               collector.addAll(Arrays.asList(rtx.getDeclaredMethods())); // Add the
+               // methods
+               // declared
+               // on this
+               // type
+               // now add all the inter-typed members too
+               if (includeITDs && rtx.interTypeMungers != null) {
+                       for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
+                               ConcreteTypeMunger tm = (ConcreteTypeMunger) i.next();
+                               ResolvedMember rm = tm.getSignature();
+                               if (rm != null) { // new parent type munger can have null
+                                       // signature...
+                                       collector.add(tm.getSignature());
+                               }
+                       }
+               }
+               if (!rtx.equals(ResolvedType.OBJECT)) {
+                       ResolvedType superType = rtx.getSuperclass();
+                       if (superType != null && !superType.isMissing()) {
+                               addAndRecurse(knowninterfaces, collector, superType, includeITDs, allowMissing); // Recurse if we aren't at
+                               // the top
+                       }
+               }
+               ResolvedType[] interfaces = rtx.getDeclaredInterfaces(); // Go through
+               // the
+               // interfaces
+               // on the
+               // way back
+               // down
+               for (int i = 0; i < interfaces.length; i++) {
+                       ResolvedType iface = interfaces[i];
+
+                       // we need to know if it is an interface from Parent kind munger
+                       // as those are used for @AJ ITD and we precisely want to skip those
+                       boolean shouldSkip = false;
+                       for (int j = 0; j < rtx.interTypeMungers.size(); j++) {
+                               ConcreteTypeMunger munger = (ConcreteTypeMunger) rtx.interTypeMungers.get(j);
+                               if (munger.getMunger() != null && munger.getMunger().getKind() == ResolvedTypeMunger.Parent
+                                               && ((NewParentTypeMunger) munger.getMunger()).getNewParent().equals(iface) // pr171953
+                               ) {
+                                       shouldSkip = true;
+                                       break;
+                               }
+                       }
+
+                       if (!shouldSkip && !knowninterfaces.contains(iface)) { // Dont do
+                               // interfaces
+                               // more than
+                               // once
+                               knowninterfaces.add(iface);
+                               if (allowMissing && iface.isMissing()) {
+                                       if (iface instanceof MissingResolvedTypeWithKnownSignature) {
+                                               ((MissingResolvedTypeWithKnownSignature) iface).raiseWarningOnMissingInterfaceWhilstFindingMethods();
+                                       }
+                               } else {
+                                       addAndRecurse(knowninterfaces, collector, iface, includeITDs, allowMissing);
+                               }
+                       }
+               }
+       }
+
+       public ResolvedType[] getResolvedTypeParameters() {
+               if (resolvedTypeParams == null) {
+                       resolvedTypeParams = world.resolve(typeParameters);
+               }
+               return resolvedTypeParams;
+       }
+
+       /**
+        * described in JVM spec 2ed 5.4.3.2
+        */
+       public ResolvedMember lookupField(Member m) {
+               return lookupMember(m, getFields());
+       }
+
+       /**
+        * described in JVM spec 2ed 5.4.3.3. Doesnt check ITDs.
+        */
+       public ResolvedMember lookupMethod(Member m) {
+               return lookupMember(m, getMethods());
+       }
+
+       public ResolvedMember lookupMethodInITDs(Member m) {
+               if (interTypeMungers != null) {
+                       for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
+                               ConcreteTypeMunger tm = (ConcreteTypeMunger) i.next();
+                               if (matches(tm.getSignature(), m)) {
+                                       return tm.getSignature();
+                               }
+                       }
+               }
+               return null;
+       }
+
+       /**
+        * return null if not found
+        */
+       private ResolvedMember lookupMember(Member m, Iterator i) {
+               while (i.hasNext()) {
+                       ResolvedMember f = (ResolvedMember) i.next();
+                       if (matches(f, m))
+                               return f;
+                       if (f.hasBackingGenericMember() && m.getName().equals(f.getName())) { // might
+                               // be
+                               // worth
+                               // checking
+                               // the
+                               // method
+                               // behind
+                               // the
+                               // parameterized method (see pr137496)
+                               if (matches(f.getBackingGenericMember(), m))
+                                       return f;
+                       }
+               }
+               return null; // ResolvedMember.Missing;
+               // throw new BCException("can't find " + m);
+       }
+
+       /**
+        * return null if not found
+        */
+       private ResolvedMember lookupMember(Member m, ResolvedMember[] a) {
+               for (int i = 0; i < a.length; i++) {
+                       ResolvedMember f = a[i];
+                       if (matches(f, m))
+                               return f;
+               }
+               return null;
+       }
+
+       /**
+        * Looks for the first member in the hierarchy matching aMember. This method differs from lookupMember(Member) in that it takes
+        * into account parameters which are type variables - which clearly an unresolved Member cannot do since it does not know
+        * anything about type variables.
+        */
+       public ResolvedMember lookupResolvedMember(ResolvedMember aMember, boolean allowMissing) {
+               Iterator toSearch = null;
+               ResolvedMember found = null;
+               if ((aMember.getKind() == Member.METHOD) || (aMember.getKind() == Member.CONSTRUCTOR)) {
+                       toSearch = getMethodsWithoutIterator(true, allowMissing).iterator();
+               } else {
+                       if (aMember.getKind() != Member.FIELD)
+                               throw new IllegalStateException("I didn't know you would look for members of kind " + aMember.getKind());
+                       toSearch = getFields();
+               }
+               while (toSearch.hasNext()) {
+                       ResolvedMemberImpl candidate = (ResolvedMemberImpl) toSearch.next();
+                       if (candidate.matches(aMember)) {
+                               found = candidate;
+                               break;
+                       }
+               }
+
+               return found;
+       }
+
+       public static boolean matches(Member m1, Member m2) {
+               if (m1 == null)
+                       return m2 == null;
+               if (m2 == null)
+                       return false;
+
+               // Check the names
+               boolean equalNames = m1.getName().equals(m2.getName());
+               if (!equalNames)
+                       return false;
+
+               // Check the signatures
+               boolean equalSignatures = m1.getSignature().equals(m2.getSignature());
+               if (equalSignatures)
+                       return true;
+
+               // If they aren't the same, we need to allow for covariance ... where
+               // one sig might be ()LCar; and
+               // the subsig might be ()LFastCar; - where FastCar is a subclass of Car
+               boolean equalCovariantSignatures = m1.getParameterSignature().equals(m2.getParameterSignature());
+               if (equalCovariantSignatures)
+                       return true;
+
+               return false;
+       }
+
+       public static boolean conflictingSignature(Member m1, Member m2) {
+               if (m1 == null || m2 == null)
+                       return false;
+
+               if (!m1.getName().equals(m2.getName())) {
+                       return false;
+               }
+               if (m1.getKind() != m2.getKind()) {
+                       return false;
+               }
+
+               if (m1.getKind() == Member.FIELD) {
+                       return m1.getDeclaringType().equals(m2.getDeclaringType());
+               } else if (m1.getKind() == Member.POINTCUT) {
+                       return true;
+               }
+
+               UnresolvedType[] p1 = m1.getGenericParameterTypes();
+               UnresolvedType[] p2 = m2.getGenericParameterTypes();
+               if (p1 == null)
+                       p1 = m1.getParameterTypes();
+               if (p2 == null)
+                       p2 = m2.getParameterTypes();
+               int n = p1.length;
+               if (n != p2.length)
+                       return false;
+
+               for (int i = 0; i < n; i++) {
+                       if (!p1[i].equals(p2[i]))
+                               return false;
+               }
+               return true;
+       }
+
+       /**
+        * returns an iterator through all of the pointcuts of this type, in order for checking from JVM spec 2ed 5.4.3.2 (as for
+        * fields). This means that the order is
+        * <p/>
+        * <ul>
+        * <li>pointcuts from current class</li>
+        * <li>recur into direct superinterfaces</li>
+        * <li>recur into superclass</li>
+        * </ul>
+        * <p/>
+        * We keep a hashSet of interfaces that we've visited so we don't spiral out into 2^n land.
+        */
+       public Iterator getPointcuts() {
+               final Iterators.Filter dupFilter = Iterators.dupFilter();
+               // same order as fields
+               Iterators.Getter typeGetter = new Iterators.Getter() {
+                       public Iterator get(Object o) {
+                               return dupFilter.filter(((ResolvedType) o).getDirectSupertypes());
+                       }
+               };
+               Iterators.Getter pointcutGetter = new Iterators.Getter() {
+                       public Iterator get(Object o) {
+                               // System.err.println("getting for " + o);
+                               return Iterators.array(((ResolvedType) o).getDeclaredPointcuts());
+                       }
+               };
+               return Iterators.mapOver(Iterators.recur(this, typeGetter), pointcutGetter);
+       }
+
+       public ResolvedPointcutDefinition findPointcut(String name) {
+               // System.err.println("looking for pointcuts " + this);
+               for (Iterator i = getPointcuts(); i.hasNext();) {
+                       ResolvedPointcutDefinition f = (ResolvedPointcutDefinition) i.next();
+                       // System.err.println(f);
+                       if (name.equals(f.getName())) {
+                               return f;
+                       }
+               }
+               // pr120521
+               if (!getOutermostType().equals(this)) {
+                       ResolvedType outerType = getOutermostType().resolve(world);
+                       ResolvedPointcutDefinition rpd = outerType.findPointcut(name);
+                       return rpd;
+               }
+               return null; // should we throw an exception here?
+       }
+
+       // all about collecting CrosscuttingMembers
+
+       // ??? collecting data-structure, shouldn't really be a field
+       public CrosscuttingMembers crosscuttingMembers;
+
+       public CrosscuttingMembers collectCrosscuttingMembers(boolean shouldConcretizeIfNeeded) {
+               crosscuttingMembers = new CrosscuttingMembers(this, shouldConcretizeIfNeeded);
+               crosscuttingMembers.setPerClause(getPerClause());
+               crosscuttingMembers.addShadowMungers(collectShadowMungers());
+               // GENERICITDFIX
+               // crosscuttingMembers.addTypeMungers(collectTypeMungers());
+               crosscuttingMembers.addTypeMungers(getTypeMungers());
+               // FIXME AV - skip but needed ?? or ??
+               // crosscuttingMembers.addLateTypeMungers(getLateTypeMungers());
+               crosscuttingMembers.addDeclares(collectDeclares(!this.doesNotExposeShadowMungers()));
+               crosscuttingMembers.addPrivilegedAccesses(getPrivilegedAccesses());
+
+               // System.err.println("collected cc members: " + this + ", " +
+               // collectDeclares());
+               return crosscuttingMembers;
+       }
+
+       public final Collection collectDeclares(boolean includeAdviceLike) {
+               if (!this.isAspect())
+                       return Collections.EMPTY_LIST;
+
+               ArrayList ret = new ArrayList();
+               // if (this.isAbstract()) {
+               // for (Iterator i = getDeclares().iterator(); i.hasNext();) {
+               // Declare dec = (Declare) i.next();
+               // if (!dec.isAdviceLike()) ret.add(dec);
+               // }
+               //        
+               // if (!includeAdviceLike) return ret;
+
+               if (!this.isAbstract()) {
+                       // ret.addAll(getDeclares());
+                       final Iterators.Filter dupFilter = Iterators.dupFilter();
+                       Iterators.Getter typeGetter = new Iterators.Getter() {
+                               public Iterator get(Object o) {
+                                       return dupFilter.filter(((ResolvedType) o).getDirectSupertypes());
+                               }
+                       };
+                       Iterator typeIterator = Iterators.recur(this, typeGetter);
+
+                       while (typeIterator.hasNext()) {
+                               ResolvedType ty = (ResolvedType) typeIterator.next();
+                               // System.out.println("super: " + ty + ", " + );
+                               for (Iterator i = ty.getDeclares().iterator(); i.hasNext();) {
+                                       Declare dec = (Declare) i.next();
+                                       if (dec.isAdviceLike()) {
+                                               if (includeAdviceLike)
+                                                       ret.add(dec);
+                                       } else {
+                                               ret.add(dec);
+                                       }
+                               }
+                       }
+               }
+
+               return ret;
+       }
+
+       private final Collection collectShadowMungers() {
+               if (!this.isAspect() || this.isAbstract() || this.doesNotExposeShadowMungers())
+                       return Collections.EMPTY_LIST;
+
+               ArrayList acc = new ArrayList();
+               final Iterators.Filter dupFilter = Iterators.dupFilter();
+               Iterators.Getter typeGetter = new Iterators.Getter() {
+                       public Iterator get(Object o) {
+                               return dupFilter.filter(((ResolvedType) o).getDirectSupertypes());
+                       }
+               };
+               Iterator typeIterator = Iterators.recur(this, typeGetter);
+
+               while (typeIterator.hasNext()) {
+                       ResolvedType ty = (ResolvedType) typeIterator.next();
+                       acc.addAll(ty.getDeclaredShadowMungers());
+               }
+
+               return acc;
+       }
+
+       protected boolean doesNotExposeShadowMungers() {
+               return false;
+       }
+
+       public PerClause getPerClause() {
+               return null;
+       }
+
+       public Collection getDeclares() {
+               return Collections.EMPTY_LIST;
+       }
+
+       protected Collection getTypeMungers() {
+               return Collections.EMPTY_LIST;
+       }
+
+       protected Collection getPrivilegedAccesses() {
+               return Collections.EMPTY_LIST;
+       }
+
+       // ---- useful things
+
+       public final boolean isInterface() {
+               return Modifier.isInterface(getModifiers());
+       }
+
+       public final boolean isAbstract() {
+               return Modifier.isAbstract(getModifiers());
+       }
+
+       public boolean isClass() {
+               return false;
+       }
+
+       public boolean isAspect() {
+               return false;
+       }
+
+       public boolean isAnnotationStyleAspect() {
+               return false;
+       }
+
+       /**
+        * Note: Only overridden by Name subtype.
+        */
+       public boolean isEnum() {
+               return false;
+       }
+
+       /**
+        * Note: Only overridden by Name subtype.
+        */
+       public boolean isAnnotation() {
+               return false;
+       }
+
+       public boolean isAnonymous() {
+               return false;
+       }
+
+       public boolean isNested() {
+               return false;
+       }
+
+       public void addAnnotation(AnnotationAJ annotationX) {
+               throw new RuntimeException("ResolvedType.addAnnotation() should never be called");
+       }
+
+       public AnnotationAJ[] getAnnotations() {
+               throw new RuntimeException("ResolvedType.getAnnotations() should never be called");
+       }
+
+       /**
+        * Note: Only overridden by ReferenceType subtype
+        */
+       public boolean canAnnotationTargetType() {
+               return false;
+       }
+
+       /**
+        * Note: Only overridden by ReferenceType subtype
+        */
+       public AnnotationTargetKind[] getAnnotationTargetKinds() {
+               return null;
+       }
+
+       /**
+        * Note: Only overridden by Name subtype.
+        */
+       public boolean isAnnotationWithRuntimeRetention() {
+               return false;
+       }
+
+       public boolean isSynthetic() {
+               return signature.indexOf("$ajc") != -1;
+       }
+
+       public final boolean isFinal() {
+               return Modifier.isFinal(getModifiers());
+       }
+
+       protected Map /* Type variable name -> UnresolvedType */getMemberParameterizationMap() {
+               if (!isParameterizedType())
+                       return Collections.EMPTY_MAP;
+               TypeVariable[] tvs = getGenericType().getTypeVariables();
+               Map parameterizationMap = new HashMap();
+               for (int i = 0; i < tvs.length; i++) {
+                       parameterizationMap.put(tvs[i].getName(), typeParameters[i]);
+               }
+               return parameterizationMap;
+       }
+
+       public Collection getDeclaredAdvice() {
+               List l = new ArrayList();
+               ResolvedMember[] methods = getDeclaredMethods();
+               if (isParameterizedType())
+                       methods = getGenericType().getDeclaredMethods();
+               Map typeVariableMap = getAjMemberParameterizationMap();
+               for (int i = 0, len = methods.length; i < len; i++) {
+                       ShadowMunger munger = methods[i].getAssociatedShadowMunger();
+                       if (munger != null) {
+                               if (ajMembersNeedParameterization()) {
+                                       // munger.setPointcut(munger.getPointcut().parameterizeWith(
+                                       // typeVariableMap));
+                                       munger = munger.parameterizeWith(this, typeVariableMap);
+                                       if (munger instanceof Advice) {
+                                               Advice advice = (Advice) munger;
+                                               // update to use the parameterized signature...
+                                               UnresolvedType[] ptypes = methods[i].getGenericParameterTypes();
+                                               UnresolvedType[] newPTypes = new UnresolvedType[ptypes.length];
+                                               for (int j = 0; j < ptypes.length; j++) {
+                                                       if (ptypes[j] instanceof TypeVariableReferenceType) {
+                                                               TypeVariableReferenceType tvrt = (TypeVariableReferenceType) ptypes[j];
+                                                               if (typeVariableMap.containsKey(tvrt.getTypeVariable().getName())) {
+                                                                       newPTypes[j] = (UnresolvedType) typeVariableMap.get(tvrt.getTypeVariable().getName());
+                                                               } else {
+                                                                       newPTypes[j] = ptypes[j];
+                                                               }
+                                                       } else {
+                                                               newPTypes[j] = ptypes[j];
+                                                       }
+                                               }
+                                               advice.setBindingParameterTypes(newPTypes);
+                                       }
+                               }
+                               munger.setDeclaringType(this);
+                               l.add(munger);
+                       }
+               }
+               return l;
+       }
+
+       public Collection getDeclaredShadowMungers() {
+               Collection c = getDeclaredAdvice();
+               return c;
+       }
+
+       // ---- only for testing!
+
+       public ResolvedMember[] getDeclaredJavaFields() {
+               return filterInJavaVisible(getDeclaredFields());
+       }
+
+       public ResolvedMember[] getDeclaredJavaMethods() {
+               return filterInJavaVisible(getDeclaredMethods());
+       }
+
+       public ShadowMunger[] getDeclaredShadowMungersArray() {
+               List l = (List) getDeclaredShadowMungers();
+               return (ShadowMunger[]) l.toArray(new ShadowMunger[l.size()]);
+       }
+
+       private ResolvedMember[] filterInJavaVisible(ResolvedMember[] ms) {
+               List l = new ArrayList();
+               for (int i = 0, len = ms.length; i < len; i++) {
+                       if (!ms[i].isAjSynthetic() && ms[i].getAssociatedShadowMunger() == null) {
+                               l.add(ms[i]);
+                       }
+               }
+               return (ResolvedMember[]) l.toArray(new ResolvedMember[l.size()]);
+       }
+
+       public abstract ISourceContext getSourceContext();
+
+       // ---- fields
+
+       public static final ResolvedType[] NONE = new ResolvedType[0];
+
+       public static final Primitive BYTE = new Primitive("B", 1, 0);
+       public static final Primitive CHAR = new Primitive("C", 1, 1);
+       public static final Primitive DOUBLE = new Primitive("D", 2, 2);
+       public static final Primitive FLOAT = new Primitive("F", 1, 3);
+       public static final Primitive INT = new Primitive("I", 1, 4);
+       public static final Primitive LONG = new Primitive("J", 2, 5);
+       public static final Primitive SHORT = new Primitive("S", 1, 6);
+       public static final Primitive VOID = new Primitive("V", 0, 8);
+       public static final Primitive BOOLEAN = new Primitive("Z", 1, 7);
+       public static final Missing MISSING = new Missing();
+
+       /** Reset the static state in the primitive types */
+       // OPTIMIZE I think we have a bug here because primitives are static and the
+       // world they use may vary (or may even be
+       // null)
+       public static void resetPrimitives() {
+               BYTE.world = null;
+               CHAR.world = null;
+               DOUBLE.world = null;
+               FLOAT.world = null;
+               INT.world = null;
+               LONG.world = null;
+               SHORT.world = null;
+               VOID.world = null;
+               BOOLEAN.world = null;
+       }
+
+       // ---- types
+       public static ResolvedType makeArray(ResolvedType type, int dim) {
+               if (dim == 0)
+                       return type;
+               ResolvedType array = new ArrayReferenceType("[" + type.getSignature(), "[" + type.getErasureSignature(), type.getWorld(),
+                               type);
+               return makeArray(array, dim - 1);
+       }
+
+       static class Primitive extends ResolvedType {
+               private final int size;
+               private final int index;
+
+               Primitive(String signature, int size, int index) {
+                       super(signature, null);
+                       this.size = size;
+                       this.index = index;
+                       this.typeKind = TypeKind.PRIMITIVE;
+               }
+
+               public final int getSize() {
+                       return size;
+               }
+
+               public final int getModifiers() {
+                       return Modifier.PUBLIC | Modifier.FINAL;
+               }
+
+               public final boolean isPrimitiveType() {
+                       return true;
+               }
+
+               public boolean hasAnnotation(UnresolvedType ofType) {
+                       return false;
+               }
+
+               public final boolean isAssignableFrom(ResolvedType other) {
+                       if (!other.isPrimitiveType()) {
+                               if (!world.isInJava5Mode())
+                                       return false;
+                               return validBoxing.contains(this.getSignature() + other.getSignature());
+                       }
+                       return assignTable[((Primitive) other).index][index];
+               }
+
+               public final boolean isAssignableFrom(ResolvedType other, boolean allowMissing) {
+                       return isAssignableFrom(other);
+               }
+
+               public final boolean isCoerceableFrom(ResolvedType other) {
+                       if (this == other)
+                               return true;
+                       if (!other.isPrimitiveType())
+                               return false;
+                       if (index > 6 || ((Primitive) other).index > 6)
+                               return false;
+                       return true;
+               }
+
+               public ResolvedType resolve(World world) {
+                       this.world = world;
+                       return super.resolve(world);
+               }
+
+               public final boolean needsNoConversionFrom(ResolvedType other) {
+                       if (!other.isPrimitiveType())
+                               return false;
+                       return noConvertTable[((Primitive) other).index][index];
+               }
+
+               private static final boolean[][] assignTable = {// to: B C D F I J S V Z
+               // from
+                               { true, true, true, true, true, true, true, false, false }, // B
+                               { false, true, true, true, true, true, false, false, false }, // C
+                               { false, false, true, false, false, false, false, false, false }, // D
+                               { false, false, true, true, false, false, false, false, false }, // F
+                               { false, false, true, true, true, true, false, false, false }, // I
+                               { false, false, true, true, false, true, false, false, false }, // J
+                               { false, false, true, true, true, true, true, false, false }, // S
+                               { false, false, false, false, false, false, false, true, false }, // V
+                               { false, false, false, false, false, false, false, false, true }, // Z
+               };
+               private static final boolean[][] noConvertTable = {// to: B C D F I J S
+               // V Z from
+                               { true, true, false, false, true, false, true, false, false }, // B
+                               { false, true, false, false, true, false, false, false, false }, // C
+                               { false, false, true, false, false, false, false, false, false }, // D
+                               { false, false, false, true, false, false, false, false, false }, // F
+                               { false, false, false, false, true, false, false, false, false }, // I
+                               { false, false, false, false, false, true, false, false, false }, // J
+                               { false, false, false, false, true, false, true, false, false }, // S
+                               { false, false, false, false, false, false, false, true, false }, // V
+                               { false, false, false, false, false, false, false, false, true }, // Z
+               };
+
+               // ----
+
+               public final ResolvedMember[] getDeclaredFields() {
+                       return ResolvedMember.NONE;
+               }
+
+               public final ResolvedMember[] getDeclaredMethods() {
+                       return ResolvedMember.NONE;
+               }
+
+               public final ResolvedType[] getDeclaredInterfaces() {
+                       return ResolvedType.NONE;
+               }
+
+               public final ResolvedMember[] getDeclaredPointcuts() {
+                       return ResolvedMember.NONE;
+               }
+
+               public final ResolvedType getSuperclass() {
+                       return null;
+               }
+
+               public ISourceContext getSourceContext() {
+                       return null;
+               }
+
+       }
+
+       static class Missing extends ResolvedType {
+               Missing() {
+                       super(MISSING_NAME, null);
+               }
+
+               // public final String toString() {
+               // return "<missing>";
+               // }
+               public final String getName() {
+                       return MISSING_NAME;
+               }
+
+               public final boolean isMissing() {
+                       return true;
+               }
+
+               public boolean hasAnnotation(UnresolvedType ofType) {
+                       return false;
+               }
+
+               public final ResolvedMember[] getDeclaredFields() {
+                       return ResolvedMember.NONE;
+               }
+
+               public final ResolvedMember[] getDeclaredMethods() {
+                       return ResolvedMember.NONE;
+               }
+
+               public final ResolvedType[] getDeclaredInterfaces() {
+                       return ResolvedType.NONE;
+               }
+
+               public final ResolvedMember[] getDeclaredPointcuts() {
+                       return ResolvedMember.NONE;
+               }
+
+               public final ResolvedType getSuperclass() {
+                       return null;
+               }
+
+               public final int getModifiers() {
+                       return 0;
+               }
+
+               public final boolean isAssignableFrom(ResolvedType other) {
+                       return false;
+               }
+
+               public final boolean isAssignableFrom(ResolvedType other, boolean allowMissing) {
+                       return false;
+               }
+
+               public final boolean isCoerceableFrom(ResolvedType other) {
+                       return false;
+               }
+
+               public boolean needsNoConversionFrom(ResolvedType other) {
+                       return false;
+               }
+
+               public ISourceContext getSourceContext() {
+                       return null;
+               }
+
+       }
+
+       /**
+        * Look up a member, takes into account any ITDs on this type. return null if not found
+        */
+       public ResolvedMember lookupMemberNoSupers(Member member) {
+               ResolvedMember ret = lookupDirectlyDeclaredMemberNoSupers(member);
+               if (ret == null && interTypeMungers != null) {
+                       for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
+                               ConcreteTypeMunger tm = (ConcreteTypeMunger) i.next();
+                               if (matches(tm.getSignature(), member)) {
+                                       return tm.getSignature();
+                               }
+                       }
+               }
+               return ret;
+       }
+
+       public ResolvedMember lookupMemberWithSupersAndITDs(Member member) {
+               ResolvedMember ret = lookupMemberNoSupers(member);
+               if (ret != null)
+                       return ret;
+
+               ResolvedType supert = getSuperclass();
+               while (ret == null && supert != null) {
+                       ret = supert.lookupMemberNoSupers(member);
+                       if (ret == null)
+                               supert = supert.getSuperclass();
+               }
+
+               return ret;
+       }
+
+       /**
+        * as lookupMemberNoSupers, but does not include ITDs
+        * 
+        * @param member
+        * @return
+        */
+       public ResolvedMember lookupDirectlyDeclaredMemberNoSupers(Member member) {
+               ResolvedMember ret;
+               if (member.getKind() == Member.FIELD) {
+                       ret = lookupMember(member, getDeclaredFields());
+               } else {
+                       // assert member.getKind() == Member.METHOD || member.getKind() ==
+                       // Member.CONSTRUCTOR
+                       ret = lookupMember(member, getDeclaredMethods());
+               }
+               return ret;
+       }
+
+       /**
+        * This lookup has specialized behaviour - a null result tells the EclipseTypeMunger that it should make a default
+        * implementation of a method on this type.
+        * 
+        * @param member
+        * @return
+        */
+       public ResolvedMember lookupMemberIncludingITDsOnInterfaces(Member member) {
+               return lookupMemberIncludingITDsOnInterfaces(member, this);
+       }
+
+       private ResolvedMember lookupMemberIncludingITDsOnInterfaces(Member member, ResolvedType onType) {
+               ResolvedMember ret = onType.lookupMemberNoSupers(member);
+               if (ret != null) {
+                       return ret;
+               } else {
+                       ResolvedType superType = onType.getSuperclass();
+                       if (superType != null) {
+                               ret = lookupMemberIncludingITDsOnInterfaces(member, superType);
+                       }
+                       if (ret == null) {
+                               // try interfaces then, but only ITDs now...
+                               ResolvedType[] superInterfaces = onType.getDeclaredInterfaces();
+                               for (int i = 0; i < superInterfaces.length; i++) {
+                                       ret = superInterfaces[i].lookupMethodInITDs(member);
+                                       if (ret != null)
+                                               return ret;
+                               }
+                       }
+               }
+               return ret;
+       }
+
+       protected List interTypeMungers = new ArrayList(0);
+
+       public List getInterTypeMungers() {
+               return interTypeMungers;
+       }
+
+       public List getInterTypeParentMungers() {
+               List l = new ArrayList();
+               for (Iterator iter = interTypeMungers.iterator(); iter.hasNext();) {
+                       ConcreteTypeMunger element = (ConcreteTypeMunger) iter.next();
+                       if (element.getMunger() instanceof NewParentTypeMunger)
+                               l.add(element);
+               }
+               return l;
+       }
+
+       /**
+        * ??? This method is O(N*M) where N = number of methods and M is number of inter-type declarations in my super
+        */
+       public List getInterTypeMungersIncludingSupers() {
+               ArrayList ret = new ArrayList();
+               collectInterTypeMungers(ret);
+               return ret;
+       }
+
+       public List getInterTypeParentMungersIncludingSupers() {
+               ArrayList ret = new ArrayList();
+               collectInterTypeParentMungers(ret);
+               return ret;
+       }
+
+       private void collectInterTypeParentMungers(List collector) {
+               for (Iterator iter = getDirectSupertypes(); iter.hasNext();) {
+                       ResolvedType superType = (ResolvedType) iter.next();
+                       superType.collectInterTypeParentMungers(collector);
+               }
+               collector.addAll(getInterTypeParentMungers());
+       }
+
+       protected void collectInterTypeMungers(List collector) {
+               for (Iterator iter = getDirectSupertypes(); iter.hasNext();) {
+                       ResolvedType superType = (ResolvedType) iter.next();
+                       if (superType == null) {
+                               throw new BCException("UnexpectedProblem: a supertype in the hierarchy for " + this.getName() + " is null");
+                       }
+                       superType.collectInterTypeMungers(collector);
+               }
+
+               outer: for (Iterator iter1 = collector.iterator(); iter1.hasNext();) {
+                       ConcreteTypeMunger superMunger = (ConcreteTypeMunger) iter1.next();
+                       if (superMunger.getSignature() == null)
+                               continue;
+
+                       if (!superMunger.getSignature().isAbstract())
+                               continue;
+
+                       for (Iterator iter = getInterTypeMungers().iterator(); iter.hasNext();) {
+                               ConcreteTypeMunger myMunger = (ConcreteTypeMunger) iter.next();
+                               if (conflictingSignature(myMunger.getSignature(), superMunger.getSignature())) {
+                                       iter1.remove();
+                                       continue outer;
+                               }
+                       }
+
+                       if (!superMunger.getSignature().isPublic())
+                               continue;
+
+                       for (Iterator iter = getMethods(); iter.hasNext();) {
+                               ResolvedMember method = (ResolvedMember) iter.next();
+                               if (conflictingSignature(method, superMunger.getSignature())) {
+                                       iter1.remove();
+                                       continue outer;
+                               }
+                       }
+               }
+
+               collector.addAll(getInterTypeMungers());
+       }
+
+       /**
+        * Check: 1) That we don't have any abstract type mungers unless this type is abstract. 2) That an abstract ITDM on an interface
+        * is declared public. (Compiler limitation) (PR70794)
+        */
+       public void checkInterTypeMungers() {
+               if (isAbstract())
+                       return;
+
+               boolean itdProblem = false;
+
+               for (Iterator iter = getInterTypeMungersIncludingSupers().iterator(); iter.hasNext();) {
+                       ConcreteTypeMunger munger = (ConcreteTypeMunger) iter.next();
+                       itdProblem = checkAbstractDeclaration(munger) || itdProblem; // Rule
+                       // 2
+
+               }
+
+               if (itdProblem)
+                       return; // If the rules above are broken, return right now
+
+               for (Iterator iter = getInterTypeMungersIncludingSupers().iterator(); iter.hasNext();) {
+                       ConcreteTypeMunger munger = (ConcreteTypeMunger) iter.next();
+                       if (munger.getSignature() != null && munger.getSignature().isAbstract()) { // Rule 1
+                               if (munger.getMunger().getKind() == ResolvedTypeMunger.MethodDelegate) {
+                                       // ignore for @AJ ITD as munger.getSignature() is the
+                                       // interface method hence abstract
+                               } else {
+                                       world.getMessageHandler()
+                                                       .handleMessage(
+                                                                       new Message("must implement abstract inter-type declaration: " + munger.getSignature(), "",
+                                                                                       IMessage.ERROR, getSourceLocation(), null,
+                                                                                       new ISourceLocation[] { getMungerLocation(munger) }));
+                               }
+                       }
+               }
+       }
+
+       /**
+        * See PR70794. This method checks that if an abstract inter-type method declaration is made on an interface then it must also
+        * be public. This is a compiler limitation that could be made to work in the future (if someone provides a worthwhile usecase)
+        * 
+        * @return indicates if the munger failed the check
+        */
+       private boolean checkAbstractDeclaration(ConcreteTypeMunger munger) {
+               if (munger.getMunger() != null && (munger.getMunger() instanceof NewMethodTypeMunger)) {
+                       ResolvedMember itdMember = munger.getSignature();
+                       ResolvedType onType = itdMember.getDeclaringType().resolve(world);
+                       if (onType.isInterface() && itdMember.isAbstract() && !itdMember.isPublic()) {
+                               world.getMessageHandler().handleMessage(
+                                               new Message(WeaverMessages.format(WeaverMessages.ITD_ABSTRACT_MUST_BE_PUBLIC_ON_INTERFACE, munger
+                                                               .getSignature(), onType), "", Message.ERROR, getSourceLocation(), null,
+                                                               new ISourceLocation[] { getMungerLocation(munger) }));
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       /**
+        * Get a source location for the munger. Until intertype mungers remember where they came from, the source location for the
+        * munger itself is null. In these cases use the source location for the aspect containing the ITD.
+        */
+       private ISourceLocation getMungerLocation(ConcreteTypeMunger munger) {
+               ISourceLocation sloc = munger.getSourceLocation();
+               if (sloc == null) {
+                       sloc = munger.getAspectType().getSourceLocation();
+               }
+               return sloc;
+       }
+
+       /**
+        * Returns a ResolvedType object representing the declaring type of this type, or null if this type does not represent a
+        * non-package-level-type.
+        * <p/>
+        * <strong>Warning</strong>: This is guaranteed to work for all member types. For anonymous/local types, the only guarantee is
+        * given in JLS 13.1, where it guarantees that if you call getDeclaringType() repeatedly, you will eventually get the top-level
+        * class, but it does not say anything about classes in between.
+        * 
+        * @return the declaring UnresolvedType object, or null.
+        */
+       public ResolvedType getDeclaringType() {
+               if (isArray())
+                       return null;
+               String name = getName();
+               int lastDollar = name.lastIndexOf('$');
+               while (lastDollar > 0) { // allow for classes starting '$' (pr120474)
+                       ResolvedType ret = world.resolve(UnresolvedType.forName(name.substring(0, lastDollar)), true);
+                       if (!ResolvedType.isMissing(ret))
+                               return ret;
+                       lastDollar = name.lastIndexOf('$', lastDollar - 1);
+               }
+               return null;
+       }
+
+       public static boolean isVisible(int modifiers, ResolvedType targetType, ResolvedType fromType) {
+               // System.err.println("mod: " + modifiers + ", " + targetType + " and "
+               // + fromType);
+
+               if (Modifier.isPublic(modifiers)) {
+                       return true;
+               } else if (Modifier.isPrivate(modifiers)) {
+                       return targetType.getOutermostType().equals(fromType.getOutermostType());
+               } else if (Modifier.isProtected(modifiers)) {
+                       return samePackage(targetType, fromType) || targetType.isAssignableFrom(fromType);
+               } else { // package-visible
+                       return samePackage(targetType, fromType);
+               }
+       }
+
+       private static boolean samePackage(ResolvedType targetType, ResolvedType fromType) {
+               String p1 = targetType.getPackageName();
+               String p2 = fromType.getPackageName();
+               if (p1 == null)
+                       return p2 == null;
+               if (p2 == null)
+                       return false;
+               return p1.equals(p2);
+       }
+
+       /**
+        * Checks if the generic type for 'this' and the generic type for 'other' are the same - it can be passed raw or parameterized
+        * versions and will just compare the underlying generic type.
+        */
+       private boolean genericTypeEquals(ResolvedType other) {
+               ResolvedType rt = other;
+               if (rt.isParameterizedType() || rt.isRawType())
+                       rt.getGenericType();
+               if (((isParameterizedType() || isRawType()) && getGenericType().equals(rt)) || (this.equals(other)))
+                       return true;
+               return false;
+       }
+
+       /**
+        * Look up the actual occurence of a particular type in the hierarchy for 'this' type. The input is going to be a generic type,
+        * and the caller wants to know if it was used in its RAW or a PARAMETERIZED form in this hierarchy.
+        * 
+        * returns null if it can't be found.
+        */
+       public ResolvedType discoverActualOccurrenceOfTypeInHierarchy(ResolvedType lookingFor) {
+               if (!lookingFor.isGenericType())
+                       throw new BCException("assertion failed: method should only be called with generic type, but " + lookingFor + " is "
+                                       + lookingFor.typeKind);
+
+               if (this.equals(ResolvedType.OBJECT))
+                       return null;
+
+               if (genericTypeEquals(lookingFor))
+                       return this;
+
+               ResolvedType superT = getSuperclass();
+               if (superT.genericTypeEquals(lookingFor))
+                       return superT;
+
+               ResolvedType[] superIs = getDeclaredInterfaces();
+               for (int i = 0; i < superIs.length; i++) {
+                       ResolvedType superI = superIs[i];
+                       if (superI.genericTypeEquals(lookingFor))
+                               return superI;
+                       ResolvedType checkTheSuperI = superI.discoverActualOccurrenceOfTypeInHierarchy(lookingFor);
+                       if (checkTheSuperI != null)
+                               return checkTheSuperI;
+               }
+               return superT.discoverActualOccurrenceOfTypeInHierarchy(lookingFor);
+       }
+
+       /**
+        * Called for all type mungers but only does something if they share type variables with a generic type which they target. When
+        * this happens this routine will check for the target type in the target hierarchy and 'bind' any type parameters as
+        * appropriate. For example, for the ITD "List<T> I<T>.x" against a type like this: "class A implements I<String>" this routine
+        * will return a parameterized form of the ITD "List<String> I.x"
+        */
+       public ConcreteTypeMunger fillInAnyTypeParameters(ConcreteTypeMunger munger) {
+               boolean debug = false;
+               ResolvedMember member = munger.getSignature();
+               if (munger.isTargetTypeParameterized()) {
+                       if (debug)
+                               System.err.println("Processing attempted parameterization of " + munger + " targetting type " + this);
+                       if (debug)
+                               System.err.println("  This type is " + this + "  (" + typeKind + ")");
+                       // need to tailor this munger instance for the particular target...
+                       if (debug)
+                               System.err.println("  Signature that needs parameterizing: " + member);
+                       // Retrieve the generic type
+                       ResolvedType onType = world.resolve(member.getDeclaringType()).getGenericType();
+                       member.resolve(world); // Ensure all parts of the member are
+                       // resolved
+                       if (debug)
+                               System.err.println("  Actual target ontype: " + onType + "  (" + onType.typeKind + ")");
+                       // quickly find the targettype in the type hierarchy for this type
+                       // (it will be either RAW or PARAMETERIZED)
+                       ResolvedType actualTarget = discoverActualOccurrenceOfTypeInHierarchy(onType);
+                       if (actualTarget == null)
+                               throw new BCException("assertion failed: asked " + this + " for occurrence of " + onType + " in its hierarchy??");
+
+                       // only bind the tvars if its a parameterized type or the raw type
+                       // (in which case they collapse to bounds) - don't do it
+                       // for generic types ;)
+                       if (!actualTarget.isGenericType()) {
+                               if (debug)
+                                       System.err.println("Occurrence in " + this + " is actually " + actualTarget + "  (" + actualTarget.typeKind
+                                                       + ")");
+                               // parameterize the signature
+                               // ResolvedMember newOne =
+                               // member.parameterizedWith(actualTarget.getTypeParameters(),
+                               // onType,actualTarget.isParameterizedType());
+                       }
+                       // if (!actualTarget.isRawType())
+                       munger = munger.parameterizedFor(actualTarget);
+                       if (debug)
+                               System.err.println("New sig: " + munger.getSignature());
+
+                       if (debug)
+                               System.err.println("=====================================");
+               }
+               return munger;
+       }
+
+       public void addInterTypeMunger(ConcreteTypeMunger munger) {
+               ResolvedMember sig = munger.getSignature();
+               if (sig == null || munger.getMunger() == null || munger.getMunger().getKind() == ResolvedTypeMunger.PrivilegedAccess) {
+                       interTypeMungers.add(munger);
+                       return;
+               }
+
+               // ConcreteTypeMunger originalMunger = munger;
+               // we will use the 'parameterized' ITD for all the comparisons but we
+               // say the original
+               // one passed in actually matched as it will be added to the intertype
+               // member finder
+               // for the target type. It is possible we only want to do this if a
+               // generic type
+               // is discovered and the tvar is collapsed to a bound?
+               munger = fillInAnyTypeParameters(munger);
+               sig = munger.getSignature(); // possibly changed when type parms filled
+               // in
+
+               // System.err.println("add: " + munger + " to " + this.getClassName() +
+               // " with " + interTypeMungers);
+               if (sig.getKind() == Member.METHOD) {
+                       if (!compareToExistingMembers(munger, getMethodsWithoutIterator(false, true) /* getMethods() */))
+                               return;
+                       if (this.isInterface()) {
+                               if (!compareToExistingMembers(munger, Arrays.asList(world.getCoreType(OBJECT).getDeclaredMethods()).iterator()))
+                                       return;
+                       }
+               } else if (sig.getKind() == Member.FIELD) {
+                       if (!compareToExistingMembers(munger, Arrays.asList(getDeclaredFields()).iterator()))
+                               return;
+               } else {
+                       if (!compareToExistingMembers(munger, Arrays.asList(getDeclaredMethods()).iterator()))
+                               return;
+               }
+
+               // now compare to existingMungers
+               for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
+                       ConcreteTypeMunger existingMunger = (ConcreteTypeMunger) i.next();
+                       if (conflictingSignature(existingMunger.getSignature(), munger.getSignature())) {
+                               // System.err.println("match " + munger + " with " +
+                               // existingMunger);
+                               if (isVisible(munger.getSignature().getModifiers(), munger.getAspectType(), existingMunger.getAspectType())) {
+                                       // System.err.println("    is visible");
+                                       int c = compareMemberPrecedence(sig, existingMunger.getSignature());
+                                       if (c == 0) {
+                                               c = getWorld().compareByPrecedenceAndHierarchy(munger.getAspectType(), existingMunger.getAspectType());
+                                       }
+                                       // System.err.println("       compare: " + c);
+                                       if (c < 0) {
+                                               // the existing munger dominates the new munger
+                                               checkLegalOverride(munger.getSignature(), existingMunger.getSignature());
+                                               return;
+                                       } else if (c > 0) {
+                                               // the new munger dominates the existing one
+                                               checkLegalOverride(existingMunger.getSignature(), munger.getSignature());
+                                               i.remove();
+                                               break;
+                                       } else {
+                                               interTypeConflictError(munger, existingMunger);
+                                               interTypeConflictError(existingMunger, munger);
+                                               return;
+                                       }
+                               }
+                       }
+               }
+               // System.err.println("adding: " + munger + " to " + this);
+               // we are adding the parameterized form of the ITD to the list of
+               // mungers. Within it, the munger knows the original declared
+               // signature for the ITD so it can be retrieved.
+               interTypeMungers.add(munger);
+       }
+
+       private boolean compareToExistingMembers(ConcreteTypeMunger munger, List existingMembersList) {
+               return compareToExistingMembers(munger, existingMembersList.iterator());
+       }
+
+       // ??? returning too soon
+       private boolean compareToExistingMembers(ConcreteTypeMunger munger, Iterator existingMembers) {
+               ResolvedMember sig = munger.getSignature();
+
+               // ResolvedType declaringAspectType = munger.getAspectType();
+               // if (declaringAspectType.isRawType()) declaringAspectType =
+               // declaringAspectType.getGenericType();
+               // if (declaringAspectType.isGenericType()) {
+               //
+               // ResolvedType genericOnType =
+               // getWorld().resolve(sig.getDeclaringType()).getGenericType();
+               // ConcreteTypeMunger ctm =
+               // munger.parameterizedFor(discoverActualOccurrenceOfTypeInHierarchy
+               // (genericOnType));
+               // sig = ctm.getSignature(); // possible sig change when type
+               // }
+               // if (munger.getMunger().hasTypeVariableAliases()) {
+               // ResolvedType genericOnType =
+               // getWorld().resolve(sig.getDeclaringType()).getGenericType();
+               // ConcreteTypeMunger ctm =
+               // munger.parameterizedFor(discoverActualOccurrenceOfTypeInHierarchy(
+               // genericOnType));
+               // sig = ctm.getSignature(); // possible sig change when type parameters
+               // filled in
+               // }
+               while (existingMembers.hasNext()) {
+
+                       ResolvedMember existingMember = (ResolvedMember) existingMembers.next();
+                       // don't worry about clashing with bridge methods
+                       if (existingMember.isBridgeMethod())
+                               continue;
+                       // System.err.println("Comparing munger: "+sig+" with member "+
+                       // existingMember);
+                       if (conflictingSignature(existingMember, munger.getSignature())) {
+                               // System.err.println("conflict: existingMember=" +
+                               // existingMember + "   typeMunger=" + munger);
+                               // System.err.println(munger.getSourceLocation() + ", " +
+                               // munger.getSignature() + ", " +
+                               // munger.getSignature().getSourceLocation());
+
+                               if (isVisible(existingMember.getModifiers(), this, munger.getAspectType())) {
+                                       int c = compareMemberPrecedence(sig, existingMember);
+                                       // System.err.println("   c: " + c);
+                                       if (c < 0) {
+                                               // existingMember dominates munger
+                                               checkLegalOverride(munger.getSignature(), existingMember);
+                                               return false;
+                                       } else if (c > 0) {
+                                               // munger dominates existingMember
+                                               checkLegalOverride(existingMember, munger.getSignature());
+                                               // interTypeMungers.add(munger);
+                                               // ??? might need list of these overridden abstracts
+                                               continue;
+                                       } else {
+                                               // bridge methods can differ solely in return type.
+                                               // FIXME this whole method seems very hokey - unaware of
+                                               // covariance/varargs/bridging - it
+                                               // could do with a rewrite !
+                                               boolean sameReturnTypes = (existingMember.getReturnType().equals(sig.getReturnType()));
+                                               if (sameReturnTypes) {
+                                                       // pr206732 - if the existingMember is due to a
+                                                       // previous application of this same ITD (which can
+                                                       // happen if this is a binary type being brought in
+                                                       // from the aspectpath). The 'better' fix is
+                                                       // to recognize it is from the aspectpath at a
+                                                       // higher level and dont do this, but that is rather
+                                                       // more work.
+                                                       boolean isDuplicateOfPreviousITD = false;
+                                                       ResolvedType declaringRt = existingMember.getDeclaringType().resolve(world);
+                                                       WeaverStateInfo wsi = declaringRt.getWeaverState();
+                                                       if (wsi != null) {
+                                                               List mungersAffectingThisType = wsi.getTypeMungers(declaringRt);
+                                                               if (mungersAffectingThisType != null) {
+                                                                       for (Iterator iterator = mungersAffectingThisType.iterator(); iterator.hasNext()
+                                                                                       && !isDuplicateOfPreviousITD;) {
+                                                                               ConcreteTypeMunger ctMunger = (ConcreteTypeMunger) iterator.next();
+                                                                               // relatively crude check - is the ITD
+                                                                               // for the same as the existingmember
+                                                                               // and does it come
+                                                                               // from the same aspect
+                                                                               if (ctMunger.getSignature().equals(existingMember)
+                                                                                               && ctMunger.aspectType.equals(munger.getAspectType())) {
+                                                                                       isDuplicateOfPreviousITD = true;
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                                       if (!isDuplicateOfPreviousITD) {
+                                                               getWorld().getMessageHandler().handleMessage(
+                                                                               MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_MEMBER_CONFLICT, munger
+                                                                                               .getAspectType().getName(), existingMember), munger.getSourceLocation()));
+                                                       }
+                                               }
+                                       }
+                               } else if (isDuplicateMemberWithinTargetType(existingMember, this, sig)) {
+                                       getWorld().getMessageHandler().handleMessage(
+                                                       MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_MEMBER_CONFLICT, munger.getAspectType()
+                                                                       .getName(), existingMember), munger.getSourceLocation()));
+
+                               }
+                               // return;
+                       }
+               }
+               return true;
+       }
+
+       // we know that the member signature matches, but that the member in the
+       // target type is not visible to the aspect.
+       // this may still be disallowed if it would result in two members within the
+       // same declaring type with the same
+       // signature AND more than one of them is concrete AND they are both visible
+       // within the target type.
+       private boolean isDuplicateMemberWithinTargetType(ResolvedMember existingMember, ResolvedType targetType,
+                       ResolvedMember itdMember) {
+               if ((existingMember.isAbstract() || itdMember.isAbstract()))
+                       return false;
+               UnresolvedType declaringType = existingMember.getDeclaringType();
+               if (!targetType.equals(declaringType))
+                       return false;
+               // now have to test that itdMember is visible from targetType
+               if (itdMember.isPrivate())
+                       return false;
+               if (itdMember.isPublic())
+                       return true;
+               // must be in same package to be visible then...
+               if (!targetType.getPackageName().equals(itdMember.getDeclaringType().getPackageName()))
+                       return false;
+
+               // trying to put two members with the same signature into the exact same
+               // type..., and both visible in that type.
+               return true;
+       }
+
+       /**
+        * @return true if the override is legal note: calling showMessage with two locations issues TWO messages, not ONE message with
+        *         an additional source location.
+        */
+       public boolean checkLegalOverride(ResolvedMember parent, ResolvedMember child) {
+               // System.err.println("check: " + child.getDeclaringType() +
+               // " overrides " + parent.getDeclaringType());
+               if (Modifier.isFinal(parent.getModifiers())) {
+                       world.showMessage(Message.ERROR, WeaverMessages.format(WeaverMessages.CANT_OVERRIDE_FINAL_MEMBER, parent), child
+                                       .getSourceLocation(), null);
+                       return false;
+               }
+
+               boolean incompatibleReturnTypes = false;
+               // In 1.5 mode, allow for covariance on return type
+               if (world.isInJava5Mode() && parent.getKind() == Member.METHOD) {
+
+                       // Look at the generic types when doing this comparison
+                       ResolvedType rtParentReturnType = parent.resolve(world).getGenericReturnType().resolve(world);
+                       ResolvedType rtChildReturnType = child.resolve(world).getGenericReturnType().resolve(world);
+                       incompatibleReturnTypes = !rtParentReturnType.isAssignableFrom(rtChildReturnType);
+                       // For debug, uncomment this bit and we'll repeat the check - stick
+                       // a breakpoint on the call
+                       // if (incompatibleReturnTypes) {
+                       // incompatibleReturnTypes =
+                       // !rtParentReturnType.isAssignableFrom(rtChildReturnType);
+                       // }
+               } else {
+                       incompatibleReturnTypes = !parent.getReturnType().equals(child.getReturnType());
+               }
+
+               if (incompatibleReturnTypes) {
+                       world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.ITD_RETURN_TYPE_MISMATCH, parent, child), child
+                                       .getSourceLocation(), parent.getSourceLocation());
+                       return false;
+               }
+               if (parent.getKind() == Member.POINTCUT) {
+                       UnresolvedType[] pTypes = parent.getParameterTypes();
+                       UnresolvedType[] cTypes = child.getParameterTypes();
+                       if (!Arrays.equals(pTypes, cTypes)) {
+                               world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.ITD_PARAM_TYPE_MISMATCH, parent, child),
+                                               child.getSourceLocation(), parent.getSourceLocation());
+                               return false;
+                       }
+               }
+               // System.err.println("check: " + child.getModifiers() +
+               // " more visible " + parent.getModifiers());
+               if (isMoreVisible(parent.getModifiers(), child.getModifiers())) {
+                       world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.ITD_VISIBILITY_REDUCTION, parent, child), child
+                                       .getSourceLocation(), parent.getSourceLocation());
+                       return false;
+               }
+
+               // check declared exceptions
+               ResolvedType[] childExceptions = world.resolve(child.getExceptions());
+               ResolvedType[] parentExceptions = world.resolve(parent.getExceptions());
+               ResolvedType runtimeException = world.resolve("java.lang.RuntimeException");
+               ResolvedType error = world.resolve("java.lang.Error");
+
+               outer: for (int i = 0, leni = childExceptions.length; i < leni; i++) {
+                       // System.err.println("checking: " + childExceptions[i]);
+                       if (runtimeException.isAssignableFrom(childExceptions[i]))
+                               continue;
+                       if (error.isAssignableFrom(childExceptions[i]))
+                               continue;
+
+                       for (int j = 0, lenj = parentExceptions.length; j < lenj; j++) {
+                               if (parentExceptions[j].isAssignableFrom(childExceptions[i]))
+                                       continue outer;
+                       }
+
+                       // this message is now better handled my MethodVerifier in JDT core.
+                       // world.showMessage(IMessage.ERROR,
+                       // WeaverMessages.format(WeaverMessages.ITD_DOESNT_THROW,
+                       // childExceptions[i].getName()),
+                       // child.getSourceLocation(), null);
+
+                       return false;
+               }
+               if (parent.isStatic() && !child.isStatic()) {
+                       world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.ITD_OVERRIDDEN_STATIC, child, parent), child
+                                       .getSourceLocation(), null);
+                       return false;
+               } else if (child.isStatic() && !parent.isStatic()) {
+                       world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.ITD_OVERIDDING_STATIC, child, parent), child
+                                       .getSourceLocation(), null);
+                       return false;
+               }
+               return true;
+
+       }
+
+       private int compareMemberPrecedence(ResolvedMember m1, ResolvedMember m2) {
+               // if (!m1.getReturnType().equals(m2.getReturnType())) return 0;
+
+               // need to allow for the special case of 'clone' - which is like
+               // abstract but is
+               // not marked abstract. The code below this next line seems to make
+               // assumptions
+               // about what will have gotten through the compiler based on the normal
+               // java rules. clone goes against these...
+               if (m2.isProtected() && m2.getName().charAt(0) == 'c') {
+                       UnresolvedType declaring = m2.getDeclaringType();
+                       if (declaring != null) {
+                               if (declaring.getName().equals("java.lang.Object") && m2.getName().equals("clone"))
+                                       return +1;
+                       }
+               }
+
+               if (Modifier.isAbstract(m1.getModifiers()))
+                       return -1;
+               if (Modifier.isAbstract(m2.getModifiers()))
+                       return +1;
+
+               if (m1.getDeclaringType().equals(m2.getDeclaringType()))
+                       return 0;
+
+               ResolvedType t1 = m1.getDeclaringType().resolve(world);
+               ResolvedType t2 = m2.getDeclaringType().resolve(world);
+               if (t1.isAssignableFrom(t2)) {
+                       return -1;
+               }
+               if (t2.isAssignableFrom(t1)) {
+                       return +1;
+               }
+               return 0;
+       }
+
+       public static boolean isMoreVisible(int m1, int m2) {
+               if (Modifier.isPrivate(m1))
+                       return false;
+               if (isPackage(m1))
+                       return Modifier.isPrivate(m2);
+               if (Modifier.isProtected(m1))
+                       return /* private package */(Modifier.isPrivate(m2) || isPackage(m2));
+               if (Modifier.isPublic(m1))
+                       return /* private package protected */!Modifier.isPublic(m2);
+               throw new RuntimeException("bad modifier: " + m1);
+       }
+
+       private static boolean isPackage(int i) {
+               return (0 == (i & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED)));
+       }
+
+       private void interTypeConflictError(ConcreteTypeMunger m1, ConcreteTypeMunger m2) {
+               // XXX this works only if we ignore separate compilation issues
+               // XXX dual errors possible if (this instanceof BcelObjectType) return;
+
+               // System.err.println("conflict at " + m2.getSourceLocation());
+               getWorld().showMessage(
+                               IMessage.ERROR,
+                               WeaverMessages.format(WeaverMessages.ITD_CONFLICT, m1.getAspectType().getName(), m2.getSignature(), m2
+                                               .getAspectType().getName()), m2.getSourceLocation(), getSourceLocation());
+       }
+
+       public ResolvedMember lookupSyntheticMember(Member member) {
+               // ??? horribly inefficient
+               // for (Iterator i =
+               // System.err.println("lookup " + member + " in " + interTypeMungers);
+               for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
+                       ConcreteTypeMunger m = (ConcreteTypeMunger) i.next();
+                       ResolvedMember ret = m.getMatchingSyntheticMember(member);
+                       if (ret != null) {
+                               // System.err.println("   found: " + ret);
+                               return ret;
+                       }
+               }
+
+               // Handling members for the new array join point
+               if (world.isJoinpointArrayConstructionEnabled() && this.isArray()) {
+                       if (member.getKind() == Member.CONSTRUCTOR) {
+                               ResolvedMemberImpl ret = new ResolvedMemberImpl(Member.CONSTRUCTOR, this, Modifier.PUBLIC, ResolvedType.VOID,
+                                               "<init>", world.resolve(member.getParameterTypes()));
+                               return ret;
+                       }
+               }
+
+               // if (this.getSuperclass() != ResolvedType.OBJECT &&
+               // this.getSuperclass() != null) {
+               // return getSuperclass().lookupSyntheticMember(member);
+               // }
+
+               return null;
+       }
+
+       public void clearInterTypeMungers() {
+               if (isRawType())
+                       getGenericType().clearInterTypeMungers();
+               interTypeMungers = new ArrayList();
+       }
+
+       public boolean isTopmostImplementor(ResolvedType interfaceType) {
+               if (isInterface())
+                       return false;
+               if (!interfaceType.isAssignableFrom(this, true))
+                       return false;
+               // check that I'm truly the topmost implementor
+               if (this.getSuperclass().isMissing())
+                       return true; // we don't know anything about supertype, and it can't
+               // be exposed to weaver
+               if (interfaceType.isAssignableFrom(this.getSuperclass(), true)) {
+                       return false;
+               }
+               return true;
+       }
+
+       public ResolvedType getTopmostImplementor(ResolvedType interfaceType) {
+               if (isInterface())
+                       return null;
+               if (!interfaceType.isAssignableFrom(this))
+                       return null;
+               // Check if my super class is an implementor?
+               ResolvedType higherType = this.getSuperclass().getTopmostImplementor(interfaceType);
+               if (higherType != null)
+                       return higherType;
+               return this;
+       }
+
+       public List getExposedPointcuts() {
+               List ret = new ArrayList();
+               if (getSuperclass() != null)
+                       ret.addAll(getSuperclass().getExposedPointcuts());
+
+               for (Iterator i = Arrays.asList(getDeclaredInterfaces()).iterator(); i.hasNext();) {
+                       ResolvedType t = (ResolvedType) i.next();
+                       addPointcutsResolvingConflicts(ret, Arrays.asList(t.getDeclaredPointcuts()), false);
+               }
+               addPointcutsResolvingConflicts(ret, Arrays.asList(getDeclaredPointcuts()), true);
+               for (Iterator i = ret.iterator(); i.hasNext();) {
+                       ResolvedPointcutDefinition inherited = (ResolvedPointcutDefinition) i.next();
+                       // System.err.println("looking at: " + inherited + " in " + this);
+                       // System.err.println("            " + inherited.isAbstract() +
+                       // " in " + this.isAbstract());
+                       if (inherited.isAbstract()) {
+                               if (!this.isAbstract()) {
+                                       getWorld().showMessage(IMessage.ERROR,
+                                                       WeaverMessages.format(WeaverMessages.POINCUT_NOT_CONCRETE, inherited, this.getName()),
+                                                       inherited.getSourceLocation(), this.getSourceLocation());
+                               }
+                       }
+               }
+
+               return ret;
+       }
+
+       private void addPointcutsResolvingConflicts(List acc, List added, boolean isOverriding) {
+               for (Iterator i = added.iterator(); i.hasNext();) {
+                       ResolvedPointcutDefinition toAdd = (ResolvedPointcutDefinition) i.next();
+                       // System.err.println("adding: " + toAdd);
+                       for (Iterator j = acc.iterator(); j.hasNext();) {
+                               ResolvedPointcutDefinition existing = (ResolvedPointcutDefinition) j.next();
+                               if (existing == toAdd)
+                                       continue;
+                               if (!isVisible(existing.getModifiers(), existing.getDeclaringType().resolve(getWorld()), this)) {
+                                       // if they intended to override it but it is not visible,
+                                       // give them a nicer message
+                                       if (existing.isAbstract() && conflictingSignature(existing, toAdd)) {
+                                               getWorld().showMessage(
+                                                               IMessage.ERROR,
+                                                               WeaverMessages.format(WeaverMessages.POINTCUT_NOT_VISIBLE, existing.getDeclaringType().getName()
+                                                                               + "." + existing.getName() + "()", this.getName()), toAdd.getSourceLocation(), null);
+                                               j.remove();
+                                       }
+                                       continue;
+                               }
+                               if (conflictingSignature(existing, toAdd)) {
+                                       if (isOverriding) {
+                                               checkLegalOverride(existing, toAdd);
+                                               j.remove();
+                                       } else {
+                                               getWorld().showMessage(
+                                                               IMessage.ERROR,
+                                                               WeaverMessages.format(WeaverMessages.CONFLICTING_INHERITED_POINTCUTS, this.getName()
+                                                                               + toAdd.getSignature()), existing.getSourceLocation(), toAdd.getSourceLocation());
+                                               j.remove();
+                                       }
+                               }
+                       }
+                       acc.add(toAdd);
+               }
+       }
+
+       public ISourceLocation getSourceLocation() {
+               return null;
+       }
+
+       public boolean isExposedToWeaver() {
+               return false;
+       }
+
+       public WeaverStateInfo getWeaverState() {
+               return null;
+       }
+
+       /**
+        * Overridden by ReferenceType to return a sensible answer for parameterized and raw types.
+        * 
+        * @return
+        */
+       public ResolvedType getGenericType() {
+               if (!(isParameterizedType() || isRawType()))
+                       throw new BCException("The type " + getBaseName() + " is not parameterized or raw - it has no generic type");
+               return null;
+       }
+
+       public ResolvedType parameterizedWith(UnresolvedType[] typeParameters) {
+               if (!(isGenericType() || isParameterizedType()))
+                       return this;
+               return TypeFactory.createParameterizedType(this.getGenericType(), typeParameters, getWorld());
+       }
+
+       /**
+        * Iff I am a parameterized type, and any of my parameters are type variable references, return a version with those type
+        * parameters replaced in accordance with the passed bindings.
+        */
+       public UnresolvedType parameterize(Map typeBindings) {
+               if (!isParameterizedType())
+                       return this;// throw new IllegalStateException(
+               // "Can't parameterize a type that is not a parameterized type"
+               // );
+               boolean workToDo = false;
+               for (int i = 0; i < typeParameters.length; i++) {
+                       if (typeParameters[i].isTypeVariableReference() || (typeParameters[i] instanceof BoundedReferenceType)) {
+                               workToDo = true;
+                       }
+               }
+               if (!workToDo) {
+                       return this;
+               } else {
+                       UnresolvedType[] newTypeParams = new UnresolvedType[typeParameters.length];
+                       for (int i = 0; i < newTypeParams.length; i++) {
+                               newTypeParams[i] = typeParameters[i];
+                               if (newTypeParams[i].isTypeVariableReference()) {
+                                       TypeVariableReferenceType tvrt = (TypeVariableReferenceType) newTypeParams[i];
+                                       UnresolvedType binding = (UnresolvedType) typeBindings.get(tvrt.getTypeVariable().getName());
+                                       if (binding != null)
+                                               newTypeParams[i] = binding;
+                               } else if (newTypeParams[i] instanceof BoundedReferenceType) {
+                                       BoundedReferenceType brType = (BoundedReferenceType) newTypeParams[i];
+                                       newTypeParams[i] = brType.parameterize(typeBindings);
+                                       // brType.parameterize(typeBindings)
+                               }
+                       }
+                       return TypeFactory.createParameterizedType(getGenericType(), newTypeParams, getWorld());
+               }
+       }
+
+       // public boolean hasParameterizedSuperType() {
+       // getParameterizedSuperTypes();
+       // return parameterizedSuperTypes.length > 0;
+       // }
+
+       // public boolean hasGenericSuperType() {
+       // ResolvedType[] superTypes = getDeclaredInterfaces();
+       // for (int i = 0; i < superTypes.length; i++) {
+       // if (superTypes[i].isGenericType())
+       // return true;
+       // }
+       // return false;
+       // }
+
+       // private ResolvedType[] parameterizedSuperTypes = null;
+
+       /**
+        * Similar to the above method, but accumulates the super types
+        * 
+        * @return
+        */
+       // public ResolvedType[] getParameterizedSuperTypes() {
+       // if (parameterizedSuperTypes != null)
+       // return parameterizedSuperTypes;
+       // List accumulatedTypes = new ArrayList();
+       // accumulateParameterizedSuperTypes(this, accumulatedTypes);
+       // ResolvedType[] ret = new ResolvedType[accumulatedTypes.size()];
+       // parameterizedSuperTypes = (ResolvedType[]) accumulatedTypes.toArray(ret);
+       // return parameterizedSuperTypes;
+       // }
+       // private void accumulateParameterizedSuperTypes(ResolvedType forType, List
+       // parameterizedTypeList) {
+       // if (forType.isParameterizedType()) {
+       // parameterizedTypeList.add(forType);
+       // }
+       // if (forType.getSuperclass() != null) {
+       // accumulateParameterizedSuperTypes(forType.getSuperclass(),
+       // parameterizedTypeList);
+       // }
+       // ResolvedType[] interfaces = forType.getDeclaredInterfaces();
+       // for (int i = 0; i < interfaces.length; i++) {
+       // accumulateParameterizedSuperTypes(interfaces[i], parameterizedTypeList);
+       // }
+       // }
+       /**
+        * @return true if assignable to java.lang.Exception
+        */
+       public boolean isException() {
+               return (world.getCoreType(UnresolvedType.JAVA_LANG_EXCEPTION).isAssignableFrom(this));
+       }
+
+       /**
+        * @return true if it is an exception and it is a checked one, false otherwise.
+        */
+       public boolean isCheckedException() {
+               if (!isException())
+                       return false;
+               if (world.getCoreType(UnresolvedType.RUNTIME_EXCEPTION).isAssignableFrom(this))
+                       return false;
+               return true;
+       }
+
+       /**
+        * Determines if variables of this type could be assigned values of another with lots of help. java.lang.Object is convertable
+        * from all types. A primitive type is convertable from X iff it's assignable from X. A reference type is convertable from X iff
+        * it's coerceable from X. In other words, X isConvertableFrom Y iff the compiler thinks that _some_ value of Y could be
+        * assignable to a variable of type X without loss of precision.
+        * 
+        * @param other the other type
+        * @param world the {@link World} in which the possible assignment should be checked.
+        * @return true iff variables of this type could be assigned values of other with possible conversion
+        */
+       public final boolean isConvertableFrom(ResolvedType other) {
+
+               // // version from TypeX
+               // if (this.equals(OBJECT)) return true;
+               // if (this.isPrimitiveType() || other.isPrimitiveType()) return
+               // this.isAssignableFrom(other);
+               // return this.isCoerceableFrom(other);
+               //       
+
+               // version from ResolvedTypeX
+               if (this.equals(OBJECT))
+                       return true;
+               if (world.isInJava5Mode()) {
+                       if (this.isPrimitiveType() ^ other.isPrimitiveType()) { // If one is
+                               // primitive
+                               // and the
+                               // other
+                               // isnt
+                               if (validBoxing.contains(this.getSignature() + other.getSignature()))
+                                       return true;
+                       }
+               }
+               if (this.isPrimitiveType() || other.isPrimitiveType())
+                       return this.isAssignableFrom(other);
+               return this.isCoerceableFrom(other);
+       }
+
+       /**
+        * Determines if the variables of this type could be assigned values of another type without casting. This still allows for
+        * assignment conversion as per JLS 2ed 5.2. For object types, this means supertypeOrEqual(THIS, OTHER).
+        * 
+        * @param other the other type
+        * @param world the {@link World} in which the possible assignment should be checked.
+        * @return true iff variables of this type could be assigned values of other without casting
+        * @throws NullPointerException if other is null
+        */
+       public abstract boolean isAssignableFrom(ResolvedType other);
+
+       public abstract boolean isAssignableFrom(ResolvedType other, boolean allowMissing);
+
+       /**
+        * Determines if values of another type could possibly be cast to this type. The rules followed are from JLS 2ed 5.5,
+        * "Casting Conversion".
+        * <p/>
+        * <p>
+        * This method should be commutative, i.e., for all UnresolvedType a, b and all World w:
+        * <p/>
+        * <blockquote>
+        * 
+        * <pre>
+        * a.isCoerceableFrom(b, w) == b.isCoerceableFrom(a, w)
+        * </pre>
+        * 
+        * </blockquote>
+        * 
+        * @param other the other type
+        * @param world the {@link World} in which the possible coersion should be checked.
+        * @return true iff values of other could possibly be cast to this type.
+        * @throws NullPointerException if other is null.
+        */
+       public abstract boolean isCoerceableFrom(ResolvedType other);
+
+       public boolean needsNoConversionFrom(ResolvedType o) {
+               return isAssignableFrom(o);
+       }
+
+       public String getSignatureForAttribute() {
+               return signature; // Assume if this is being called that it is for a
+               // simple type (eg. void, int, etc)
+       }
+
+       private FuzzyBoolean parameterizedWithTypeVariable = FuzzyBoolean.MAYBE;
+
+       /**
+        * return true if the parameterization of this type includes a member type variable. Member type variables occur in generic
+        * methods/ctors.
+        */
+       public boolean isParameterizedWithTypeVariable() {
+               // MAYBE means we haven't worked it out yet...
+               if (parameterizedWithTypeVariable == FuzzyBoolean.MAYBE) {
+
+                       // if there are no type parameters then we cant be...
+                       if (typeParameters == null || typeParameters.length == 0) {
+                               parameterizedWithTypeVariable = FuzzyBoolean.NO;
+                               return false;
+                       }
+
+                       for (int i = 0; i < typeParameters.length; i++) {
+                               ResolvedType aType = (ResolvedType) typeParameters[i];
+                               if (aType.isTypeVariableReference()
+                               // Changed according to the problems covered in bug 222648
+                               // Don't care what kind of type variable - the fact that there
+                               // is one
+                               // at all means we can't risk caching it against we get confused
+                               // later
+                               // by another variation of the parameterization that just
+                               // happens to
+                               // use the same type variable name
+
+                               // assume the worst - if its definetly not a type declared one,
+                               // it could be anything
+                               // && ((TypeVariableReference)aType).getTypeVariable().
+                               // getDeclaringElementKind()!=TypeVariable.TYPE
+                               ) {
+                                       parameterizedWithTypeVariable = FuzzyBoolean.YES;
+                                       return true;
+                               }
+                               if (aType.isParameterizedType()) {
+                                       boolean b = aType.isParameterizedWithTypeVariable();
+                                       if (b) {
+                                               parameterizedWithTypeVariable = FuzzyBoolean.YES;
+                                               return true;
+                                       }
+                               }
+                               if (aType.isGenericWildcard()) {
+                                       BoundedReferenceType boundedRT = (BoundedReferenceType) aType;
+                                       if (boundedRT.isExtends()) {
+                                               boolean b = false;
+                                               UnresolvedType upperBound = boundedRT.getUpperBound();
+                                               if (upperBound.isParameterizedType()) {
+                                                       b = ((ResolvedType) upperBound).isParameterizedWithTypeVariable();
+                                               } else if (upperBound.isTypeVariableReference()
+                                                               && ((TypeVariableReference) upperBound).getTypeVariable().getDeclaringElementKind() == TypeVariable.METHOD) {
+                                                       b = true;
+                                               }
+                                               if (b) {
+                                                       parameterizedWithTypeVariable = FuzzyBoolean.YES;
+                                                       return true;
+                                               }
+                                               // FIXME asc need to check additional interface bounds
+                                       }
+                                       if (boundedRT.isSuper()) {
+                                               boolean b = false;
+                                               UnresolvedType lowerBound = boundedRT.getLowerBound();
+                                               if (lowerBound.isParameterizedType()) {
+                                                       b = ((ResolvedType) lowerBound).isParameterizedWithTypeVariable();
+                                               } else if (lowerBound.isTypeVariableReference()
+                                                               && ((TypeVariableReference) lowerBound).getTypeVariable().getDeclaringElementKind() == TypeVariable.METHOD) {
+                                                       b = true;
+                                               }
+                                               if (b) {
+                                                       parameterizedWithTypeVariable = FuzzyBoolean.YES;
+                                                       return true;
+                                               }
+                                       }
+                               }
+                       }
+                       parameterizedWithTypeVariable = FuzzyBoolean.NO;
+               }
+               return parameterizedWithTypeVariable.alwaysTrue();
+       }
+
+       protected boolean ajMembersNeedParameterization() {
+               if (isParameterizedType())
+                       return true;
+               if (getSuperclass() != null)
+                       return getSuperclass().ajMembersNeedParameterization();
+               return false;
+       }
+
+       protected Map getAjMemberParameterizationMap() {
+               Map myMap = getMemberParameterizationMap();
+               if (myMap.isEmpty()) {
+                       // might extend a parameterized aspect that we also need to
+                       // consider...
+                       if (getSuperclass() != null)
+                               return getSuperclass().getAjMemberParameterizationMap();
+               }
+               return myMap;
+       }
+
+       public void setBinaryPath(String binaryPath) {
+               this.binaryPath = binaryPath;
+       }
+
+       /**
+        * Returns the path to the jar or class file from which this binary aspect came or null if not a binary aspect
+        */
+       public String getBinaryPath() {
+               return binaryPath;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedTypeMunger.java
new file mode 100644 (file)
index 0000000..1a76644
--- /dev/null
@@ -0,0 +1,446 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation
+ *     Alexandre Vasseur    @AspectJ ITDs
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.SourceLocation;
+import org.aspectj.util.TypeSafeEnum;
+
+/**
+ * This is an abstraction over method/field introduction. It might not have the chops to handle other inter-type declarations. This
+ * is the thing that is used on the eclipse side and serialized into a ConcreteTypeMunger.
+ */
+public abstract class ResolvedTypeMunger {
+       protected Kind kind;
+       protected ResolvedMember signature;
+
+       /**
+        * The declared signature is filled in when a type munger is parameterized for application to a particular type. It represents
+        * the signature originally declared in the source file.
+        */
+       protected ResolvedMember declaredSignature;
+
+       // This list records the occurences (in order) of any names specified in the <>
+       // for a target type for the ITD. So for example, for List<C,B,A> this list
+       // will be C,B,A - the list is used later to map other occurrences of C,B,A
+       // across the intertype declaration to the right type variables in the generic
+       // type upon which the itd is being made.
+       // might need serializing the class file for binary weaving.
+       protected List /* String */typeVariableAliases;
+
+       private Set /* resolvedMembers */superMethodsCalled = Collections.EMPTY_SET;
+
+       private ISourceLocation location; // Lost during serialize/deserialize !
+
+       public ResolvedTypeMunger(Kind kind, ResolvedMember signature) {
+               this.kind = kind;
+               this.signature = signature;
+               UnresolvedType declaringType = signature != null ? signature.getDeclaringType() : null;
+               if (declaringType != null) {
+                       if (declaringType.isRawType())
+                               throw new IllegalStateException("Use generic type, not raw type");
+                       if (declaringType.isParameterizedType())
+                               throw new IllegalStateException("Use generic type, not parameterized type");
+               }
+               // boolean aChangeOccurred = false;
+               //              
+               // UnresolvedType rt = signature.getReturnType();
+               // if (rt.isParameterizedType() || rt.isGenericType()) {rt = rt.getRawType();aChangeOccurred=true;}
+               // UnresolvedType[] pt = signature.getParameterTypes();
+               // for (int i = 0; i < pt.length; i++) {
+               // if (pt[i].isParameterizedType() || pt[i].isGenericType()) { pt[i] = pt[i].getRawType();aChangeOccurred=true;}
+               // }
+               // if (aChangeOccurred) {
+               // this.signature = new
+               // ResolvedMemberImpl(signature.getKind(),signature.getDeclaringType(),signature.getModifiers(),rt,signature
+               // .getName(),pt,signature.getExceptions());
+               // }
+       }
+
+       public void setSourceLocation(ISourceLocation isl) {
+               location = isl;
+       }
+
+       public ISourceLocation getSourceLocation() {
+               return location;
+       }
+
+       // ----
+
+       // fromType is guaranteed to be a non-abstract aspect
+       // public ConcreteTypeMunger concretize(World world, ResolvedType aspectType) {
+       //      
+       // ConcreteTypeMunger munger = world.concreteTypeMunger(this, aspectType);
+       // return munger;
+       // }
+
+       public boolean matches(ResolvedType matchType, ResolvedType aspectType) {
+               ResolvedType onType = matchType.getWorld().resolve(signature.getDeclaringType());
+               if (onType.isRawType())
+                       onType = onType.getGenericType();
+               // System.err.println("matching: " + this + " to " + matchType + " onType = " + onType);
+               if (matchType.equals(onType)) {
+                       if (!onType.isExposedToWeaver()) {
+                               // if the onType is an interface, and it already has the member we are about
+                               // to munge, then this is ok...
+                               boolean ok = (onType.isInterface() && (onType.lookupMemberWithSupersAndITDs(getSignature()) != null));
+
+                               if (!ok && onType.getWeaverState() == null) {
+                                       if (matchType.getWorld().getLint().typeNotExposedToWeaver.isEnabled()) {
+                                               matchType.getWorld().getLint().typeNotExposedToWeaver.signal(matchType.getName(), signature
+                                                               .getSourceLocation());
+                                       }
+                               }
+                       }
+                       return true;
+               }
+               // System.err.println("NO MATCH DIRECT");
+
+               if (onType.isInterface()) {
+                       return matchType.isTopmostImplementor(onType);
+               } else {
+                       return false;
+               }
+       }
+
+       // ----
+
+       public String toString() {
+               return "ResolvedTypeMunger(" + getKind() + ", " + getSignature() + ")";
+               // .superMethodsCalled + ")";
+       }
+
+       // ----
+
+       public static ResolvedTypeMunger read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               Kind kind = Kind.read(s);
+               if (kind == Field) {
+                       return NewFieldTypeMunger.readField(s, context);
+               } else if (kind == Method) {
+                       return NewMethodTypeMunger.readMethod(s, context);
+               } else if (kind == Constructor) {
+                       return NewConstructorTypeMunger.readConstructor(s, context);
+               } else if (kind == MethodDelegate) {
+                       return MethodDelegateTypeMunger.readMethod(s, context);
+               } else if (kind == FieldHost) {
+                       return MethodDelegateTypeMunger.FieldHostTypeMunger.readFieldHost(s, context);
+               } else {
+                       throw new RuntimeException("unimplemented");
+               }
+       }
+
+       protected static Set readSuperMethodsCalled(VersionedDataInputStream s) throws IOException {
+
+               Set ret = new HashSet();
+               int n = s.readInt();
+               if (n < 0)
+                       throw new BCException("Problem deserializing type munger");
+               for (int i = 0; i < n; i++) {
+                       ret.add(ResolvedMemberImpl.readResolvedMember(s, null));
+               }
+               return ret;
+       }
+
+       protected void writeSuperMethodsCalled(DataOutputStream s) throws IOException {
+
+               if (superMethodsCalled == null || superMethodsCalled.size() == 0) {
+                       s.writeInt(0);
+                       return;
+               }
+
+               List ret = new ArrayList(superMethodsCalled);
+               Collections.sort(ret);
+               int n = ret.size();
+               s.writeInt(n);
+               for (Iterator i = ret.iterator(); i.hasNext();) {
+                       ResolvedMember m = (ResolvedMember) i.next();
+                       m.write(s);
+               }
+
+       }
+
+       protected static ISourceLocation readSourceLocation(VersionedDataInputStream s) throws IOException {
+               // Location persistence for type mungers was added after 1.2.1 was shipped...
+               if (s.getMajorVersion() < AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150)
+                       return null;
+               SourceLocation ret = null;
+               ObjectInputStream ois = null;
+               try {
+                       // This logic copes with the location missing from the attribute - an EOFException will
+                       // occur on the next line and we ignore it.
+                       ois = new ObjectInputStream(s);
+                       Boolean validLocation = (Boolean) ois.readObject();
+                       if (validLocation.booleanValue()) {
+                               File f = (File) ois.readObject();
+                               Integer ii = (Integer) ois.readObject();
+                               Integer offset = (Integer) ois.readObject();
+                               ret = new SourceLocation(f, ii.intValue());
+                               ret.setOffset(offset.intValue());
+                       }
+               } catch (EOFException eof) {
+                       return null; // This exception occurs if processing an 'old style' file where the
+                       // type munger attributes don't include the source location.
+               } catch (IOException ioe) {
+                       // Something went wrong, maybe this is an 'old style' file that doesnt attach locations to mungers?
+                       // (but I thought that was just an EOFException?)
+                       ioe.printStackTrace();
+                       return null;
+               } catch (ClassNotFoundException e) {
+               } finally {
+                       if (ois != null)
+                               ois.close();
+               }
+               return ret;
+       }
+
+       protected void writeSourceLocation(DataOutputStream s) throws IOException {
+               ObjectOutputStream oos = new ObjectOutputStream(s);
+               // oos.writeObject(location);
+               oos.writeObject(new Boolean(location != null));
+               if (location != null) {
+                       oos.writeObject(location.getSourceFile());
+                       oos.writeObject(new Integer(location.getLine()));
+                       oos.writeObject(new Integer(location.getOffset()));
+               }
+               oos.flush();
+               oos.close();
+       }
+
+       public abstract void write(DataOutputStream s) throws IOException;
+
+       public Kind getKind() {
+               return kind;
+       }
+
+       public static class Kind extends TypeSafeEnum {
+               /* private */Kind(String name, int key) {
+                       super(name, key);
+               }
+
+               public static Kind read(DataInputStream s) throws IOException {
+                       int key = s.readByte();
+                       switch (key) {
+                       case 1:
+                               return Field;
+                       case 2:
+                               return Method;
+                       case 5:
+                               return Constructor;
+                       case 9:
+                               return MethodDelegate;
+                       case 10:
+                               return FieldHost;
+                       }
+                       throw new BCException("bad kind: " + key);
+               }
+
+               public String toString() {
+                       // we want MethodDelegate to appear as Method in WeaveInfo messages
+                       // TODO we may want something for fieldhost ?
+                       if (MethodDelegate.getName().equals(getName())) {
+                               return Method.toString();
+                       } else {
+                               return super.toString();
+                       }
+               }
+       }
+
+       // ---- fields
+
+       public static final Kind Field = new Kind("Field", 1);
+       public static final Kind Method = new Kind("Method", 2);
+       public static final Kind Constructor = new Kind("Constructor", 5);
+
+       // not serialized, only created during concretization of aspects
+       public static final Kind PerObjectInterface = new Kind("PerObjectInterface", 3);
+       public static final Kind PrivilegedAccess = new Kind("PrivilegedAccess", 4);
+
+       public static final Kind Parent = new Kind("Parent", 6);
+       public static final Kind PerTypeWithinInterface = new Kind("PerTypeWithinInterface", 7); // PTWIMPL not serialized, used during
+                                                                                                                                                                                               // concretization of aspects
+
+       public static final Kind AnnotationOnType = new Kind("AnnotationOnType", 8); // not serialized
+
+       public static final Kind MethodDelegate = new Kind("MethodDelegate", 9);// serialized, @AJ ITDs
+       public static final Kind FieldHost = new Kind("FieldHost", 10);// serialized, @AJ ITDs
+
+       public static final String SUPER_DISPATCH_NAME = "superDispatch";
+
+       public void setSuperMethodsCalled(Set c) {
+               this.superMethodsCalled = c;
+       }
+
+       public Set getSuperMethodsCalled() {
+               return superMethodsCalled;
+       }
+
+       public ResolvedMember getSignature() {
+               return signature;
+       }
+
+       // ----
+
+       public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedType aspectType) {
+               if ((getSignature() != null) && getSignature().isPublic() && member.equals(getSignature())) {
+                       return getSignature();
+               }
+
+               return null;
+       }
+
+       public boolean changesPublicSignature() {
+               return kind == Field || kind == Method || kind == Constructor;
+       }
+
+       public boolean needsAccessToTopmostImplementor() {
+               if (kind == Field) {
+                       return true;
+               } else if (kind == Method) {
+                       return !signature.isAbstract();
+               } else {
+                       return false;
+               }
+       }
+
+       protected static List readInTypeAliases(VersionedDataInputStream s) throws IOException {
+               if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
+                       int count = s.readInt();
+                       if (count != 0) {
+                               List aliases = new ArrayList();
+                               for (int i = 0; i < count; i++) {
+                                       aliases.add(s.readUTF());
+                               }
+                               return aliases;
+                       }
+               }
+               return null;
+       }
+
+       protected void writeOutTypeAliases(DataOutputStream s) throws IOException {
+               // Write any type variable aliases
+               if (typeVariableAliases == null || typeVariableAliases.size() == 0) {
+                       s.writeInt(0);
+               } else {
+                       s.writeInt(typeVariableAliases.size());
+                       for (Iterator iter = typeVariableAliases.iterator(); iter.hasNext();) {
+                               String element = (String) iter.next();
+                               s.writeUTF(element);
+                       }
+               }
+       }
+
+       public List getTypeVariableAliases() {
+               return typeVariableAliases;
+       }
+
+       public boolean hasTypeVariableAliases() {
+               return (typeVariableAliases != null && typeVariableAliases.size() > 0);
+       }
+
+       /**
+        * return true if type variables are specified with the target type for this ITD. e.g. this would return true:
+        * "int I<A,B>.m() { return 42; }"
+        */
+       public boolean sharesTypeVariablesWithGenericType() {
+               return (typeVariableAliases != null && typeVariableAliases.size() > 0);
+       }
+
+       /**
+        * Parameterizes a resolved type munger for a particular usage of its target type (this is used when the target type is generic
+        * and the ITD shares type variables with the target) see ConcreteTypeMunger.parameterizedFor
+        */
+       public ResolvedTypeMunger parameterizedFor(ResolvedType target) {
+               throw new BCException("Dont call parameterizedFor on a type munger of this kind: " + this.getClass());
+       }
+
+       // ResolvedType genericType = target;
+       // if (target.isRawType() || target.isParameterizedType()) genericType = genericType.getGenericType();
+       // ResolvedMember parameterizedSignature = null;
+       // // If we are parameterizing it for a generic type, we just need to 'swap the letters' from the ones used
+       // // in the original ITD declaration to the ones used in the actual target type declaration.
+       // if (target.isGenericType()) {
+       // TypeVariable vars[] = target.getTypeVariables();
+       // UnresolvedTypeVariableReferenceType[] varRefs = new UnresolvedTypeVariableReferenceType[vars.length];
+       // for (int i = 0; i < vars.length; i++) {
+       // varRefs[i] = new UnresolvedTypeVariableReferenceType(vars[i]);
+       // }
+       // parameterizedSignature = getSignature().parameterizedWith(varRefs,genericType,true,typeVariableAliases);
+       // } else {
+       // // For raw and 'normal' parameterized targets (e.g. Interface, Interface<String>)
+       // parameterizedSignature =
+       // getSignature().parameterizedWith(target.getTypeParameters(),genericType,target.isParameterizedType(),typeVariableAliases);
+       // }
+       // return new NewMethodTypeMunger(parameterizedSignature,getSuperMethodsCalled(),typeVariableAliases);
+       // }
+       // /**
+       // * see ResolvedTypeMunger.parameterizedFor(ResolvedType)
+       // */
+       // public ResolvedTypeMunger parameterizedFor(ResolvedType target) {
+       // ResolvedType genericType = target;
+       // if (target.isRawType() || target.isParameterizedType()) genericType = genericType.getGenericType();
+       // ResolvedMember parameterizedSignature =
+       // getSignature().parameterizedWith(target.getTypeParameters(),genericType,target.isParameterizedType(),typeVariableAliases);
+       // return new NewFieldTypeMunger(parameterizedSignature,getSuperMethodsCalled(),typeVariableAliases);
+       // }
+
+       public void setDeclaredSignature(ResolvedMember rm) {
+               declaredSignature = rm;
+       }
+
+       public ResolvedMember getDeclaredSignature() {
+               return declaredSignature;
+       }
+
+       /**
+        * A late munger has to be done after shadow munging since which shadows are matched can affect the operation of the late
+        * munger. e.g. perobjectinterfacemunger
+        */
+       public boolean isLateMunger() {
+               return false;
+       }
+
+       /**
+        * Some type mungers are created purely to help with the implementation of shadow mungers. For example to support the cflow()
+        * pointcut we create a new cflow field in the aspect, and that is added via a BcelCflowCounterFieldAdder.
+        * 
+        * During compilation we need to compare sets of type mungers, and if some only come into existence after the 'shadowy' type
+        * things have been processed, we need to ignore them during the comparison.
+        * 
+        * Returning true from this method indicates the type munger exists to support 'shadowy' stuff - and so can be ignored in some
+        * comparison.
+        */
+       public boolean existsToSupportShadowMunging() {
+               return false;
+       }
+
+       public ResolvedTypeMunger parameterizeWith(Map m, World w) {
+               throw new BCException("Dont call parameterizeWith() on a type munger of this kind: " + this.getClass());
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Shadow.java b/org.aspectj.matcher/src/org/aspectj/weaver/Shadow.java
new file mode 100644 (file)
index 0000000..edc8fd1
--- /dev/null
@@ -0,0 +1,666 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.PartialOrder;
+import org.aspectj.util.TypeSafeEnum;
+import org.aspectj.weaver.ast.Var;
+
+/*
+ * The superclass of anything representing a the shadow of a join point.  A shadow represents
+ * some bit of code, and encompasses both entry and exit from that code.  All shadows have a kind
+ * and a signature.
+ */
+
+public abstract class Shadow {
+
+       // every Shadow has a unique id, doesn't matter if it wraps...
+       private static int nextShadowID = 100; // easier to spot than zero. // OPTIMIZE is this a bug? static?
+
+       private final Kind kind;
+       private final Member signature;
+       private Member matchingSignature;
+       private ResolvedMember resolvedSignature;
+       protected final Shadow enclosingShadow;
+       protected List mungers = Collections.EMPTY_LIST;
+
+       public int shadowId = nextShadowID++; // every time we build a shadow, it gets a new id
+
+       // ----
+       protected Shadow(Kind kind, Member signature, Shadow enclosingShadow) {
+               this.kind = kind;
+               this.signature = signature;
+               this.enclosingShadow = enclosingShadow;
+       }
+
+       // ----
+
+       public abstract World getIWorld();
+
+       public List /* ShadowMunger */getMungers() {
+               return mungers;
+       }
+
+       /**
+        * could this(*) pcd ever match
+        */
+       public final boolean hasThis() {
+               if (getKind().neverHasThis()) {
+                       return false;
+               } else if (getKind().isEnclosingKind()) {
+                       return !getSignature().isStatic();
+               } else if (enclosingShadow == null) {
+                       return false;
+               } else {
+                       return enclosingShadow.hasThis();
+               }
+       }
+
+       /**
+        * the type of the this object here
+        * 
+        * @throws IllegalStateException if there is no this here
+        */
+       public final UnresolvedType getThisType() {
+               if (!hasThis())
+                       throw new IllegalStateException("no this");
+               if (getKind().isEnclosingKind()) {
+                       return getSignature().getDeclaringType();
+               } else {
+                       return enclosingShadow.getThisType();
+               }
+       }
+
+       /**
+        * a var referencing this
+        * 
+        * @throws IllegalStateException if there is no target here
+        */
+       public abstract Var getThisVar();
+
+       /**
+        * could target(*) pcd ever match
+        */
+       public final boolean hasTarget() {
+               if (getKind().neverHasTarget()) {
+                       return false;
+               } else if (getKind().isTargetSameAsThis()) {
+                       return hasThis();
+               } else {
+                       return !getSignature().isStatic();
+               }
+       }
+
+       /**
+        * the type of the target object here
+        * 
+        * @throws IllegalStateException if there is no target here
+        */
+       public final UnresolvedType getTargetType() {
+               if (!hasTarget())
+                       throw new IllegalStateException("no target");
+               return getSignature().getDeclaringType();
+       }
+
+       /**
+        * a var referencing the target
+        * 
+        * @throws IllegalStateException if there is no target here
+        */
+       public abstract Var getTargetVar();
+
+       public UnresolvedType[] getArgTypes() {
+               if (getKind() == FieldSet)
+                       return new UnresolvedType[] { getSignature().getReturnType() };
+               return getSignature().getParameterTypes();
+       }
+
+       public boolean isShadowForArrayConstructionJoinpoint() {
+               return (getKind() == ConstructorCall && signature.getDeclaringType().isArray());
+       }
+
+       public boolean isShadowForMonitor() {
+               return (getKind() == SynchronizationLock || getKind() == SynchronizationUnlock);
+       }
+
+       // will return the right length array of ints depending on how many dimensions the array has
+       public ResolvedType[] getArgumentTypesForArrayConstructionShadow() {
+               String s = signature.getDeclaringType().getSignature();
+               int pos = s.indexOf("[");
+               int dims = 1;
+               while (pos < s.length()) {
+                       pos++;
+                       if (pos < s.length())
+                               dims += (s.charAt(pos) == '[' ? 1 : 0);
+               }
+               if (dims == 1)
+                       return new ResolvedType[] { ResolvedType.INT };
+               ResolvedType[] someInts = new ResolvedType[dims];
+               for (int i = 0; i < dims; i++)
+                       someInts[i] = ResolvedType.INT;
+               return someInts;
+       }
+
+       public UnresolvedType[] getGenericArgTypes() {
+               if (isShadowForArrayConstructionJoinpoint()) {
+                       return getArgumentTypesForArrayConstructionShadow();
+               }
+               if (isShadowForMonitor()) {
+                       return UnresolvedType.ARRAY_WITH_JUST_OBJECT;
+               }
+               if (getKind() == FieldSet)
+                       return new UnresolvedType[] { getResolvedSignature().getGenericReturnType() };
+               return getResolvedSignature().getGenericParameterTypes();
+       }
+
+       public UnresolvedType getArgType(int arg) {
+               if (getKind() == FieldSet)
+                       return getSignature().getReturnType();
+               return getSignature().getParameterTypes()[arg];
+       }
+
+       public int getArgCount() {
+               if (getKind() == FieldSet)
+                       return 1;
+               return getSignature().getParameterTypes().length;
+       }
+
+       // /**
+       // * Return name of the argument at position 'i' at this shadow. This does not make sense for all shadows - but can be useful in
+       // * the case of, for example, method-execution.
+       // *
+       // * @return null if it cannot be determined
+       // */
+       // public String getArgName(int i, World w) {
+       // String[] names = getSignature().getParameterNames(w);
+       // if (names == null || i >= names.length)
+       // return null;
+       // return names[i];
+       // }
+
+       public abstract UnresolvedType getEnclosingType();
+
+       public abstract Var getArgVar(int i);
+
+       public abstract Var getThisJoinPointVar();
+
+       public abstract Var getThisJoinPointStaticPartVar();
+
+       public abstract Var getThisEnclosingJoinPointStaticPartVar();
+
+       // annotation variables
+       public abstract Var getKindedAnnotationVar(UnresolvedType forAnnotationType);
+
+       public abstract Var getWithinAnnotationVar(UnresolvedType forAnnotationType);
+
+       public abstract Var getWithinCodeAnnotationVar(UnresolvedType forAnnotationType);
+
+       public abstract Var getThisAnnotationVar(UnresolvedType forAnnotationType);
+
+       public abstract Var getTargetAnnotationVar(UnresolvedType forAnnotationType);
+
+       public abstract Var getArgAnnotationVar(int i, UnresolvedType forAnnotationType);
+
+       public abstract Member getEnclosingCodeSignature();
+
+       /**
+        * returns the kind of shadow this is, representing what happens under this shadow
+        */
+       public Kind getKind() {
+               return kind;
+       }
+
+       /**
+        * returns the signature of the thing under this shadow
+        */
+       public Member getSignature() {
+               return signature;
+       }
+
+       /**
+        * returns the signature of the thing under this shadow, with any synthetic arguments removed
+        */
+       public Member getMatchingSignature() {
+               return matchingSignature != null ? matchingSignature : signature;
+       }
+
+       public void setMatchingSignature(Member member) {
+               this.matchingSignature = member;
+       }
+
+       /**
+        * returns the resolved signature of the thing under this shadow
+        * 
+        */
+       public ResolvedMember getResolvedSignature() {
+               if (resolvedSignature == null) {
+                       resolvedSignature = signature.resolve(getIWorld());
+               }
+               return resolvedSignature;
+       }
+
+       public UnresolvedType getReturnType() {
+               if (kind == ConstructorCall)
+                       return getSignature().getDeclaringType();
+               else if (kind == FieldSet)
+                       return ResolvedType.VOID;
+               else if (kind == SynchronizationLock || kind == SynchronizationUnlock)
+                       return ResolvedType.VOID;
+               return getResolvedSignature().getGenericReturnType();
+       }
+
+       public static String METHOD_EXECUTION = "method-execution";
+       public static String METHOD_CALL = "method-call";
+       public static String CONSTRUCTOR_EXECUTION = "constructor-execution";
+       public static String CONSTRUCTOR_CALL = "constructor-call";
+       public static String FIELD_GET = "field-get";
+       public static String FIELD_SET = "field-set";
+       public static String STATICINITIALIZATION = "staticinitialization";
+       public static String PREINITIALIZATION = "preinitialization";
+       public static String INITIALIZATION = "initialization";
+       public static String EXCEPTION_HANDLER = "exception-handler";
+       public static String SYNCHRONIZATION_LOCK = "lock";
+       public static String SYNCHRONIZATION_UNLOCK = "unlock";
+       public static String ADVICE_EXECUTION = "adviceexecution";
+
+       /**
+        * These names are the ones that will be returned by thisJoinPoint.getKind() Those need to be documented somewhere
+        */
+       public static final Kind MethodCall = new Kind(METHOD_CALL, 1, true);
+       public static final Kind ConstructorCall = new Kind(CONSTRUCTOR_CALL, 2, true);
+       public static final Kind MethodExecution = new Kind(METHOD_EXECUTION, 3, false);
+       public static final Kind ConstructorExecution = new Kind(CONSTRUCTOR_EXECUTION, 4, false);
+       public static final Kind FieldGet = new Kind(FIELD_GET, 5, true);
+       public static final Kind FieldSet = new Kind(FIELD_SET, 6, true);
+       public static final Kind StaticInitialization = new Kind(STATICINITIALIZATION, 7, false);
+       public static final Kind PreInitialization = new Kind(PREINITIALIZATION, 8, false);
+       public static final Kind AdviceExecution = new Kind(ADVICE_EXECUTION, 9, false);
+       public static final Kind Initialization = new Kind(INITIALIZATION, 10, false);
+       public static final Kind ExceptionHandler = new Kind(EXCEPTION_HANDLER, 11, true);
+       public static final Kind SynchronizationLock = new Kind(SYNCHRONIZATION_LOCK, 12, true);
+       public static final Kind SynchronizationUnlock = new Kind(SYNCHRONIZATION_UNLOCK, 13, true);
+
+       // Bits here are 1<<(Kind.getKey()) - and unfortunately keys didn't start at zero so bits here start at 2
+       public static final int MethodCallBit = 0x002;
+       public static final int ConstructorCallBit = 0x004;
+       public static final int MethodExecutionBit = 0x008;
+       public static final int ConstructorExecutionBit = 0x010;
+       public static final int FieldGetBit = 0x020;
+       public static final int FieldSetBit = 0x040;
+       public static final int StaticInitializationBit = 0x080;
+       public static final int PreInitializationBit = 0x100;
+       public static final int AdviceExecutionBit = 0x200;
+       public static final int InitializationBit = 0x400;
+       public static final int ExceptionHandlerBit = 0x800;
+       public static final int SynchronizationLockBit = 0x1000;
+       public static final int SynchronizationUnlockBit = 0x2000;
+
+       public static final int MAX_SHADOW_KIND = 13;
+       public static final Kind[] SHADOW_KINDS = new Kind[] { MethodCall, ConstructorCall, MethodExecution, ConstructorExecution,
+                       FieldGet, FieldSet, StaticInitialization, PreInitialization, AdviceExecution, Initialization, ExceptionHandler,
+                       SynchronizationLock, SynchronizationUnlock };
+
+       public static final int ALL_SHADOW_KINDS_BITS;
+       public static final int NO_SHADOW_KINDS_BITS;
+
+       static {
+               ALL_SHADOW_KINDS_BITS = 0x3ffe;
+               NO_SHADOW_KINDS_BITS = 0x0000;
+       }
+
+       /**
+        * Return count of how many bits set in the supplied parameter.
+        */
+       public static int howMany(int i) {
+               int count = 0;
+               for (int j = 0; j < SHADOW_KINDS.length; j++) {
+                       if ((i & SHADOW_KINDS[j].bit) != 0)
+                               count++;
+               }
+               return count;
+       }
+
+       /**
+        * A type-safe enum representing the kind of shadows
+        */
+       public static final class Kind extends TypeSafeEnum {
+               // private boolean argsOnStack; //XXX unused
+
+               public int bit;
+
+               public Kind(String name, int key, boolean argsOnStack) {
+                       super(name, key);
+                       bit = 1 << key;
+                       // this.argsOnStack = argsOnStack;
+               }
+
+               public String toLegalJavaIdentifier() {
+                       return getName().replace('-', '_');
+               }
+
+               public boolean argsOnStack() {
+                       return !isTargetSameAsThis();
+               }
+
+               // !!! this is false for handlers!
+               public boolean allowsExtraction() {
+                       return true;
+               }
+
+               public boolean isSet(int i) {
+                       return (i & bit) != 0;
+               }
+
+               // XXX revisit along with removal of priorities
+               public boolean hasHighPriorityExceptions() {
+                       return !isTargetSameAsThis();
+               }
+
+               private final static int hasReturnValueFlag = MethodCallBit | ConstructorCallBit | MethodExecutionBit | FieldGetBit
+                               | AdviceExecutionBit;
+
+               /**
+                * These shadow kinds have return values that can be bound in after returning(Dooberry doo) advice.
+                * 
+                * @return
+                */
+               public boolean hasReturnValue() {
+                       return (bit & hasReturnValueFlag) != 0;
+               }
+
+               private final static int isEnclosingKindFlag = MethodExecutionBit | ConstructorExecutionBit | AdviceExecutionBit
+                               | StaticInitializationBit | InitializationBit;
+
+               /**
+                * These are all the shadows that contains other shadows within them and are often directly associated with methods.
+                */
+               public boolean isEnclosingKind() {
+                       return (bit & isEnclosingKindFlag) != 0;
+               }
+
+               private final static int isTargetSameAsThisFlag = MethodExecutionBit | ConstructorExecutionBit | StaticInitializationBit
+                               | PreInitializationBit | AdviceExecutionBit | InitializationBit;
+
+               public boolean isTargetSameAsThis() {
+                       return (bit & isTargetSameAsThisFlag) != 0;
+               }
+
+               private final static int neverHasTargetFlag = ConstructorCallBit | ExceptionHandlerBit | PreInitializationBit
+                               | StaticInitializationBit | SynchronizationLockBit | SynchronizationUnlockBit;
+
+               public boolean neverHasTarget() {
+                       return (bit & neverHasTargetFlag) != 0;
+               }
+
+               private final static int neverHasThisFlag = PreInitializationBit | StaticInitializationBit;
+
+               public boolean neverHasThis() {
+                       return (bit & neverHasThisFlag) != 0;
+               }
+
+               public String getSimpleName() {
+                       int dash = getName().lastIndexOf('-');
+                       if (dash == -1)
+                               return getName();
+                       else
+                               return getName().substring(dash + 1);
+               }
+
+               public static Kind read(DataInputStream s) throws IOException {
+                       int key = s.readByte();
+                       switch (key) {
+                       case 1:
+                               return MethodCall;
+                       case 2:
+                               return ConstructorCall;
+                       case 3:
+                               return MethodExecution;
+                       case 4:
+                               return ConstructorExecution;
+                       case 5:
+                               return FieldGet;
+                       case 6:
+                               return FieldSet;
+                       case 7:
+                               return StaticInitialization;
+                       case 8:
+                               return PreInitialization;
+                       case 9:
+                               return AdviceExecution;
+                       case 10:
+                               return Initialization;
+                       case 11:
+                               return ExceptionHandler;
+                       case 12:
+                               return SynchronizationLock;
+                       case 13:
+                               return SynchronizationUnlock;
+                       }
+                       throw new BCException("unknown kind: " + key);
+               }
+       }
+
+       /**
+        * Only does the check if the munger requires it (@AJ aspects don't)
+        * 
+        * @param munger
+        * @return
+        */
+       protected boolean checkMunger(ShadowMunger munger) {
+               if (munger.mustCheckExceptions()) {
+                       for (Iterator i = munger.getThrownExceptions().iterator(); i.hasNext();) {
+                               if (!checkCanThrow(munger, (ResolvedType) i.next()))
+                                       return false;
+                       }
+               }
+               return true;
+       }
+
+       protected boolean checkCanThrow(ShadowMunger munger, ResolvedType resolvedTypeX) {
+               if (getKind() == ExceptionHandler) {
+                       // XXX much too lenient rules here, need to walk up exception handlers
+                       return true;
+               }
+
+               if (!isDeclaredException(resolvedTypeX, getSignature())) {
+                       getIWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CANT_THROW_CHECKED, resolvedTypeX, this), // from
+                                       // advice
+                                       // in
+                                       // \
+                                       // '"
+                                       // +
+                                       // munger
+                                       // .
+                                       // +
+                                       // "\'"
+                                       // ,
+                                       getSourceLocation(), munger.getSourceLocation());
+               }
+
+               return true;
+       }
+
+       private boolean isDeclaredException(ResolvedType resolvedTypeX, Member member) {
+               ResolvedType[] excs = getIWorld().resolve(member.getExceptions(getIWorld()));
+               for (int i = 0, len = excs.length; i < len; i++) {
+                       if (excs[i].isAssignableFrom(resolvedTypeX))
+                               return true;
+               }
+               return false;
+       }
+
+       public void addMunger(ShadowMunger munger) {
+               if (checkMunger(munger)) {
+                       if (mungers == Collections.EMPTY_LIST)
+                               mungers = new ArrayList();
+                       this.mungers.add(munger);
+               }
+       }
+
+       public final void implement() {
+               sortMungers();
+               if (mungers == null)
+                       return;
+               prepareForMungers();
+               implementMungers();
+       }
+
+       private void sortMungers() {
+
+               List sorted = PartialOrder.sort(mungers);
+
+               // Bunch of code to work out whether to report xlints for advice that isn't ordered at this Joinpoint
+               possiblyReportUnorderedAdvice(sorted);
+
+               if (sorted == null) {
+                       // this means that we have circular dependencies
+                       for (Iterator i = mungers.iterator(); i.hasNext();) {
+                               ShadowMunger m = (ShadowMunger) i.next();
+                               getIWorld().getMessageHandler().handleMessage(
+                                               MessageUtil.error(WeaverMessages.format(WeaverMessages.CIRCULAR_DEPENDENCY, this), m.getSourceLocation()));
+                       }
+               }
+               mungers = sorted;
+       }
+
+       // not quite optimal... but the xlint is ignore by default
+       private void possiblyReportUnorderedAdvice(List sorted) {
+               if (sorted != null && getIWorld().getLint().unorderedAdviceAtShadow.isEnabled() && mungers.size() > 1) {
+
+                       // Stores a set of strings of the form 'aspect1:aspect2' which indicates there is no
+                       // precedence specified between the two aspects at this shadow.
+                       Set clashingAspects = new HashSet();
+                       int max = mungers.size();
+
+                       // Compare every pair of advice mungers
+                       for (int i = max - 1; i >= 0; i--) {
+                               for (int j = 0; j < i; j++) {
+                                       Object a = mungers.get(i);
+                                       Object b = mungers.get(j);
+
+                                       // Make sure they are the right type
+                                       if (a instanceof Advice && b instanceof Advice) {
+                                               Advice adviceA = (Advice) a;
+                                               Advice adviceB = (Advice) b;
+                                               if (!adviceA.concreteAspect.equals(adviceB.concreteAspect)) {
+                                                       AdviceKind adviceKindA = adviceA.getKind();
+                                                       AdviceKind adviceKindB = adviceB.getKind();
+
+                                                       // make sure they are the nice ones (<6) and not any synthetic advice ones we
+                                                       // create to support other features of the language.
+                                                       if (adviceKindA.getKey() < (byte) 6 && adviceKindB.getKey() < (byte) 6
+                                                                       && adviceKindA.getPrecedence() == adviceKindB.getPrecedence()) {
+
+                                                               // Ask the world if it knows about precedence between these
+                                                               Integer order = getIWorld().getPrecedenceIfAny(adviceA.concreteAspect, adviceB.concreteAspect);
+
+                                                               if (order != null && order.equals(new Integer(0))) {
+                                                                       String key = adviceA.getDeclaringAspect() + ":" + adviceB.getDeclaringAspect();
+                                                                       String possibleExistingKey = adviceB.getDeclaringAspect() + ":" + adviceA.getDeclaringAspect();
+                                                                       if (!clashingAspects.contains(possibleExistingKey))
+                                                                               clashingAspects.add(key);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       for (Iterator iter = clashingAspects.iterator(); iter.hasNext();) {
+                               String element = (String) iter.next();
+                               String aspect1 = element.substring(0, element.indexOf(":"));
+                               String aspect2 = element.substring(element.indexOf(":") + 1);
+                               getIWorld().getLint().unorderedAdviceAtShadow.signal(new String[] { this.toString(), aspect1, aspect2 }, this
+                                               .getSourceLocation(), null);
+                       }
+               }
+       }
+
+       /**
+        * Prepare the shadow for implementation. After this is done, the shadow should be in such a position that each munger simply
+        * needs to be implemented.
+        */
+       protected void prepareForMungers() {
+               throw new RuntimeException("Generic shadows cannot be prepared");
+       }
+
+       /** Actually implement the (non-empty) mungers associated with this shadow */
+       private void implementMungers() {
+               World world = getIWorld();
+               for (Iterator iter = mungers.iterator(); iter.hasNext();) {
+                       ShadowMunger munger = (ShadowMunger) iter.next();
+                       munger.implementOn(this);
+                       world.reportMatch(munger, this);
+               }
+       }
+
+       public abstract ISourceLocation getSourceLocation();
+
+       // ---- utility
+
+       public String toString() {
+               return getKind() + "(" + getSignature() + ")"; // + getSourceLines();
+       }
+
+       public String toResolvedString(World world) {
+               StringBuffer sb = new StringBuffer();
+               sb.append(getKind());
+               sb.append("(");
+               Member m = getSignature();
+               if (m == null) {
+                       sb.append("<<missing signature>>");
+               } else {
+                       ResolvedMember rm = world.resolve(m);
+                       if (rm == null) {
+                               sb.append("<<unresolvableMember:").append(m).append(">>");
+                       } else {
+                               String genString = rm.toGenericString();
+                               if (genString == null) {
+                                       sb.append("<<unableToGetGenericStringFor:").append(rm).append(">>");
+                               } else {
+                                       sb.append(genString);
+                               }
+
+                       }
+               }
+               sb.append(")");
+               return sb.toString();
+               // was: return getKind() + "(" + world.resolve(getSignature()).toGenericString() + ")";
+       }
+
+       /**
+        * Convert a bit array for the shadow kinds into a set of them... should only be used for testing - mainline code should do bit
+        * manipulation!
+        */
+       public static Set toSet(int i) {
+               Set results = new HashSet();
+               for (int j = 0; j < Shadow.SHADOW_KINDS.length; j++) {
+                       Kind k = Shadow.SHADOW_KINDS[j];
+                       if (k.isSet(i))
+                               results.add(k);
+               }
+               return results;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ShadowMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/ShadowMunger.java
new file mode 100644 (file)
index 0000000..bc6e398
--- /dev/null
@@ -0,0 +1,191 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Map;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.SourceLocation;
+import org.aspectj.util.PartialOrder;
+import org.aspectj.weaver.patterns.PerClause;
+import org.aspectj.weaver.patterns.Pointcut;
+
+/**
+ * For every shadow munger, nothing can be done with it until it is concretized. Then...
+ * 
+ * (Then we call fast match.)
+ * 
+ * For every shadow munger, for every shadow, first match is called, then (if match returned true) the shadow munger is specialized
+ * for the shadow, which may modify state. Then implement is called.
+ */
+public abstract class ShadowMunger implements PartialOrder.PartialComparable, IHasPosition {
+
+       protected Pointcut pointcut;
+
+       // these three fields hold the source location of this munger
+       protected int start, end;
+       protected ISourceContext sourceContext;
+       private ISourceLocation sourceLocation;
+       private ISourceLocation binarySourceLocation;
+       private File binaryFile;
+       public String handle = null;
+       private ResolvedType declaringType; // the type that declared this munger.
+
+       public ShadowMunger(Pointcut pointcut, int start, int end, ISourceContext sourceContext) {
+               this.pointcut = pointcut;
+               this.start = start;
+               this.end = end;
+               this.sourceContext = sourceContext;
+       }
+
+       public abstract ShadowMunger concretize(ResolvedType fromType, World world, PerClause clause);
+
+       public abstract void specializeOn(Shadow shadow);
+
+       public abstract void implementOn(Shadow shadow);
+
+       /**
+        * All overriding methods should call super
+        */
+       public boolean match(Shadow shadow, World world) {
+               return pointcut.match(shadow).maybeTrue();
+       }
+
+       public abstract ShadowMunger parameterizeWith(ResolvedType declaringType, Map typeVariableMap);
+
+       public int fallbackCompareTo(Object other) {
+               return toString().compareTo(toString());
+       }
+
+       public int getEnd() {
+               return end;
+       }
+
+       public int getStart() {
+               return start;
+       }
+
+       public ISourceLocation getSourceLocation() {
+               if (sourceLocation == null) {
+                       if (sourceContext != null) {
+                               sourceLocation = sourceContext.makeSourceLocation(this);
+                       }
+               }
+               if (isBinary()) {
+                       if (binarySourceLocation == null) {
+                               binarySourceLocation = getBinarySourceLocation(sourceLocation);
+                       }
+                       return binarySourceLocation;
+               }
+               return sourceLocation;
+       }
+
+       // ---- fields
+
+       public static final ShadowMunger[] NONE = new ShadowMunger[0];
+
+       public Pointcut getPointcut() {
+               return pointcut;
+       }
+
+       // pointcut may be updated during rewriting...
+       public void setPointcut(Pointcut pointcut) {
+               this.pointcut = pointcut;
+       }
+
+       /**
+        * Invoked when the shadow munger of a resolved type are processed.
+        * 
+        * @param aType
+        */
+       public void setDeclaringType(ResolvedType aType) {
+               declaringType = aType;
+       }
+
+       public ResolvedType getDeclaringType() {
+               return declaringType;
+       }
+
+       /**
+        * @return a Collection of ResolvedType for all checked exceptions that might be thrown by this munger
+        */
+       public abstract Collection getThrownExceptions();
+
+       /**
+        * Does the munger has to check that its exception are accepted by the shadow ? ATAJ: It s not the case for @AJ around advice
+        * f.e. that can throw Throwable, even if the advised method does not throw any exceptions.
+        * 
+        * @return true if munger has to check that its exceptions can be throwned based on the shadow
+        */
+       public abstract boolean mustCheckExceptions();
+
+       /**
+        * Returns the binarySourceLocation for the given sourcelocation. This isn't cached because it's used when faulting in the
+        * binary nodes and is called with ISourceLocations for all advice, pointcuts and deows contained within the
+        * resolvedDeclaringAspect.
+        */
+       public ISourceLocation getBinarySourceLocation(ISourceLocation sl) {
+               if (sl == null)
+                       return null;
+               String sourceFileName = null;
+               if (getDeclaringType() instanceof ReferenceType) {
+                       String s = ((ReferenceType) getDeclaringType()).getDelegate().getSourcefilename();
+                       int i = s.lastIndexOf('/');
+                       if (i != -1) {
+                               sourceFileName = s.substring(i + 1);
+                       } else {
+                               sourceFileName = s;
+                       }
+               }
+               ISourceLocation sLoc = new SourceLocation(getBinaryFile(), sl.getLine(), sl.getEndLine(),
+                               ((sl.getColumn() == 0) ? ISourceLocation.NO_COLUMN : sl.getColumn()), sl.getContext(), sourceFileName);
+               return sLoc;
+       }
+
+       /**
+        * Returns the File with pathname to the class file, for example either C:\temp
+        * \ajcSandbox\workspace\ajcTest16957.tmp\simple.jar!pkg\BinaryAspect.class if the class file is in a jar file, or
+        * C:\temp\ajcSandbox\workspace\ajcTest16957.tmp!pkg\BinaryAspect.class if the class file is in a directory
+        */
+       private File getBinaryFile() {
+               if (binaryFile == null) {
+                       String s = getDeclaringType().getBinaryPath();
+                       File f = getDeclaringType().getSourceLocation().getSourceFile();
+                       int i = f.getPath().lastIndexOf('.');
+                       String path = f.getPath().substring(0, i) + ".class";
+                       binaryFile = new File(s + "!" + path);
+               }
+               return binaryFile;
+       }
+
+       /**
+        * Returns whether or not this shadow munger came from a binary aspect - keep a record of whether or not we've checked if we're
+        * binary otherwise we keep caluclating the same thing many times
+        */
+       public boolean isBinary() {
+               if (!checkedIsBinary) {
+                       ResolvedType rt = getDeclaringType();
+                       if (rt != null) {
+                               isBinary = ((rt.getBinaryPath() == null) ? false : true);
+                       }
+                       checkedIsBinary = true;
+               }
+               return isBinary;
+       }
+
+       private boolean isBinary;
+       private boolean checkedIsBinary;
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/SignatureUtils.java b/org.aspectj.matcher/src/org/aspectj/weaver/SignatureUtils.java
new file mode 100644 (file)
index 0000000..af1cace
--- /dev/null
@@ -0,0 +1,246 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * 
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Andy Clement - refactored out of MemberImpl
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+
+public class SignatureUtils {
+
+       public static String getSignatureString(Member m, World world) {                
+       MemberKind kind = m.getKind();
+       if (kind == Member.METHOD) {
+               return getMethodSignatureString(m,world);
+       } else if (kind == Member.CONSTRUCTOR) {
+               return getConstructorSignatureString(m,world);
+       } else if (kind == Member.FIELD) {
+               return getFieldSignatureString(m,world);
+       } else if (kind == Member.HANDLER) {
+               return getHandlerSignatureString(m,world);
+       } else if (kind == Member.STATIC_INITIALIZATION) {
+               return getStaticInitializationSignatureString(m,world);
+       } else if (kind == Member.ADVICE) {
+               return getAdviceSignatureString(m,world);
+       } else if (kind == Member.MONITORENTER || kind == Member.MONITOREXIT) {
+               return getMonitorSignatureString(m,world);
+       } else {
+               throw new BCException("Do not know the signature string for MemberKind "+kind);
+       }
+    }
+
+    public static String getSignatureMakerName(Member m) {
+       MemberKind kind = m.getKind();
+       if (kind == Member.METHOD) {
+               return "makeMethodSig";
+       } else if (kind == Member.CONSTRUCTOR) {
+               return "makeConstructorSig";
+       } else if (kind == Member.FIELD) {
+               return "makeFieldSig";
+       } else if (kind == Member.HANDLER) {
+               return "makeCatchClauseSig";
+       } else if (kind == Member.STATIC_INITIALIZATION) {
+               return "makeInitializerSig";
+       } else if (kind == Member.ADVICE) {
+               return "makeAdviceSig";
+       } else if (kind == Member.MONITORENTER) {
+               return "makeLockSig";
+       } else if (kind == Member.MONITOREXIT) {
+               return "makeUnlockSig";
+       } else {
+               throw new BCException("Do not know the signature maker name for MemberKind "+kind);
+       }
+    }
+
+       public static String getSignatureType(Member m) {
+       MemberKind kind = m.getKind();
+       if (m.getName().equals("<clinit>") && kind!=Member.STATIC_INITIALIZATION) throw new BCException();
+//     if (m.getName().equals("<clinit>")) return "org.aspectj.lang.reflect.InitializerSignature";
+       
+       if (kind == Member.METHOD) {
+               return "org.aspectj.lang.reflect.MethodSignature";
+       } else if (kind == Member.CONSTRUCTOR) {
+               return "org.aspectj.lang.reflect.ConstructorSignature";
+       } else if (kind == Member.FIELD) {
+               return "org.aspectj.lang.reflect.FieldSignature";
+       } else if (kind == Member.HANDLER) {
+               return "org.aspectj.lang.reflect.CatchClauseSignature";
+       } else if (kind == Member.STATIC_INITIALIZATION) {
+               return "org.aspectj.lang.reflect.InitializerSignature";
+       } else if (kind == Member.ADVICE) {
+               return "org.aspectj.lang.reflect.AdviceSignature";
+       } else if (kind == Member.MONITORENTER) {
+               return "org.aspectj.lang.reflect.LockSignature";
+       } else if (kind == Member.MONITOREXIT) {
+               return "org.aspectj.lang.reflect.UnlockSignature";
+       } else {
+               throw new BCException("Do not know the signature type for MemberKind "+kind);
+       }
+    }
+
+    
+    // ---
+       
+
+       private static String getHandlerSignatureString(Member m, World world) {
+        StringBuffer buf = new StringBuffer();
+        buf.append(makeString(0));
+        buf.append('-');
+        //buf.append(getName());
+        buf.append('-');
+        buf.append(makeString(m.getDeclaringType()));
+        buf.append('-');
+        buf.append(makeString(m.getParameterTypes()[0]));
+        buf.append('-');
+        String pName = "<missing>";
+        String[] names = m.getParameterNames(world);
+        if (names != null) pName = names[0];
+        buf.append(pName);
+        buf.append('-');
+        return buf.toString();
+       }
+       
+       private static String getStaticInitializationSignatureString(Member m, World world) {
+        StringBuffer buf = new StringBuffer();
+        buf.append(makeString(m.getModifiers(world)));
+        buf.append('-');
+        //buf.append(getName());
+        buf.append('-');
+        buf.append(makeString(m.getDeclaringType()));
+        buf.append('-');
+        return buf.toString();
+       }
+
+       protected static String getAdviceSignatureString(Member m, World world) {
+        StringBuffer buf = new StringBuffer();
+        buf.append(makeString(m.getModifiers(world)));
+        buf.append('-');
+        buf.append(m.getName());
+        buf.append('-');
+        buf.append(makeString(m.getDeclaringType()));
+        buf.append('-');
+        buf.append(makeString(m.getParameterTypes()));
+        buf.append('-');
+        buf.append(makeString(m.getParameterNames(world)));
+        buf.append('-');
+        buf.append(makeString(m.getExceptions(world)));
+        buf.append('-');
+        buf.append(makeString(m.getReturnType()));
+        buf.append('-');
+        return buf.toString();
+       }
+
+
+       protected static String getMethodSignatureString(Member m, World world) {
+        StringBuffer buf = new StringBuffer();
+        buf.append(makeString(m.getModifiers(world)));
+        buf.append('-');
+        buf.append(m.getName());
+        buf.append('-');
+        buf.append(makeString(m.getDeclaringType()));
+        buf.append('-');
+        buf.append(makeString(m.getParameterTypes()));
+        buf.append('-');
+        buf.append(makeString(m.getParameterNames(world)));
+        buf.append('-');
+        buf.append(makeString(m.getExceptions(world)));
+        buf.append('-');
+        buf.append(makeString(m.getReturnType()));
+        buf.append('-');
+        return buf.toString();
+       }
+       
+       protected static String getMonitorSignatureString(Member m, World world) {
+        StringBuffer buf = new StringBuffer();
+        buf.append(makeString(Modifier.STATIC));    // modifiers
+        buf.append('-');
+        buf.append(m.getName());                      // name
+        buf.append('-');
+        buf.append(makeString(m.getDeclaringType())); // Declaring Type
+        buf.append('-');
+        buf.append(makeString(m.getParameterTypes()[0])); // Parameter Types
+        buf.append('-');
+        buf.append("");                                 // Parameter names
+        buf.append('-');
+        return buf.toString();
+       }
+
+       protected static String getConstructorSignatureString(Member m, World world) {
+        StringBuffer buf = new StringBuffer();
+        buf.append(makeString(m.getModifiers(world)));
+        buf.append('-');
+        buf.append('-');
+        buf.append(makeString(m.getDeclaringType()));
+        buf.append('-');
+        buf.append(makeString(m.getParameterTypes()));
+        buf.append('-');
+        buf.append(makeString(m.getParameterNames(world)));
+        buf.append('-');
+        buf.append(makeString(m.getExceptions(world)));
+        buf.append('-');
+        return buf.toString();
+    }
+       
+       
+
+
+       protected static String getFieldSignatureString(Member m, World world) {
+        StringBuffer buf = new StringBuffer();
+        buf.append(makeString(m.getModifiers(world)));
+        buf.append('-');
+        buf.append(m.getName());
+        buf.append('-');
+        buf.append(makeString(m.getDeclaringType()));
+        buf.append('-');
+        buf.append(makeString(m.getReturnType()));
+        buf.append('-');
+        return buf.toString();
+    }
+
+       protected static String makeString(int i) {
+               return Integer.toString(i, 16);
+       }
+
+       protected static String makeString(UnresolvedType t) {
+       // this is the inverse of the odd behavior for Class.forName w/ arrays
+       if (t.isArray()) {
+               // this behavior matches the string used by the eclipse compiler for Foo.class literals
+               return t.getSignature().replace('/', '.');
+       } else {
+               return t.getName();
+       }
+    }
+    
+
+
+       protected static String makeString(UnresolvedType[] types) {
+       if (types == null) return "";
+        StringBuffer buf = new StringBuffer();
+        for (int i = 0, len=types.length; i < len; i++) {
+            buf.append(makeString(types[i]));
+            buf.append(':');
+        }
+        return buf.toString();
+    }
+    
+
+
+       protected static String makeString(String[] names) {
+       if (names == null) return "";
+        StringBuffer buf = new StringBuffer();
+        for (int i = 0, len=names.length; i < len; i++) {
+            buf.append(names[i]);
+            buf.append(':');
+        }
+        return buf.toString();
+    }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/SimpleAnnotationValue.java b/org.aspectj.matcher/src/org/aspectj/weaver/SimpleAnnotationValue.java
new file mode 100644 (file)
index 0000000..41dab70
--- /dev/null
@@ -0,0 +1,82 @@
+/* *******************************************************************
+ * Copyright (c) 2006 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement IBM     initial implementation 
+ * ******************************************************************/
+ package org.aspectj.weaver;
+
+public class SimpleAnnotationValue extends AnnotationValue {
+
+       public SimpleAnnotationValue(int kind) {
+               super(kind);
+       }
+
+       public SimpleAnnotationValue(int kind, Object value) {
+               super(kind); 
+               switch (kind) {
+                       case AnnotationValue.PRIMITIVE_BYTE: theByte = ((Byte)value).byteValue(); break;
+                       case AnnotationValue.PRIMITIVE_CHAR: theChar = ((Character)value).charValue(); break;
+                       case AnnotationValue.PRIMITIVE_INT: theInt = ((Integer)value).intValue(); break;
+                       case AnnotationValue.STRING: theString = (String)value; break;
+                       case AnnotationValue.PRIMITIVE_DOUBLE: theDouble = ((Double)value).doubleValue(); break;
+                       case AnnotationValue.PRIMITIVE_FLOAT: theFloat = ((Float)value).floatValue(); break;
+                       case AnnotationValue.PRIMITIVE_LONG: theLong = ((Long)value).longValue(); break;
+                       case AnnotationValue.PRIMITIVE_SHORT: theShort = ((Short)value).shortValue(); break;
+                       case AnnotationValue.PRIMITIVE_BOOLEAN: theBoolean = ((Boolean)value).booleanValue(); break;
+                       default:
+                           throw new BCException("Not implemented for this kind: "+whatKindIsThis(kind));
+               }
+       }
+
+       private byte theByte;
+       private char theChar;
+       private int  theInt;
+       private String theString;
+       private double theDouble;
+       private float theFloat;
+       private long theLong;
+       private short theShort;
+       private boolean theBoolean;
+       
+       public void setValueString(String s) { theString = s;   }
+       public void setValueByte(byte b)    { theByte = b; }
+       public void setValueChar(char c)    { theChar = c; }
+       public void setValueInt(int i)      { theInt = i; }
+       
+
+       public String stringify() {
+               switch (valueKind) {
+                 case 'B': // byte
+                         return Byte.toString(theByte);
+                 case 'C': // char
+                         return new Character(theChar).toString();
+                 case 'D': // double
+                         return Double.toString(theDouble);
+                 case 'F': // float
+                         return Float.toString(theFloat);
+                 case 'I': // int
+                        return Integer.toString(theInt);
+                 case 'J': // long
+                         return Long.toString(theLong);
+                 case 'S': // short
+                         return Short.toString(theShort);
+                 case 'Z': // boolean
+                         return new Boolean(theBoolean).toString();
+                 case 's': // String
+                         return theString;
+                 default: throw new BCException("Do not understand this kind: "+valueKind);
+               }
+       }
+       
+       public String toString() {
+               return stringify();
+       }
+
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/SourceContextImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/SourceContextImpl.java
new file mode 100644 (file)
index 0000000..76f0dbd
--- /dev/null
@@ -0,0 +1,109 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.File;
+import java.util.Arrays;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.SourceLocation;
+
+public class SourceContextImpl implements ISourceContext {
+       
+//     private AbstractReferenceTypeDelegate delegate;
+       private int[] lineBreaks;
+       String sfname;
+       
+       public SourceContextImpl(AbstractReferenceTypeDelegate delegate) {
+//             this.delegate = delegate;
+               sfname = delegate.getSourcefilename();
+       }
+       
+       public void configureFromAttribute(String name,int []linebreaks) { 
+//             this.delegate.setSourcefilename(name);
+               sfname = name;
+               this.lineBreaks = linebreaks;
+       }
+       
+       public void setSourceFileName(String name) {
+               sfname = name;
+       }
+       
+       private File getSourceFile() {
+               return new File(sfname);
+//             return new File(delegate.getSourcefilename());
+       }
+       
+       public void tidy() {}
+       
+       public int getOffset() { return 0; }
+               
+               /*
+               // AMC - a temporary "fudge" to give as much information as possible about the identity of the
+               // source file this source location points to.
+               String internalClassName = getEnclosingClass().getInternalClassName();
+               String fileName = getEnclosingClass().getFileName();
+               String extension = fileName.substring( fileName.lastIndexOf("."), fileName.length());
+               String filePrefix = fileName.substring( 0, fileName.lastIndexOf("."));
+               // internal class name is e.g. figures/Point, we don't know whether the file was
+               // .aj or .java so we put it together with the file extension of the enclosing class
+               // BUT... sometimes internalClassName is a different class (an aspect), so we only use it if it 
+               // matches the file name.
+               String mostAccurateFileNameGuess;
+               if ( internalClassName.endsWith(filePrefix)) {
+                       mostAccurateFileNameGuess = internalClassName + extension;
+               } else {
+                       mostAccurateFileNameGuess = fileName;
+               }
+               return new SourceLocation(new File(mostAccurateFileNameGuess), getSourceLine());
+               */
+
+
+
+       public ISourceLocation makeSourceLocation(IHasPosition position) {
+               if (lineBreaks != null) {
+                       int line = Arrays.binarySearch(lineBreaks, position.getStart());
+                       if (line < 0) line = -line;
+                       return new SourceLocation(getSourceFile(), line); //??? have more info
+               } else {
+                       return new SourceLocation(getSourceFile(), 0);
+               }
+       }
+       
+       public ISourceLocation makeSourceLocation(int line, int offset) {
+        if (line < 0) line = 0;
+               SourceLocation sl = new SourceLocation(getSourceFile(), line);
+        if (offset > 0) {
+            sl.setOffset(offset);
+        } else {
+            if (lineBreaks != null) {
+                int likelyOffset = 0;
+                if (line > 0 && line < lineBreaks.length) {
+                    //1st char of given line is next char after previous end of line
+                    likelyOffset = lineBreaks[line-1] + 1;
+                }
+                sl.setOffset(likelyOffset);
+            }
+        }
+        return sl;
+       }
+
+
+       public final static ISourceContext UNKNOWN_SOURCE_CONTEXT = new ISourceContext() {
+               public ISourceLocation makeSourceLocation(IHasPosition position) {return null;}
+               public ISourceLocation makeSourceLocation(int line, int offset) {return null;}
+               public int getOffset() {return 0;}
+               public void tidy() {}
+       };
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/StandardAnnotation.java b/org.aspectj.matcher/src/org/aspectj/weaver/StandardAnnotation.java
new file mode 100644 (file)
index 0000000..3dd7bfb
--- /dev/null
@@ -0,0 +1,153 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This type represents the weavers abstraction of an annotation - it is not tied to any underlying BCI toolkit. The weaver actualy
+ * handles these through AnnotationX wrapper objects - until we start transforming the BCEL annotations into this form (expensive)
+ * or offer a clever visitor mechanism over the BCEL annotation stuff that builds these annotation types directly.
+ * 
+ * @author AndyClement
+ */
+public class StandardAnnotation extends AbstractAnnotationAJ {
+
+       private final boolean isRuntimeVisible;
+
+       private List /* of AnnotationNVPair */nvPairs = null;
+
+       public StandardAnnotation(ResolvedType type, boolean isRuntimeVisible) {
+               super(type);
+               this.isRuntimeVisible = isRuntimeVisible;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public boolean isRuntimeVisible() {
+               return isRuntimeVisible;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public String stringify() {
+               StringBuffer sb = new StringBuffer();
+               sb.append("@").append(type.getClassName());
+               if (hasNameValuePairs()) {
+                       sb.append("(");
+                       for (Iterator iter = nvPairs.iterator(); iter.hasNext();) {
+                               AnnotationNameValuePair element = (AnnotationNameValuePair) iter.next();
+                               sb.append(element.stringify());
+                       }
+                       sb.append(")");
+               }
+               return sb.toString();
+       }
+
+       public String toString() {
+               StringBuffer sb = new StringBuffer();
+               sb.append("ANNOTATION [" + getTypeSignature() + "] [" + (isRuntimeVisible ? "runtimeVisible" : "runtimeInvisible") + "] [");
+               if (nvPairs != null) {
+                       for (Iterator iter = nvPairs.iterator(); iter.hasNext();) {
+                               AnnotationNameValuePair element = (AnnotationNameValuePair) iter.next();
+                               sb.append(element.toString());
+                               if (iter.hasNext())
+                                       sb.append(",");
+                       }
+               }
+               sb.append("]");
+               return sb.toString();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public boolean hasNamedValue(String n) {
+               if (nvPairs == null)
+                       return false;
+               for (int i = 0; i < nvPairs.size(); i++) {
+                       AnnotationNameValuePair pair = (AnnotationNameValuePair) nvPairs.get(i);
+                       if (pair.getName().equals(n))
+                               return true;
+               }
+               return false;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public boolean hasNameValuePair(String n, String v) {
+               if (nvPairs == null)
+                       return false;
+               for (int i = 0; i < nvPairs.size(); i++) {
+                       AnnotationNameValuePair pair = (AnnotationNameValuePair) nvPairs.get(i);
+                       if (pair.getName().equals(n)) {
+                               if (pair.getValue().stringify().equals(v))
+                                       return true;
+                       }
+               }
+               return false;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public Set /* <String> */getTargets() {
+               if (!type.equals(UnresolvedType.AT_TARGET)) {
+                       return Collections.EMPTY_SET;
+               }
+               AnnotationNameValuePair nvp = (AnnotationNameValuePair) nvPairs.get(0);
+               ArrayAnnotationValue aav = (ArrayAnnotationValue) nvp.getValue();
+               AnnotationValue[] avs = aav.getValues();
+               Set targets = new HashSet();
+               for (int i = 0; i < avs.length; i++) {
+                       AnnotationValue value = avs[i];
+                       targets.add(value.stringify());
+               }
+               return targets;
+       }
+
+       public List getNameValuePairs() {
+               return nvPairs;
+       }
+
+       public boolean hasNameValuePairs() {
+               return nvPairs != null && nvPairs.size() != 0;
+       }
+
+       public void addNameValuePair(AnnotationNameValuePair pair) {
+               if (nvPairs == null) {
+                       nvPairs = new ArrayList();
+               }
+               nvPairs.add(pair);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public String getStringFormOfValue(String name) {
+               if (hasNameValuePairs()) {
+                       for (Iterator iterator = nvPairs.iterator(); iterator.hasNext();) {
+                               AnnotationNameValuePair nvPair = (AnnotationNameValuePair) iterator.next();
+                               if (nvPair.getName().equals(name)) {
+                                       return nvPair.getValue().stringify();
+                               }
+                       }
+               }
+               return null;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/StaticJoinPointFactory.java b/org.aspectj.matcher/src/org/aspectj/weaver/StaticJoinPointFactory.java
new file mode 100644 (file)
index 0000000..c7f4f86
--- /dev/null
@@ -0,0 +1,56 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+
+public class StaticJoinPointFactory {
+//     int usedKeys;
+//     
+//     List/*String*/ strings = new ArrayList();
+//     Map/*String,Integer*/ keysForStrings = new HashMap();
+//     
+//     public StaticJoinPointFactory() {
+//             super();
+//     }
+//
+//     static char[] encoding = new char[] {
+//             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',//10
+//             'a', 'b', 'z', //36
+//             'A', 'B', 'Z', //62
+//        '%', '$', //64
+//    };
+//    
+//    static int TWO_WORDS = 64*64-1;
+//    static int WORD_MASK = 63;
+//    
+//    public void write(String s, StringBuffer result) {
+//     int i = getIndex(s);
+//     encode(i, result);
+//    }
+//    
+//    void encode(int i, StringBuffer result) {
+//     if (i > TWO_WORDS) {
+//             throw new RuntimeException("unimplemented");
+//     } else {
+//             result.append( encoding[(i >> 6) & WORD_MASK] );
+//             result.append( encoding[i & WORD_MASK] );
+//     }
+//    }
+//    
+//    public String read(StringReader reader) {
+//     int i = reader.read();
+//     
+//    }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/TemporaryTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/TemporaryTypeMunger.java
new file mode 100644 (file)
index 0000000..2d31b59
--- /dev/null
@@ -0,0 +1,35 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.util.Map;
+
+/**
+ * Some methods need a temporary type munger (because ConcreteTypeMunger is abstract - dont ask...).
+ * 
+ * TODO ought to remove the need for this or at least sort out the two methods that are in it, they look wierd...
+ * 
+ * @author AndyClement
+ */
+public class TemporaryTypeMunger extends ConcreteTypeMunger {
+
+       public TemporaryTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) {
+               super(munger, aspectType);
+       }
+
+       public ConcreteTypeMunger parameterizeWith(Map parameterizationMap, World world) {
+               throw new UnsupportedOperationException("Cannot be called on a TemporaryTypeMunger");
+       }
+
+       public ConcreteTypeMunger parameterizedFor(ResolvedType targetType) {
+               throw new UnsupportedOperationException("Cannot be called on a TemporaryTypeMunger");
+       }
+
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/TypeFactory.java b/org.aspectj.matcher/src/org/aspectj/weaver/TypeFactory.java
new file mode 100644 (file)
index 0000000..2200224
--- /dev/null
@@ -0,0 +1,293 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author colyer
+ * 
+ */
+public class TypeFactory {
+
+       /**
+        * Create a parameterized version of a generic type.
+        * 
+        * @param aGenericType
+        * @param someTypeParameters note, in the case of an inner type of a parameterized type, this parameter may legitimately be null
+        * @param inAWorld
+        * @return
+        */
+       public static ReferenceType createParameterizedType(ResolvedType aBaseType, UnresolvedType[] someTypeParameters, World inAWorld) {
+               ResolvedType baseType = aBaseType;
+               if (!aBaseType.isGenericType()) {
+                       // try and find the generic type...
+                       if (someTypeParameters != null && someTypeParameters.length > 0) {
+                               if (!aBaseType.isRawType())
+                                       throw new IllegalStateException("Expecting raw type, not: " + aBaseType);
+                               baseType = baseType.getGenericType();
+                               if (baseType == null)
+                                       throw new IllegalStateException("Raw type does not have generic type set");
+                       } // else if someTypeParameters is null, then the base type is allowed to be non-generic, it's an inner
+               }
+               ResolvedType[] resolvedParameters = inAWorld.resolve(someTypeParameters);
+               ReferenceType pType = new ReferenceType(baseType, resolvedParameters, inAWorld);
+               // pType.setSourceContext(aBaseType.getSourceContext());
+               return (ReferenceType) pType.resolve(inAWorld);
+       }
+
+       /**
+        * Create an *unresolved* parameterized version of a generic type.
+        */
+       public static UnresolvedType createUnresolvedParameterizedType(String sig, String erasuresig, UnresolvedType[] arguments) {
+               return new UnresolvedType(sig, erasuresig, arguments);
+       }
+
+       // public static ReferenceType createRawType(
+       // ResolvedType aBaseType,
+       // World inAWorld
+       // ) {
+       // if (aBaseType.isRawType()) return (ReferenceType) aBaseType;
+       // if (!aBaseType.isGenericType()) {
+       // if (!aBaseType.isRawType()) throw new IllegalStateException("Expecting generic type");
+       // }
+       // ReferenceType rType = new ReferenceType(aBaseType,inAWorld);
+       // //rType.setSourceContext(aBaseType.getSourceContext());
+       // return (ReferenceType) rType.resolve(inAWorld);
+       // }
+
+       /**
+        * Creates a sensible unresolvedtype from some signature, for example: signature = LIGuard<TT;>; bound = toString=IGuard<T>
+        * sig=PIGuard<TT;>; sigErasure=LIGuard; kind=parameterized
+        */
+       private static UnresolvedType convertSigToType(String aSignature) {
+               UnresolvedType bound = null;
+               int startOfParams = aSignature.indexOf('<');
+               if (startOfParams == -1) {
+                       bound = UnresolvedType.forSignature(aSignature);
+               } else {
+                       int endOfParams = aSignature.lastIndexOf('>');
+                       String signatureErasure = "L" + aSignature.substring(1, startOfParams) + ";";
+                       UnresolvedType[] typeParams = createTypeParams(aSignature.substring(startOfParams + 1, endOfParams));
+                       bound = new UnresolvedType("P" + aSignature.substring(1), signatureErasure, typeParams);
+               }
+               return bound;
+       }
+
+       /**
+        * Used by UnresolvedType.read, creates a type from a full signature.
+        * 
+        * @param signature
+        * @return
+        */
+       public static UnresolvedType createTypeFromSignature(String signature) {
+               if (signature.equals(ResolvedType.MISSING_NAME))
+                       return ResolvedType.MISSING;
+               char firstChar = signature.charAt(0);
+               if (firstChar == 'P') {
+                       // parameterized type, calculate signature erasure and type parameters
+                       // (see pr122458) It is possible for a parameterized type to have *no* type parameters visible in its signature.
+                       // This happens for an inner type of a parameterized type which simply inherits the type parameters
+                       // of its parent. In this case it is parameterized but theres no < in the signature.
+                       int startOfParams = signature.indexOf('<');
+
+                       if (startOfParams == -1) {
+                               // Should be an inner type of a parameterized type - could assert there is a '$' in the signature....
+                               String signatureErasure = "L" + signature.substring(1);
+                               UnresolvedType[] typeParams = new UnresolvedType[0];
+                               return new UnresolvedType(signature, signatureErasure, typeParams);
+                       } else {
+                               int endOfParams = locateMatchingEndBracket(signature, startOfParams);// signature.lastIndexOf('>');
+                               StringBuffer erasureSig = new StringBuffer(signature);
+                               while (startOfParams != -1) {
+                                       erasureSig.delete(startOfParams, endOfParams + 1);
+                                       startOfParams = locateFirstBracket(erasureSig);
+                                       if (startOfParams != -1)
+                                               endOfParams = locateMatchingEndBracket(erasureSig, startOfParams);
+                               }
+
+                               String signatureErasure = "L" + erasureSig.toString().substring(1);
+
+                               // the type parameters of interest are only those that apply to the 'last type' in the signature
+                               // if the signature is 'PMyInterface<String>$MyOtherType;' then there are none...
+                               String lastType = null;
+                               int nestedTypePosition = signature.indexOf("$", endOfParams); // don't look for $ INSIDE the parameters
+                               if (nestedTypePosition != -1)
+                                       lastType = signature.substring(nestedTypePosition + 1);
+                               else
+                                       lastType = new String(signature);
+                               startOfParams = lastType.indexOf("<");
+                               endOfParams = locateMatchingEndBracket(lastType, startOfParams);
+                               UnresolvedType[] typeParams = UnresolvedType.NONE;
+                               if (startOfParams != -1) {
+                                       typeParams = createTypeParams(lastType.substring(startOfParams + 1, endOfParams));
+                               }
+                               return new UnresolvedType(signature, signatureErasure, typeParams);
+                       }
+                       // can't replace above with convertSigToType - leads to stackoverflow
+               } else if (signature.equals("?") || signature.equals("*")) {
+                       return WildcardedUnresolvedType.QUESTIONMARK;
+               } else if (firstChar == '+') {
+                       // ? extends ...
+                       UnresolvedType upperBound = convertSigToType(signature.substring(1));
+                       WildcardedUnresolvedType wildcardedUT = new WildcardedUnresolvedType(signature, upperBound, null);
+                       return wildcardedUT;
+               } else if (firstChar == '-') {
+                       // ? super ...
+                       UnresolvedType lowerBound = convertSigToType(signature.substring(1));
+                       WildcardedUnresolvedType wildcardedUT = new WildcardedUnresolvedType(signature, null, lowerBound);
+                       return wildcardedUT;
+               } else if (firstChar == 'T') {
+                       String typeVariableName = signature.substring(1);
+                       if (typeVariableName.endsWith(";")) {
+                               typeVariableName = typeVariableName.substring(0, typeVariableName.length() - 1);
+                       }
+                       return new UnresolvedTypeVariableReferenceType(new TypeVariable(typeVariableName));
+               } else if (firstChar == '[') {
+                       int dims = 0;
+                       while (signature.charAt(dims) == '[')
+                               dims++;
+                       UnresolvedType componentType = createTypeFromSignature(signature.substring(dims));
+                       return new UnresolvedType(signature, signature.substring(0, dims) + componentType.getErasureSignature());
+               } else if (signature.length() == 1) { // could be a primitive
+                       switch (firstChar) {
+                       case 'V':
+                               return ResolvedType.VOID;
+                       case 'Z':
+                               return ResolvedType.BOOLEAN;
+                       case 'B':
+                               return ResolvedType.BYTE;
+                       case 'C':
+                               return ResolvedType.CHAR;
+                       case 'D':
+                               return ResolvedType.DOUBLE;
+                       case 'F':
+                               return ResolvedType.FLOAT;
+                       case 'I':
+                               return ResolvedType.INT;
+                       case 'J':
+                               return ResolvedType.LONG;
+                       case 'S':
+                               return ResolvedType.SHORT;
+                       }
+               }
+               return new UnresolvedType(signature);
+       }
+
+       private static int locateMatchingEndBracket(String signature, int startOfParams) {
+               if (startOfParams == -1)
+                       return -1;
+               int count = 1;
+               int idx = startOfParams;
+               while (count > 0 && idx < signature.length()) {
+                       idx++;
+                       if (signature.charAt(idx) == '<')
+                               count++;
+                       if (signature.charAt(idx) == '>')
+                               count--;
+               }
+               return idx;
+       }
+
+       private static int locateMatchingEndBracket(StringBuffer signature, int startOfParams) {
+               if (startOfParams == -1)
+                       return -1;
+               int count = 1;
+               int idx = startOfParams;
+               while (count > 0 && idx < signature.length()) {
+                       idx++;
+                       if (signature.charAt(idx) == '<')
+                               count++;
+                       if (signature.charAt(idx) == '>')
+                               count--;
+               }
+               return idx;
+       }
+
+       private static int locateFirstBracket(StringBuffer signature) {
+               int idx = 0;
+               while (idx < signature.length()) {
+                       if (signature.charAt(idx) == '<')
+                               return idx;
+                       idx++;
+               }
+               return -1;
+       }
+
+       private static UnresolvedType[] createTypeParams(String typeParameterSpecification) {
+               String remainingToProcess = typeParameterSpecification;
+               List types = new ArrayList();
+               while (!remainingToProcess.equals("")) {
+                       int endOfSig = 0;
+                       int anglies = 0;
+                       boolean sigFound = false; // OPTIMIZE can this be done better?
+                       for (endOfSig = 0; (endOfSig < remainingToProcess.length()) && !sigFound; endOfSig++) {
+                               char thisChar = remainingToProcess.charAt(endOfSig);
+                               switch (thisChar) {
+                               case '<':
+                                       anglies++;
+                                       break;
+                               case '>':
+                                       anglies--;
+                                       break;
+                               case '[':
+                                       if (anglies == 0) {
+                                               // the next char might be a [ or a primitive type ref (BCDFIJSZ)
+                                               int nextChar = endOfSig + 1;
+                                               while (remainingToProcess.charAt(nextChar) == '[') {
+                                                       nextChar++;
+                                               }
+                                               if ("BCDFIJSZ".indexOf(remainingToProcess.charAt(nextChar)) != -1) {
+                                                       // it is something like [I or [[S
+                                                       sigFound = true;
+                                                       endOfSig = nextChar;
+                                                       break;
+                                               }
+                                       }
+                                       break;
+                               case ';':
+                                       if (anglies == 0) {
+                                               sigFound = true;
+                                               break;
+                                       }
+                               }
+                       }
+                       types.add(createTypeFromSignature(remainingToProcess.substring(0, endOfSig)));
+                       remainingToProcess = remainingToProcess.substring(endOfSig);
+               }
+               UnresolvedType[] typeParams = new UnresolvedType[types.size()];
+               types.toArray(typeParams);
+               return typeParams;
+       }
+
+       // OPTIMIZE improve all this signature processing stuff, use char arrays, etc
+
+       /**
+        * Create a signature then delegate to the other factory method. Same input/output: baseTypeSignature="LSomeType;" arguments[0]=
+        * something with sig "Pcom/Foo<Ljava/lang/String;>;" signature created = "PSomeType<Pcom/Foo<Ljava/lang/String;>;>;"
+        */
+       public static UnresolvedType createUnresolvedParameterizedType(String baseTypeSignature, UnresolvedType[] arguments) {
+               StringBuffer parameterizedSig = new StringBuffer();
+               parameterizedSig.append(ResolvedType.PARAMETERIZED_TYPE_IDENTIFIER);
+               parameterizedSig.append(baseTypeSignature.substring(1, baseTypeSignature.length() - 1));
+               if (arguments.length > 0) {
+                       parameterizedSig.append("<");
+                       for (int i = 0; i < arguments.length; i++) {
+                               parameterizedSig.append(arguments[i].getSignature());
+                       }
+                       parameterizedSig.append(">");
+               }
+               parameterizedSig.append(";");
+               return createUnresolvedParameterizedType(parameterizedSig.toString(), baseTypeSignature, arguments);
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/TypeVariable.java b/org.aspectj.matcher/src/org/aspectj/weaver/TypeVariable.java
new file mode 100644 (file)
index 0000000..2762fa7
--- /dev/null
@@ -0,0 +1,372 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * Represents a type variable with bounds
+ */
+public class TypeVariable {
+       
+       public static final TypeVariable[] NONE = new TypeVariable[0];
+       /**
+        * whether or not the bounds of this type variable have been 
+        * resolved
+        */
+       private boolean isResolved = false;
+       
+       
+       private boolean beingResolved = false;
+       
+       /**
+        * the name of the type variable as recorded in the generic signature
+        */
+       private String name;
+       
+       private int rank;
+
+    // It would be nice to push this field onto the TypeVariableDeclaringElement
+    // interface (a getKind()) but at the moment we don't always guarantee
+    // to set the declaring element (eclipse seems to utilise the knowledge of
+    // what declared the type variable, but we dont yet...)
+       /**
+        * What kind of element declared this type variable?
+        */
+       private int declaringElementKind = UNKNOWN;
+       public static final int UNKNOWN = -1;
+       public static final int METHOD  = 1;
+       public static final int TYPE    = 2;
+       private TypeVariableDeclaringElement declaringElement;
+       
+       /**
+        * the upper bound of the type variable (default to Object).
+        * From the extends clause, eg. T extends Number.
+        */
+       private UnresolvedType upperBound = UnresolvedType.OBJECT;
+       
+       /**
+        * any additional upper (interface) bounds.
+        * from the extends clause, e.g. T extends Number & Comparable
+        */
+       private UnresolvedType[] additionalInterfaceBounds = new UnresolvedType[0];
+       
+       /**
+        * any lower bound.
+        * from the super clause, eg T super Foo
+        */
+       private UnresolvedType lowerBound = null;
+       
+       public TypeVariable(String aName) {
+               this.name = aName;
+       }
+       
+       public TypeVariable(String aName, UnresolvedType anUpperBound) {
+               this(aName);
+               this.upperBound = anUpperBound;
+       }
+       
+       public TypeVariable(String aName, UnresolvedType anUpperBound, 
+                                               UnresolvedType[] someAdditionalInterfaceBounds) {
+               this(aName,anUpperBound);
+               this.additionalInterfaceBounds = someAdditionalInterfaceBounds;
+       }
+       
+       public TypeVariable(String aName, UnresolvedType anUpperBound, 
+            UnresolvedType[] someAdditionalInterfaceBounds, UnresolvedType aLowerBound) {
+               this(aName,anUpperBound,someAdditionalInterfaceBounds);
+               this.lowerBound = aLowerBound;
+       }
+       
+       // First bound is the first 'real' bound, this can be an interface if 
+       // no class bound was specified (it will default to object)
+       public UnresolvedType getFirstBound() {
+               if (upperBound.equals(UnresolvedType.OBJECT) && additionalInterfaceBounds!=null && additionalInterfaceBounds.length!=0) {
+                       return additionalInterfaceBounds[0];
+               }
+               return upperBound;
+       }
+       
+       public UnresolvedType getUpperBound() {
+               return upperBound;
+       }
+       
+       public UnresolvedType[] getAdditionalInterfaceBounds() {
+               return additionalInterfaceBounds;
+       }
+       
+       public UnresolvedType getLowerBound() {
+               return lowerBound;
+       }
+       
+       public String getName() {
+               return name;
+       }
+       
+       /**
+        * resolve all the bounds of this type variable
+        */
+       public TypeVariable resolve(World inSomeWorld) {
+               if (beingResolved) { return this; } // avoid spiral of death
+               beingResolved = true;
+               if (isResolved) return this;
+
+               TypeVariable resolvedTVar = null;
+
+               if (declaringElement != null) {
+                       // resolve by finding the real type var that we refer to...
+                       if (declaringElementKind == TYPE) {
+                               UnresolvedType declaring = (UnresolvedType) declaringElement;
+                               ReferenceType rd = (ReferenceType) declaring.resolve(inSomeWorld);
+                               TypeVariable[] tVars = rd.getTypeVariables();
+                               for (int i = 0; i < tVars.length; i++) {
+                                       if (tVars[i].getName().equals(getName())) {
+                                               resolvedTVar = tVars[i];
+                                               break;
+                                       }
+                               }
+                       } else {
+                               // look for type variable on method...
+                               ResolvedMember declaring = (ResolvedMember) declaringElement;
+                               TypeVariable[] tvrts = declaring.getTypeVariables();
+                               for (int i = 0; i < tvrts.length; i++) {
+                                       if (tvrts[i].getName().equals(getName())) resolvedTVar = tvrts[i];
+//                                     if (tvrts[i].isTypeVariableReference()) {
+//                                             TypeVariableReferenceType tvrt = (TypeVariableReferenceType) tvrts[i].resolve(inSomeWorld);
+//                                             TypeVariable tv = tvrt.getTypeVariable();
+//                                             if (tv.getName().equals(getName())) resolvedTVar = tv;
+//                                     }
+                               }                       
+                       }
+                       
+                       if (resolvedTVar == null) {
+                               // well, this is bad... we didn't find the type variable on the member
+                               // could be a separate compilation issue...
+                               // should issue message, this is a workaround to get us going...
+                               resolvedTVar = this;                            
+                       }
+               } else {
+                       resolvedTVar = this;
+               }
+                               
+               upperBound = resolvedTVar.upperBound;
+               lowerBound = resolvedTVar.lowerBound;
+               additionalInterfaceBounds = resolvedTVar.additionalInterfaceBounds;
+               
+               upperBound = upperBound.resolve(inSomeWorld);
+               if (lowerBound != null) lowerBound = lowerBound.resolve(inSomeWorld);
+               
+               if (additionalInterfaceBounds!=null) {
+                       for (int i = 0; i < additionalInterfaceBounds.length; i++) {
+                               additionalInterfaceBounds[i] = additionalInterfaceBounds[i].resolve(inSomeWorld);
+                       }
+               }
+               isResolved = true;
+               beingResolved = false;
+               return this;
+       }
+       
+       /**
+        * answer true if the given type satisfies all of the bound constraints of this
+        * type variable.
+        * If type variable has not been resolved then throws IllegalStateException
+        */
+       public boolean canBeBoundTo(ResolvedType aCandidateType) {
+               if (!isResolved) throw new IllegalStateException("Can't answer binding questions prior to resolving");
+               
+               // wildcard can accept any binding
+               if (aCandidateType.isGenericWildcard()) {  // AMC - need a more robust test!
+                       return true;
+               }
+               
+               // otherwise can be bound iff...
+               //  aCandidateType is a subtype of upperBound
+               if (!isASubtypeOf(upperBound,aCandidateType)) {
+                       return false;
+               }
+               //  aCandidateType is a subtype of all additionalInterfaceBounds
+               for (int i = 0; i < additionalInterfaceBounds.length; i++) {
+                       if (!isASubtypeOf(additionalInterfaceBounds[i], aCandidateType)) {
+                               return false;
+                       }
+               }
+               //  lowerBound is a subtype of aCandidateType
+               if ((lowerBound != null) && (!isASubtypeOf(aCandidateType,lowerBound))) {
+                       return false;
+               }
+               return true;
+       }
+       
+       private boolean isASubtypeOf(UnresolvedType candidateSuperType, UnresolvedType candidateSubType) {
+               ResolvedType superType = (ResolvedType) candidateSuperType;
+               ResolvedType subType = (ResolvedType) candidateSubType;
+               return superType.isAssignableFrom(subType);
+       }
+
+       // only used when resolving 
+       public void setUpperBound(UnresolvedType aTypeX) {
+               this.upperBound = aTypeX;
+       }
+       
+       // only used when resolving
+       public void setLowerBound(UnresolvedType aTypeX) {
+               this.lowerBound = aTypeX;
+       }
+       
+       // only used when resolving
+       public void setAdditionalInterfaceBounds(UnresolvedType[] someTypeXs) {
+               this.additionalInterfaceBounds = someTypeXs;
+       }
+       
+       public String toDebugString() {
+               return getDisplayName();
+       }
+       
+       public String getDisplayName() {
+               StringBuffer ret = new StringBuffer();
+               ret.append(name);
+               if (!getFirstBound().getName().equals("java.lang.Object")) {
+                       ret.append(" extends ");
+                       ret.append(getFirstBound().getName());
+                       if (additionalInterfaceBounds != null) {
+                               for (int i = 0; i < additionalInterfaceBounds.length; i++) {
+                                       if (!getFirstBound().equals(additionalInterfaceBounds[i])) {
+                                               ret.append(" & ");
+                                               ret.append(additionalInterfaceBounds[i].getName());
+                                       }
+                               }
+                       }
+               }
+               if (lowerBound != null) {
+                       ret.append(" super ");
+                       ret.append(lowerBound.getName());
+               }
+               return ret.toString();
+       }
+       
+       // good enough approximation
+       public String toString() {
+               return "TypeVar " + getDisplayName();
+       }
+       
+       /**
+        * Return complete signature, e.g. "T extends Number" would return "T:Ljava/lang/Number;"
+        * note: MAY INCLUDE P types if bounds are parameterized types
+        */
+       public String getSignature() {
+               StringBuffer sb = new StringBuffer();
+               sb.append(name);
+               sb.append(":");
+               sb.append(upperBound.getSignature());
+               if (additionalInterfaceBounds!=null && additionalInterfaceBounds.length!=0) {
+                       sb.append(":");
+                       for (int i = 0; i < additionalInterfaceBounds.length; i++) {
+                               UnresolvedType iBound = additionalInterfaceBounds[i];
+                               sb.append(iBound.getSignature());
+                       }
+               }
+               return sb.toString();
+       }
+       
+       /**
+        * @return signature for inclusion in an attribute, there must be no 'P' in it signatures
+        */
+       public String getSignatureForAttribute() {
+               StringBuffer sb = new StringBuffer();
+               sb.append(name);
+               sb.append(":");
+               sb.append(((ResolvedType)upperBound).getSignatureForAttribute());
+               if (additionalInterfaceBounds!=null && additionalInterfaceBounds.length!=0) {
+                       sb.append(":");
+                       for (int i = 0; i < additionalInterfaceBounds.length; i++) {
+                               ResolvedType iBound = (ResolvedType)additionalInterfaceBounds[i];
+                               sb.append(iBound.getSignatureForAttribute());
+                       }
+               }
+               return sb.toString();
+       }
+
+       
+       public void setRank(int rank) {
+               this.rank=rank;
+       }
+       
+       public int getRank() {
+               return rank;
+       }
+
+       public void setDeclaringElement(TypeVariableDeclaringElement element) {
+               this.declaringElement = element;
+               if (element instanceof UnresolvedType) {
+                       this.declaringElementKind = TYPE;
+               } else {
+                       this.declaringElementKind = METHOD;
+               }
+       }
+       
+       public TypeVariableDeclaringElement getDeclaringElement() {
+               return declaringElement;
+       }
+       
+       public void setDeclaringElementKind(int kind) {
+               this.declaringElementKind = kind;
+       }
+       
+       public int getDeclaringElementKind() {
+//             if (declaringElementKind==UNKNOWN) throw new RuntimeException("Dont know declarer of this tvar : "+this);
+               return declaringElementKind;
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+       // name, upperbound, additionalInterfaceBounds, lowerbound
+               s.writeUTF(name);
+               upperBound.write(s);
+               if (additionalInterfaceBounds==null || additionalInterfaceBounds.length==0) {
+                       s.writeInt(0);
+               } else {
+                       s.writeInt(additionalInterfaceBounds.length);
+                       for (int i = 0; i < additionalInterfaceBounds.length; i++) {
+                               UnresolvedType ibound = additionalInterfaceBounds[i];
+                               ibound.write(s);
+                       }
+               }
+       }
+       
+       public static TypeVariable read(VersionedDataInputStream s) throws IOException {
+       
+               //if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
+                       
+               String name = s.readUTF();
+               UnresolvedType ubound = UnresolvedType.read(s);
+               int iboundcount = s.readInt();
+               UnresolvedType[] ibounds = UnresolvedType.NONE;
+               if (iboundcount>0) {
+                       ibounds = new UnresolvedType[iboundcount];
+                       for (int i=0; i<iboundcount; i++) {
+                               ibounds[i] = UnresolvedType.read(s);
+                       }
+               }
+               
+               TypeVariable newVariable = new TypeVariable(name,ubound,ibounds);
+               return newVariable;             
+    }
+
+       public String getGenericSignature() {
+               return "T"+name+";";
+//             return "T"+getSignature();
+       }
+       public String getErasureSignature() {
+               return getFirstBound().getErasureSignature();
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/TypeVariableDeclaringElement.java b/org.aspectj.matcher/src/org/aspectj/weaver/TypeVariableDeclaringElement.java
new file mode 100644 (file)
index 0000000..6a4a17a
--- /dev/null
@@ -0,0 +1,23 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Andy Clement                      Initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+
+/**
+ * Tag interface - methods and types can be declaring elements for
+ * type variables. See the TypeVariable class which holds onto 
+ * the declaring element
+ */
+public interface TypeVariableDeclaringElement {
+       public TypeVariable getTypeVariableNamed(String name);
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/TypeVariableReference.java b/org.aspectj.matcher/src/org/aspectj/weaver/TypeVariableReference.java
new file mode 100644 (file)
index 0000000..fc6a989
--- /dev/null
@@ -0,0 +1,22 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+/**
+ * Implemented by Types that represent references to type variables
+ *
+ */
+public interface TypeVariableReference {
+
+       TypeVariable getTypeVariable();
+       
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/TypeVariableReferenceType.java b/org.aspectj.matcher/src/org/aspectj/weaver/TypeVariableReferenceType.java
new file mode 100644 (file)
index 0000000..9a823e6
--- /dev/null
@@ -0,0 +1,146 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Represents a type variable in a type or generic method declaration
+ */
+public class TypeVariableReferenceType extends BoundedReferenceType implements TypeVariableReference {
+
+       private TypeVariable typeVariable;
+       private boolean resolvedIfBounds = false;
+       
+       // If 'fixedUp' then the type variable in here is a reference to the real one that may
+       // exist either on a member or a type.  Not fixedUp means that we unpacked a generic
+       // signature and weren't able to fix it up during resolution (didn't quite know enough
+       // at the right time).  Wonder if we can fix it up late?
+       boolean fixedUp = false;
+       
+       public TypeVariableReferenceType(
+                       TypeVariable aTypeVariable,
+                       World aWorld) {
+               super(
+                               aTypeVariable.getGenericSignature(),
+                               aTypeVariable.getErasureSignature(),
+                         aWorld);
+               this.typeVariable = aTypeVariable;
+               this.isExtends    = false;
+               this.isSuper      = false;
+       }
+       
+       public ReferenceTypeDelegate getDelegate() {
+               if (delegate==null) 
+                 setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)typeVariable.getFirstBound()));
+               return delegate;
+       }
+
+       public UnresolvedType getUpperBound() {
+               if (typeVariable==null) return super.getUpperBound();
+               return typeVariable.getUpperBound();
+       }
+       
+       public UnresolvedType getLowerBound() {
+               return typeVariable.getLowerBound();
+       }
+       
+       private void setAdditionalInterfaceBoundsFromTypeVar() {
+               if (typeVariable.getAdditionalInterfaceBounds() == null) {
+                       return;
+               } else {
+                       UnresolvedType [] ifBounds = typeVariable.getAdditionalInterfaceBounds();
+                       additionalInterfaceBounds = new ReferenceType[ifBounds.length];
+                       for (int i = 0; i < ifBounds.length; i++) {
+                               additionalInterfaceBounds[i] = (ReferenceType) ifBounds[i].resolve(getWorld()); 
+                       }
+               }
+       }
+
+       public UnresolvedType parameterize(Map typeBindings) {
+               UnresolvedType ut = (UnresolvedType) typeBindings.get(getName());
+               if (ut!=null) return world.resolve(ut);
+               return this;
+       }
+       
+       public ReferenceType[] getAdditionalBounds() {
+               if (!resolvedIfBounds) {
+                       setAdditionalInterfaceBoundsFromTypeVar();
+                       resolvedIfBounds = true;
+               }
+               return super.getAdditionalBounds();
+       }
+       
+       public TypeVariable getTypeVariable() {
+               // if (!fixedUp) throw new BCException("ARGH"); // fix it up now?
+               return typeVariable;
+       }
+       
+       public boolean isTypeVariableReference() {
+               return true;
+       }
+       
+       public String toString() {
+               return typeVariable.getName();
+       }
+       
+       public boolean isGenericWildcard() {
+               return false;
+       }
+       
+       //public ResolvedType resolve(World world) {
+       //      return super.resolve(world);
+       //}
+       
+       public boolean isAnnotation() {
+               World world = ((ReferenceType)getUpperBound()).getWorld();
+               ResolvedType annotationType = ResolvedType.ANNOTATION.resolve(world);
+               if (getUpperBound() != null && ((ReferenceType)getUpperBound()).isAnnotation()) return true;
+               ReferenceType[] ifBounds = getAdditionalBounds();
+               for (int i = 0; i < ifBounds.length; i++) {
+                       if (ifBounds[i].isAnnotation()) return true;
+                       if (ifBounds[i] == annotationType) return true; // annotation itself does not have the annotation flag set in Java!
+               }
+               return false;
+       }
+       
+       /**
+     * return the signature for a *REFERENCE* to a type variable, which is simply:
+     *   Tname;
+     * there is no bounds info included, that is in the signature of the type variable itself
+     */
+       public String getSignature() {
+         StringBuffer sb = new StringBuffer();
+         sb.append("T");
+         sb.append(typeVariable.getName());
+         sb.append(";");
+         return sb.toString();
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               super.write(s);
+//             TypeVariableDeclaringElement tvde = typeVariable.getDeclaringElement();
+//             if (tvde == null) {
+//                     s.writeInt(TypeVariable.UNKNOWN);
+//             } else {                        
+//                     s.writeInt(typeVariable.getDeclaringElementKind());
+//                     if (typeVariable.getDeclaringElementKind() == TypeVariable.TYPE) {
+//                             ((UnresolvedType)tvde).write(s);
+//                     } else if (typeVariable.getDeclaringElementKind() == TypeVariable.METHOD){
+//                             // it's a method
+//                             ((ResolvedMember)tvde).write(s);
+//                     }
+//             }
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedType.java b/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedType.java
new file mode 100644 (file)
index 0000000..0c666ca
--- /dev/null
@@ -0,0 +1,914 @@
+/* *******************************************************************
+ * Copyright (c) 2002,2005 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ *     Andy Clement  start of generics upgrade...
+ *     Adrian Colyer - overhaul
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.GenericSignature;
+import org.aspectj.util.GenericSignatureParser;
+import org.aspectj.util.GenericSignature.ClassSignature;
+import org.aspectj.weaver.tools.Traceable;
+
+/**
+ * A UnresolvedType represents a type to the weaver. It has a basic signature that knows nothing about type variables, type
+ * parameters, etc.. UnresolvedTypes are resolved in some World (a repository of types). When a UnresolvedType is resolved it turns
+ * into a ResolvedType which may be a primitive type, or a ReferenceType. ReferenceTypes may refer to simple, generic, parameterized
+ * or type-variable based reference types. A ReferenceType is backed by a delegate that provides information about the type based on
+ * some repository (currently either BCEL or an EclipseSourceType, but in the future we probably need to support java.lang.reflect
+ * based delegates too).
+ * 
+ * Every UnresolvedType has a signature, the unique key for the type in the world.
+ * 
+ * 
+ * TypeXs are fully aware of their complete type information (there is no erasure in the UnresolvedType world). To achieve this, the
+ * signature of TypeXs combines the basic Java signature and the generic signature information into one complete signature.
+ * 
+ * The format of a UnresolvedType signature is as follows:
+ * 
+ * a simple (non-generic, non-parameterized) type has the as its signature the Java signature. e.g. Ljava/lang/String;
+ * 
+ * a generic type has signature: TypeParamsOpt ClassSig SuperClassSig SuperIntfListOpt
+ * 
+ * following the Generic signature grammar in the JVM spec., but with the addition of the ClassSignature (which is not in the
+ * generic signature). In addition type variable names are replaced by a simple number which represents their declaration order in
+ * the type declaration.
+ * 
+ * e.g. public class Foo<T extends Number> would have signature: <1:Ljava/lang/Number>Lorg.xyz.Foo;Ljava/lang/Object;
+ * 
+ * A parameterized type is a distinct type in the world with its own signature following the grammar:
+ * 
+ * TypeParamsOpt ClassSig<ParamSigList>;
+ * 
+ * but with the L for the class sig replaced by "P". For example List<String> has signature
+ * 
+ * Pjava/util/List<Ljava/lang/String>;
+ * 
+ * and List<T> in the following class : class Foo<T> { List<T> lt; }
+ * 
+ * has signature: <1:>Pjava/util/List<T1;>;
+ * 
+ * A typex that represents a type variable has its own unique signature, following the grammar for a FormalTypeParameter in the JVM
+ * spec.
+ * 
+ * A generic typex has its true signature and also an erasure signature. Both of these are keys pointing to the same UnresolvedType
+ * in the world. For example List has signature:
+ * 
+ * <1:>Ljava/util/List;Ljava/lang/Object;
+ * 
+ * and the erasure signature
+ * 
+ * Ljava/util/List;
+ * 
+ * Generics wildcards introduce their own special signatures for type parameters. The wildcard ? has signature * The wildcard ?
+ * extends Foo has signature +LFoo; The wildcard ? super Foo has signature -LFoo;
+ */
+public class UnresolvedType implements Traceable, TypeVariableDeclaringElement {
+
+       // common types referred to by the weaver
+       public static final UnresolvedType[] NONE = new UnresolvedType[0];
+       public static final UnresolvedType OBJECT = forSignature("Ljava/lang/Object;");
+       public static final UnresolvedType OBJECTARRAY = forSignature("[Ljava/lang/Object;");
+       public static final UnresolvedType CLONEABLE = forSignature("Ljava/lang/Cloneable;");
+       public static final UnresolvedType SERIALIZABLE = forSignature("Ljava/io/Serializable;");
+       public static final UnresolvedType THROWABLE = forSignature("Ljava/lang/Throwable;");
+       public static final UnresolvedType RUNTIME_EXCEPTION = forSignature("Ljava/lang/RuntimeException;");
+       public static final UnresolvedType ERROR = forSignature("Ljava/lang/Error;");
+       public static final UnresolvedType AT_INHERITED = forSignature("Ljava/lang/annotation/Inherited;");
+       public static final UnresolvedType AT_RETENTION = forSignature("Ljava/lang/annotation/Retention;");
+       public static final UnresolvedType ENUM = forSignature("Ljava/lang/Enum;");
+       public static final UnresolvedType ANNOTATION = forSignature("Ljava/lang/annotation/Annotation;");
+       public static final UnresolvedType JAVA_LANG_CLASS = forSignature("Ljava/lang/Class;");
+       public static final UnresolvedType JAVA_LANG_CLASS_ARRAY = forSignature("[Ljava/lang/Class;");
+       public static final UnresolvedType JAVA_LANG_STRING = forSignature("Ljava/lang/String;");
+       public static final UnresolvedType JAVA_LANG_EXCEPTION = forSignature("Ljava/lang/Exception;");
+       public static final UnresolvedType JAVA_LANG_REFLECT_METHOD = forSignature("Ljava/lang/reflect/Method;");
+       public static final UnresolvedType JAVA_LANG_ANNOTATION = UnresolvedType.forSignature("Ljava.lang.annotation.Annotation;");
+       public static final UnresolvedType SUPPRESS_AJ_WARNINGS = forSignature("Lorg/aspectj/lang/annotation/SuppressAjWarnings;");
+       public static final UnresolvedType AT_TARGET = forSignature("Ljava/lang/annotation/Target;");
+       public static final UnresolvedType SOMETHING = new UnresolvedType("?");
+       public static final UnresolvedType[] ARRAY_WITH_JUST_OBJECT = new UnresolvedType[] { OBJECT };
+       public static final UnresolvedType JOINPOINT_STATICPART = forSignature("Lorg/aspectj/lang/JoinPoint$StaticPart;");
+       public static final UnresolvedType JOINPOINT_ENCLOSINGSTATICPART = forSignature("Lorg/aspectj/lang/JoinPoint$EnclosingStaticPart;");
+
+       // this doesn't belong here and will get moved to ResolvedType later in the refactoring
+       public static final String MISSING_NAME = "@missing@";
+
+       // OPTIMIZE I dont think you can ask something unresolved what kind of type it is, how can it always know? Push down into
+       // resolvedtype
+       // that will force references to resolvedtypes to be correct rather than relying on unresolvedtypes to answer questions
+       protected TypeKind typeKind = TypeKind.SIMPLE; // what kind of type am I?
+
+       /**
+        * THE SIGNATURE - see the comments above for how this is defined
+        */
+       protected String signature;
+
+       /**
+        * The erasure of the signature. Contains only the Java signature of the type with all supertype, superinterface, type variable,
+        * and parameter information removed.
+        */
+       protected String signatureErasure;
+
+       /**
+        * Iff isParameterized(), then these are the type parameters
+        */
+       protected UnresolvedType[] typeParameters;
+
+       /**
+        * Iff isGeneric(), then these are the type variables declared on the type Iff isParameterized(), then these are the type
+        * variables bound as parameters in the type
+        */
+       // OPTIMIZE should be no state in here that will damage whether equals() is correct...
+       protected TypeVariable[] typeVariables;
+
+       public boolean isPrimitiveType() {
+               return typeKind == TypeKind.PRIMITIVE;
+       }
+
+       public boolean isSimpleType() {
+               return typeKind == TypeKind.SIMPLE;
+       }
+
+       public boolean isRawType() {
+               return typeKind == TypeKind.RAW;
+       }
+
+       public boolean isGenericType() {
+               return typeKind == TypeKind.GENERIC;
+       }
+
+       public boolean isParameterizedType() {
+               return typeKind == TypeKind.PARAMETERIZED;
+       }
+
+       public boolean isTypeVariableReference() {
+               return typeKind == TypeKind.TYPE_VARIABLE;
+       }
+
+       public boolean isGenericWildcard() {
+               return typeKind == TypeKind.WILDCARD;
+       }
+
+       public TypeKind getTypekind() {
+               return typeKind;
+       }
+
+       // for any reference type, we can get some extra information...
+       public final boolean isArray() {
+               return signature.length() > 0 && signature.charAt(0) == '[';
+       }
+
+       /**
+        * Equality is checked based on the underlying signature. {@link ResolvedType} objects' equals is by reference.
+        */
+       public boolean equals(Object other) {
+               if (!(other instanceof UnresolvedType))
+                       return false;
+               return signature.equals(((UnresolvedType) other).signature);
+       }
+
+       /**
+        * Equality is checked based on the underlying signature, so the hash code of a particular type is the hash code of its
+        * signature string.
+        */
+       public final int hashCode() {
+               return signature.hashCode();
+       }
+
+       protected UnresolvedType(String signature) {
+               this.signature = signature;
+               this.signatureErasure = signature;
+       }
+
+       protected UnresolvedType(String signature, String signatureErasure) {
+               this.signature = signature;
+               this.signatureErasure = signatureErasure;
+       }
+
+       // called from TypeFactory
+       public UnresolvedType(String signature, String signatureErasure, UnresolvedType[] typeParams) {
+               this.signature = signature;
+               this.signatureErasure = signatureErasure;
+               this.typeParameters = typeParams;
+               if (typeParams != null)
+                       this.typeKind = TypeKind.PARAMETERIZED;
+       }
+
+       // ---- Things we can do without a world
+
+       /**
+        * This is the size of this type as used in JVM.
+        */
+       public int getSize() {
+               return 1;
+       }
+
+       public static UnresolvedType makeArray(UnresolvedType base, int dims) {
+               StringBuffer sig = new StringBuffer();
+               for (int i = 0; i < dims; i++)
+                       sig.append("[");
+               sig.append(base.getSignature());
+               return UnresolvedType.forSignature(sig.toString());
+       }
+
+       /**
+        * NOTE: Use forSignature() if you can, it'll be cheaper ! Constructs a UnresolvedType for a java language type name. For
+        * example:
+        * 
+        * <blockquote>
+        * 
+        * <pre>
+        *   UnresolvedType.forName(&quot;java.lang.Thread[]&quot;)
+        *   UnresolvedType.forName(&quot;int&quot;)
+        * </pre>
+        * 
+        * </blockquote>
+        * 
+        * Types may equivalently be produced by this or by {@link #forSignature(String)}.
+        * 
+        * <blockquote>
+        * 
+        * <pre>
+        *   UnresolvedType.forName(&quot;java.lang.Thread[]&quot;).equals(Type.forSignature(&quot;[Ljava/lang/Thread;&quot;)
+        *   UnresolvedType.forName(&quot;int&quot;).equals(Type.forSignature(&quot;I&quot;))
+        * </pre>
+        * 
+        * </blockquote>
+        * 
+        * @param name the java language type name in question.
+        * @return a type object representing that java language type.
+        */
+       // OPTIMIZE change users of this to use forSignature, especially for simple cases
+       public static UnresolvedType forName(String name) {
+               return forSignature(nameToSignature(name));
+       }
+
+       /**
+        * Constructs a UnresolvedType for each java language type name in an incoming array.
+        * 
+        * @param names an array of java language type names.
+        * @return an array of UnresolvedType objects.
+        * @see #forName(String)
+        */
+       public static UnresolvedType[] forNames(String[] names) {
+               UnresolvedType[] ret = new UnresolvedType[names.length];
+               for (int i = 0, len = names.length; i < len; i++) {
+                       ret[i] = UnresolvedType.forName(names[i]);
+               }
+               return ret;
+       }
+
+       public static UnresolvedType forGenericType(String name, TypeVariable[] tvbs, String genericSig) {
+               // TODO asc generics needs a declared sig
+               String sig = nameToSignature(name);
+               UnresolvedType ret = UnresolvedType.forSignature(sig);
+               ret.typeKind = TypeKind.GENERIC;
+               ret.typeVariables = tvbs;
+               ret.signatureErasure = sig;
+               return ret;
+       }
+
+       public static UnresolvedType forGenericTypeSignature(String sig, String declaredGenericSig) {
+               UnresolvedType ret = UnresolvedType.forSignature(sig);
+               ret.typeKind = TypeKind.GENERIC;
+
+               ClassSignature csig = new GenericSignatureParser().parseAsClassSignature(declaredGenericSig);
+
+               GenericSignature.FormalTypeParameter[] ftps = csig.formalTypeParameters;
+               ret.typeVariables = new TypeVariable[ftps.length];
+               for (int i = 0; i < ftps.length; i++) {
+                       GenericSignature.FormalTypeParameter parameter = ftps[i];
+                       if (parameter.classBound instanceof GenericSignature.ClassTypeSignature) {
+                               GenericSignature.ClassTypeSignature cts = (GenericSignature.ClassTypeSignature) parameter.classBound;
+                               ret.typeVariables[i] = new TypeVariable(ftps[i].identifier, UnresolvedType.forSignature(cts.outerType.identifier
+                                               + ";"));
+                       } else if (parameter.classBound instanceof GenericSignature.TypeVariableSignature) {
+                               GenericSignature.TypeVariableSignature tvs = (GenericSignature.TypeVariableSignature) parameter.classBound;
+                               UnresolvedTypeVariableReferenceType utvrt = new UnresolvedTypeVariableReferenceType(new TypeVariable(
+                                               tvs.typeVariableName));
+                               ret.typeVariables[i] = new TypeVariable(ftps[i].identifier, utvrt);
+                       } else {
+                               throw new BCException(
+                                               "UnresolvedType.forGenericTypeSignature(): Do not know how to process type variable bound of type '"
+                                                               + parameter.classBound.getClass() + "'.  Full signature is '" + sig + "'");
+                       }
+               }
+               ret.signatureErasure = sig;
+               ret.signature = ret.signatureErasure;
+               return ret;
+       }
+
+       public static UnresolvedType forGenericTypeVariables(String sig, TypeVariable[] tVars) {
+               UnresolvedType ret = UnresolvedType.forSignature(sig);
+               ret.typeKind = TypeKind.GENERIC;
+               ret.typeVariables = tVars;
+               ret.signatureErasure = sig;
+               ret.signature = ret.signatureErasure;
+               return ret;
+       }
+
+       public static UnresolvedType forRawTypeName(String name) {
+               UnresolvedType ret = UnresolvedType.forName(name);
+               ret.typeKind = TypeKind.RAW;
+               return ret;
+       }
+
+       /**
+        * Creates a new type array with a fresh type appended to the end.
+        * 
+        * @param types the left hand side of the new array
+        * @param end the right hand side of the new array
+        */
+       public static UnresolvedType[] add(UnresolvedType[] types, UnresolvedType end) {
+               int len = types.length;
+               UnresolvedType[] ret = new UnresolvedType[len + 1];
+               System.arraycopy(types, 0, ret, 0, len);
+               ret[len] = end;
+               return ret;
+       }
+
+       /**
+        * Creates a new type array with a fresh type inserted at the beginning.
+        * 
+        * 
+        * @param start the left hand side of the new array
+        * @param types the right hand side of the new array
+        */
+       public static UnresolvedType[] insert(UnresolvedType start, UnresolvedType[] types) {
+               int len = types.length;
+               UnresolvedType[] ret = new UnresolvedType[len + 1];
+               ret[0] = start;
+               System.arraycopy(types, 0, ret, 1, len);
+               return ret;
+       }
+
+       /**
+        * Constructs a Type for a JVM bytecode signature string. For example:
+        * 
+        * <blockquote>
+        * 
+        * <pre>
+        *   UnresolvedType.forSignature(&quot;[Ljava/lang/Thread;&quot;)
+        *   UnresolvedType.forSignature(&quot;I&quot;);
+        * </pre>
+        * 
+        * </blockquote>
+        * 
+        * Types may equivalently be produced by this or by {@link #forName(String)}.
+        * 
+        * <blockquote>
+        * 
+        * <pre>
+        *   UnresolvedType.forName(&quot;java.lang.Thread[]&quot;).equals(Type.forSignature(&quot;[Ljava/lang/Thread;&quot;)
+        *   UnresolvedType.forName(&quot;int&quot;).equals(Type.forSignature(&quot;I&quot;))
+        * </pre>
+        * 
+        * </blockquote>
+        * 
+        * @param signature the JVM bytecode signature string for the desired type.
+        * @return a type object represnting that JVM bytecode signature.
+        */
+       public static UnresolvedType forSignature(String signature) {
+               switch (signature.charAt(0)) {
+               case 'B':
+                       return ResolvedType.BYTE;
+               case 'C':
+                       return ResolvedType.CHAR;
+               case 'D':
+                       return ResolvedType.DOUBLE;
+               case 'F':
+                       return ResolvedType.FLOAT;
+               case 'I':
+                       return ResolvedType.INT;
+               case 'J':
+                       return ResolvedType.LONG;
+               case 'L':
+                       return TypeFactory.createTypeFromSignature(signature);
+               case 'P':
+                       return TypeFactory.createTypeFromSignature(signature);
+               case 'S':
+                       return ResolvedType.SHORT;
+               case 'V':
+                       return ResolvedType.VOID;
+               case 'Z':
+                       return ResolvedType.BOOLEAN;
+               case '[':
+                       return TypeFactory.createTypeFromSignature(signature);
+               case '+':
+                       return TypeFactory.createTypeFromSignature(signature);
+               case '-':
+                       return TypeFactory.createTypeFromSignature(signature);
+               case '?':
+                       return TypeFactory.createTypeFromSignature(signature);
+               case 'T':
+                       return TypeFactory.createTypeFromSignature(signature);
+               default:
+                       throw new BCException("Bad type signature " + signature);
+               }
+       }
+
+       /**
+        * Constructs a UnresolvedType for each JVM bytecode type signature in an incoming array.
+        * 
+        * @param names an array of JVM bytecode type signatures
+        * @return an array of UnresolvedType objects.
+        * @see #forSignature(String)
+        */
+       public static UnresolvedType[] forSignatures(String[] sigs) {
+               UnresolvedType[] ret = new UnresolvedType[sigs.length];
+               for (int i = 0, len = sigs.length; i < len; i++) {
+                       ret[i] = UnresolvedType.forSignature(sigs[i]);
+               }
+               return ret;
+       }
+
+       /**
+        * Returns the name of this type in java language form (e.g. java.lang.Thread or boolean[]). This produces a more aesthetically
+        * pleasing string than {@link java.lang.Class#getName()}.
+        * 
+        * @return the java language name of this type.
+        */
+       public String getName() {
+               return signatureToName(signature);
+       }
+
+       public String getSimpleName() {
+               String name = getRawName();
+               int lastDot = name.lastIndexOf('.');
+               if (lastDot != -1) {
+                       name = name.substring(lastDot + 1);
+               }
+               if (isParameterizedType()) {
+                       StringBuffer sb = new StringBuffer(name);
+                       sb.append("<");
+                       for (int i = 0; i < (typeParameters.length - 1); i++) {
+                               sb.append(typeParameters[i].getSimpleName());
+                               sb.append(",");
+                       }
+                       sb.append(typeParameters[typeParameters.length - 1].getSimpleName());
+                       sb.append(">");
+                       name = sb.toString();
+               }
+               return name;
+       }
+
+       public String getRawName() {
+               return signatureToName((signatureErasure == null ? signature : signatureErasure));
+       }
+
+       public String getBaseName() {
+               String name = getName();
+               if (isParameterizedType() || isGenericType()) {
+                       if (typeParameters == null)
+                               return name;
+                       else
+                               return name.substring(0, name.indexOf("<"));
+               } else {
+                       return name;
+               }
+       }
+
+       public String getSimpleBaseName() {
+               String name = getBaseName();
+               int lastDot = name.lastIndexOf('.');
+               if (lastDot != -1) {
+                       name = name.substring(lastDot + 1);
+               }
+               return name;
+       }
+
+       /**
+        * Returns an array of strings representing the java langauge names of an array of types.
+        * 
+        * @param types an array of UnresolvedType objects
+        * @return an array of Strings fo the java language names of types.
+        * @see #getName()
+        */
+       public static String[] getNames(UnresolvedType[] types) {
+               String[] ret = new String[types.length];
+               for (int i = 0, len = types.length; i < len; i++) {
+                       ret[i] = types[i].getName();
+               }
+               return ret;
+       }
+
+       /**
+        * Returns the name of this type in JVM signature form. For all UnresolvedType t:
+        * 
+        * <blockquote>
+        * 
+        * <pre>
+        * UnresolvedType.forSignature(t.getSignature()).equals(t)
+        * </pre>
+        * 
+        * </blockquote>
+        * 
+        * and for all String s where s is a lexically valid JVM type signature string:
+        * 
+        * <blockquote>
+        * 
+        * <pre>
+        * UnresolvedType.forSignature(s).getSignature().equals(s)
+        * </pre>
+        * 
+        * </blockquote>
+        * 
+        * @return the java JVM signature string for this type.
+        */
+       public String getSignature() {
+               return signature;
+       }
+
+       /**
+        * For parameterized types, return the signature for the raw type
+        */
+       public String getErasureSignature() {
+               if (signatureErasure == null)
+                       return signature;
+               return signatureErasure;
+       }
+
+       private boolean needsModifiableDelegate = false;
+
+       public boolean needsModifiableDelegate() {
+               return needsModifiableDelegate;
+       }
+
+       public void setNeedsModifiableDelegate(boolean b) {
+               this.needsModifiableDelegate = b;
+       }
+
+       public UnresolvedType getRawType() {
+               return UnresolvedType.forSignature(getErasureSignature());
+       }
+
+       /**
+        * Returns a UnresolvedType object representing the effective outermost enclosing type for a name type. For all other types,
+        * this will return the type itself.
+        * 
+        * The only guarantee is given in JLS 13.1 where code generated according to those rules will have type names that can be split
+        * apart in this way.
+        * 
+        * @return the outermost enclosing UnresolvedType object or this.
+        */
+       public UnresolvedType getOutermostType() {
+               if (isArray() || isPrimitiveType())
+                       return this;
+               String sig = getErasureSignature();
+               int dollar = sig.indexOf('$');
+               if (dollar != -1) {
+                       return UnresolvedType.forSignature(sig.substring(0, dollar) + ';');
+               } else {
+                       return this;
+               }
+       }
+
+       /**
+        * Returns a UnresolvedType object representing the component type of this array, or null if this type does not represent an
+        * array type.
+        * 
+        * @return the component UnresolvedType object, or null.
+        */
+       public UnresolvedType getComponentType() {
+               if (isArray()) {
+                       return forSignature(signature.substring(1));
+               } else {
+                       return null;
+               }
+       }
+
+       /**
+        * Returns a java language string representation of this type.
+        */
+       public String toString() {
+               return getName(); // + " - " + getKind();
+       }
+
+       public String toDebugString() {
+               return getName();
+       }
+
+       // ---- requires worlds
+
+       /**
+        * Returns a resolved version of this type according to a particular world.
+        * 
+        * @param world thie {@link World} within which to resolve.
+        * @return a resolved type representing this type in the appropriate world.
+        */
+       public ResolvedType resolve(World world) {
+               return world.resolve(this);
+       }
+
+       // ---- helpers
+
+       private static String signatureToName(String signature) {
+               switch (signature.charAt(0)) {
+               case 'B':
+                       return "byte";
+               case 'C':
+                       return "char";
+               case 'D':
+                       return "double";
+               case 'F':
+                       return "float";
+               case 'I':
+                       return "int";
+               case 'J':
+                       return "long";
+               case 'L':
+                       String name = signature.substring(1, signature.length() - 1).replace('/', '.');
+                       return name;
+               case 'T':
+                       StringBuffer nameBuff2 = new StringBuffer();
+                       int colon = signature.indexOf(";");
+                       String tvarName = signature.substring(1, colon);
+                       nameBuff2.append(tvarName);
+                       return nameBuff2.toString();
+               case 'P': // it's one of our parameterized type sigs
+                       StringBuffer nameBuff = new StringBuffer();
+                       // signature for parameterized types is e.g.
+                       // List<String> -> Ljava/util/List<Ljava/lang/String;>;
+                       // Map<String,List<Integer>> -> Ljava/util/Map<java/lang/String;Ljava/util/List<Ljava/lang/Integer;>;>;
+                       int paramNestLevel = 0;
+                       for (int i = 1; i < signature.length(); i++) {
+                               char c = signature.charAt(i);
+                               switch (c) {
+                               case '/':
+                                       nameBuff.append('.');
+                                       break;
+                               case '<':
+                                       nameBuff.append("<");
+                                       paramNestLevel++;
+                                       StringBuffer innerBuff = new StringBuffer();
+                                       while (paramNestLevel > 0) {
+                                               c = signature.charAt(++i);
+                                               if (c == '<')
+                                                       paramNestLevel++;
+                                               if (c == '>')
+                                                       paramNestLevel--;
+                                               if (paramNestLevel > 0)
+                                                       innerBuff.append(c);
+                                               if (c == ';' && paramNestLevel == 1) {
+                                                       nameBuff.append(signatureToName(innerBuff.toString()));
+                                                       if (signature.charAt(i + 1) != '>')
+                                                               nameBuff.append(',');
+                                                       innerBuff = new StringBuffer();
+                                               }
+                                       }
+                                       nameBuff.append(">");
+                                       break;
+                               case ';':
+                                       break;
+                               default:
+                                       nameBuff.append(c);
+                               }
+                       }
+                       return nameBuff.toString();
+               case 'S':
+                       return "short";
+               case 'V':
+                       return "void";
+               case 'Z':
+                       return "boolean";
+               case '[':
+                       return signatureToName(signature.substring(1, signature.length())) + "[]";
+                       // case '<':
+                       // // its a generic!
+                       // if (signature.charAt(1)=='>') return signatureToName(signature.substring(2));
+               case '+':
+                       return "? extends " + signatureToName(signature.substring(1, signature.length()));
+               case '-':
+                       return "? super " + signatureToName(signature.substring(1, signature.length()));
+               case '*':
+                       return "?";
+               default:
+                       throw new BCException("Bad type signature: " + signature);
+               }
+       }
+
+       private static String nameToSignature(String name) {
+               if (name.equals("byte"))
+                       return "B";
+               if (name.equals("char"))
+                       return "C";
+               if (name.equals("double"))
+                       return "D";
+               if (name.equals("float"))
+                       return "F";
+               if (name.equals("int"))
+                       return "I";
+               if (name.equals("long"))
+                       return "J";
+               if (name.equals("short"))
+                       return "S";
+               if (name.equals("boolean"))
+                       return "Z";
+               if (name.equals("void"))
+                       return "V";
+               if (name.equals("?"))
+                       return name;
+               if (name.endsWith("[]"))
+                       return "[" + nameToSignature(name.substring(0, name.length() - 2));
+               if (name.length() != 0) {
+                       // lots more tests could be made here...
+
+                       // check if someone is calling us with something that is a signature already
+                       if (name.charAt(0) == '[') {
+                               throw new BCException("Do not call nameToSignature with something that looks like a signature (descriptor): '"
+                                               + name + "'");
+                       }
+
+                       if (name.indexOf("<") == -1) {
+                               // not parameterised
+                               return "L" + name.replace('.', '/') + ";";
+                       } else {
+                               StringBuffer nameBuff = new StringBuffer();
+                               int nestLevel = 0;
+                               nameBuff.append("P");
+                               for (int i = 0; i < name.length(); i++) {
+                                       char c = name.charAt(i);
+                                       switch (c) {
+                                       case '.':
+                                               nameBuff.append('/');
+                                               break;
+                                       case '<':
+                                               nameBuff.append("<");
+                                               nestLevel++;
+                                               StringBuffer innerBuff = new StringBuffer();
+                                               while (nestLevel > 0) {
+                                                       c = name.charAt(++i);
+                                                       if (c == '<')
+                                                               nestLevel++;
+                                                       if (c == '>')
+                                                               nestLevel--;
+                                                       if (c == ',' && nestLevel == 1) {
+                                                               nameBuff.append(nameToSignature(innerBuff.toString()));
+                                                               innerBuff = new StringBuffer();
+                                                       } else {
+                                                               if (nestLevel > 0)
+                                                                       innerBuff.append(c);
+                                                       }
+                                               }
+                                               nameBuff.append(nameToSignature(innerBuff.toString()));
+                                               nameBuff.append('>');
+                                               break;
+                                       case '>':
+                                               throw new IllegalStateException("Should by matched by <");
+                                       case ',':
+                                               throw new IllegalStateException("Should only happen inside <...>");
+                                       default:
+                                               nameBuff.append(c);
+                                       }
+                               }
+                               nameBuff.append(";");
+                               return nameBuff.toString();
+                       }
+               } else
+                       throw new BCException("Bad type name: " + name);
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeUTF(getSignature());
+       }
+
+       public static UnresolvedType read(DataInputStream s) throws IOException {
+               String sig = s.readUTF();
+               if (sig.equals(MISSING_NAME)) {
+                       return ResolvedType.MISSING;
+               } else {
+                       UnresolvedType ret = UnresolvedType.forSignature(sig);
+                       return ret;
+               }
+       }
+
+       public static void writeArray(UnresolvedType[] types, DataOutputStream s) throws IOException {
+               int len = types.length;
+               s.writeShort(len);
+               for (int i = 0; i < len; i++) {
+                       types[i].write(s);
+               }
+       }
+
+       public static UnresolvedType[] readArray(DataInputStream s) throws IOException {
+               int len = s.readShort();
+               if (len == 0)
+                       return UnresolvedType.NONE;
+               UnresolvedType[] types = new UnresolvedType[len];
+               for (int i = 0; i < len; i++) {
+                       types[i] = UnresolvedType.read(s);
+               }
+               return types;
+       }
+
+       public String getNameAsIdentifier() {
+               return getName().replace('.', '_');
+       }
+
+       public String getPackageNameAsIdentifier() {
+               String name = getName();
+               int index = name.lastIndexOf('.');
+               if (index == -1) {
+                       return "";
+               } else {
+                       return name.substring(0, index).replace('.', '_');
+               }
+       }
+
+       public String getPackageName() {
+               String name = getName();
+               if (name.indexOf("<") != -1) {
+                       name = name.substring(0, name.indexOf("<"));
+               }
+               int index = name.lastIndexOf('.');
+               if (index == -1) {
+                       return "";
+               } else {
+                       return name.substring(0, index);
+               }
+       }
+
+       public UnresolvedType[] getTypeParameters() {
+               return typeParameters == null ? UnresolvedType.NONE : typeParameters;
+       }
+
+       /**
+        * Doesn't include the package
+        */
+       public String getClassName() {
+               String name = getName();
+               int index = name.lastIndexOf('.');
+               if (index == -1) {
+                       return name;
+               } else {
+                       return name.substring(index + 1);
+               }
+       }
+
+       public TypeVariable[] getTypeVariables() {
+               return typeVariables;
+       }
+
+       public static class TypeKind {
+               // Note: It is not sufficient to say that a parameterized type with no type parameters in fact
+               // represents a raw type - a parameterized type with no type parameters can represent
+               // an inner type of a parameterized type that specifies no type parameters of its own.
+               public final static TypeKind PRIMITIVE = new TypeKind("primitive");
+               public final static TypeKind SIMPLE = new TypeKind("simple"); // a type with NO type parameters/vars
+               public final static TypeKind RAW = new TypeKind("raw"); // the erasure of a generic type
+               public final static TypeKind GENERIC = new TypeKind("generic"); // a generic type
+               public final static TypeKind PARAMETERIZED = new TypeKind("parameterized"); // a parameterized type
+               public final static TypeKind TYPE_VARIABLE = new TypeKind("type_variable"); // a type variable
+               public final static TypeKind WILDCARD = new TypeKind("wildcard"); // a generic wildcard type
+
+               public String toString() {
+                       return type;
+               }
+
+               private TypeKind(String type) {
+                       this.type = type;
+               }
+
+               private final String type;
+       }
+
+       public TypeVariable getTypeVariableNamed(String name) {
+               TypeVariable[] vars = getTypeVariables();
+               if (vars == null || vars.length == 0)
+                       return null;
+               for (int i = 0; i < vars.length; i++) {
+                       TypeVariable aVar = vars[i];
+                       if (aVar.getName().equals(name))
+                               return aVar;
+               }
+               return null;
+       }
+
+       public String toTraceString() {
+               return getClass().getName() + "[" + getName() + "]";
+       }
+
+       /**
+        * Return a version of this parameterized type in which any type parameters that are type variable references are replaced by
+        * their matching type variable binding.
+        */
+       // OPTIMIZE methods like this just allow callers to be lazy and not ensure they are working with the right (resolved) subtype
+       public UnresolvedType parameterize(Map typeBindings) {
+               throw new UnsupportedOperationException("unable to parameterize unresolved type: " + signature);
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java b/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java
new file mode 100644 (file)
index 0000000..d6486b5
--- /dev/null
@@ -0,0 +1,102 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * @author colyer
+ * Represents a type variable encountered in the Eclipse Source world,
+ * which when resolved will turn into a TypeVariableReferenceType
+ */
+public class UnresolvedTypeVariableReferenceType extends UnresolvedType implements TypeVariableReference {
+
+       private TypeVariable typeVariable;
+       
+       // constructor used as place-holder when dealing with circular refs such as Enum
+       public UnresolvedTypeVariableReferenceType() {
+               super("Ljava/lang/Object;");
+       }
+       
+       public UnresolvedTypeVariableReferenceType(TypeVariable aTypeVariable) {
+               super(aTypeVariable.getFirstBound().getSignature());
+               this.typeVariable = aTypeVariable;
+       }
+       
+       // only used when resolving circular refs...
+       public void setTypeVariable(TypeVariable aTypeVariable) {
+               this.signature = "T" + aTypeVariable.getName() + ";"; //aTypeVariable.getUpperBound().getSignature();
+               this.typeVariable = aTypeVariable;
+               this.typeKind=TypeKind.TYPE_VARIABLE;
+       }
+       
+       public ResolvedType resolve(World world) {
+               TypeVariableDeclaringElement typeVariableScope = world.getTypeVariableLookupScope();
+               TypeVariable resolvedTypeVariable = null;
+               TypeVariableReferenceType tvrt    = null;
+               if (typeVariableScope == null) {
+                       // throw new BCException("There is no scope in which to lookup type variables!");
+                       // FIXME asc correct thing to do is go bang, but to limp along, lets cope with the scope missing
+                       resolvedTypeVariable = typeVariable.resolve(world);
+                       tvrt = new TypeVariableReferenceType(resolvedTypeVariable,world);
+               } else {
+                   boolean foundOK = false;
+                       resolvedTypeVariable = typeVariableScope.getTypeVariableNamed(typeVariable.getName());
+                       // FIXME asc remove this when the shared type var stuff is sorted
+                       if (resolvedTypeVariable == null) {
+                               resolvedTypeVariable = typeVariable.resolve(world);
+                       } else {
+                         foundOK = true;
+                       }
+                       tvrt = new TypeVariableReferenceType(resolvedTypeVariable,world);
+                       tvrt.fixedUp = foundOK;
+               }
+               
+               return tvrt;
+       }
+       
+       
+       public boolean isTypeVariableReference() {
+               return true;
+       }
+       
+       public TypeVariable getTypeVariable() {
+               return typeVariable;
+       }
+
+//     public String getName() {
+//             if (typeVariable == null) return "<type variable not set!>";
+//             return typeVariable.getDisplayName();
+//     }
+       
+       public String toString() {
+               if (typeVariable == null) {
+                       return "<type variable not set!>";
+               } else {
+                       return "T" + typeVariable.getName() + ";";
+               }
+       }
+       
+       public String toDebugString() {
+               return typeVariable.getName();
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               super.write(s);
+       }
+
+       public String getErasureSignature() {
+               return typeVariable.getFirstBound().getSignature();
+       }
+       
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Utils.java b/org.aspectj.matcher/src/org/aspectj/weaver/Utils.java
new file mode 100644 (file)
index 0000000..8053af0
--- /dev/null
@@ -0,0 +1,43 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+/**
+ * 
+ * @author Andy Clement
+ */
+public class Utils {
+
+       /**
+        * Check if the annotations contain a SuppressAjWarnings annotation and if that annotation specifies that the given lint message
+        * (identified by its key) should be ignored.
+        * 
+        */
+       public static boolean isSuppressing(AnnotationAJ[] anns, String lintkey) {
+               if (anns == null) {
+                       return false;
+               }
+               // Go through the annotation types on the advice
+               for (int i = 0; i < anns.length; i++) {
+                       if (UnresolvedType.SUPPRESS_AJ_WARNINGS.getSignature().equals(anns[i].getTypeSignature())) {
+                               // Two possibilities:
+                               // 1. there are no values specified (i.e. @SuppressAjWarnings)
+                               // 2. there are values specified (i.e. @SuppressAjWarnings("A") or @SuppressAjWarnings({"A","B"})
+                               String value = anns[i].getStringFormOfValue("value");
+                               // Slightly lazy, just doing a string indexof
+                               if (value == null || value.indexOf(lintkey) != -1) {
+                                       return true;
+                               }
+                       }
+               }
+               return false;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/VersionedDataInputStream.java b/org.aspectj.matcher/src/org/aspectj/weaver/VersionedDataInputStream.java
new file mode 100644 (file)
index 0000000..f31723b
--- /dev/null
@@ -0,0 +1,32 @@
+/* *******************************************************************
+ * Copyright (c) 2005 IBM
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement           initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver;    
+
+import java.io.DataInputStream;
+import java.io.InputStream;
+
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
+
+/**
+ * Lightweight subclass of DataInputStream that knows what version of the weaver was used to construct the data in it.
+ */
+public class VersionedDataInputStream extends DataInputStream {
+       private WeaverVersionInfo version = new WeaverVersionInfo();// assume we are the latest unless something tells us otherwise...
+       public VersionedDataInputStream(InputStream is) { super(is); }
+       
+       public int getMajorVersion() { return version.getMajorVersion(); }
+       public int getMinorVersion() { return version.getMinorVersion(); }
+       public long getBuildstamp() { return version.getBuildstamp(); }
+       
+       public void setVersion(WeaverVersionInfo version) { this.version = version; }
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/WeakClassLoaderReference.java b/org.aspectj.matcher/src/org/aspectj/weaver/WeakClassLoaderReference.java
new file mode 100644 (file)
index 0000000..bcf6502
--- /dev/null
@@ -0,0 +1,63 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement     initial implementation 
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Wraps a reference to a classloader inside a WeakReference. This should be used where we do not want the existence of a
+ * classloader reference to prevent garbage collection of that classloader (and possibly an associated weaver instance in the case
+ * of load time weaving).
+ * <p>
+ * In more detail:<br>
+ * When load time weaving, the class Aj maintains a WeakHashMap from the classloader instance to a weaver instance. The aim is that
+ * the weaver is around as long as the classloader is and should the classloader be dereferenced then the weaver can also be garbage
+ * collected. The problem is that if there are many references to the classloader from within the weaver, these are considered hard
+ * references and cause the classloader to be long lived - even if the user of the classloader has dereferenced it in their code.
+ * The solution is that the weaver should use instances of WeakClassLoaderReference objects - so that when the users hard reference
+ * to the classloader goes, nothing in the weaver will cause it to hang around. There is a big assertion here that the
+ * WeakClassLoaderReference instances will not 'lose' their ClassLoader references until the top level ClassLoader reference is
+ * null'd. This means there is no need to check for the null case on get() in this WeakReference logic below, because we shouldn't
+ * be using this weaver if its associated ClassLoader has been collected. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=210470
+ * 
+ * 
+ * @author Andy Clement
+ */
+public class WeakClassLoaderReference {
+
+       protected final int hashcode;
+
+       private final WeakReference loaderRef;
+
+       public WeakClassLoaderReference(ClassLoader loader) {
+               loaderRef = new WeakReference(loader);
+               hashcode = loader.hashCode() * 37;
+       }
+
+       public ClassLoader getClassLoader() {
+               ClassLoader instance = (ClassLoader) loaderRef.get();
+               // Assert instance!=null
+               return instance;
+       }
+
+       public boolean equals(Object obj) {
+               if (!(obj instanceof WeakClassLoaderReference))
+                       return false;
+               WeakClassLoaderReference other = (WeakClassLoaderReference) obj;
+               return (other.hashcode == hashcode);
+       }
+
+       public int hashCode() {
+               return hashcode;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/WeaverMessages.java b/org.aspectj.matcher/src/org/aspectj/weaver/WeaverMessages.java
new file mode 100644 (file)
index 0000000..5e86794
--- /dev/null
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.weaver;
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+
+public class WeaverMessages {
+       
+       private static ResourceBundle bundle = ResourceBundle.getBundle("org.aspectj.weaver.weaver-messages");
+
+       public static final String ARGS_IN_DECLARE = "argsInDeclare";
+       public static final String CFLOW_IN_DECLARE = "cflowInDeclare";
+       public static final String IF_IN_DECLARE = "ifInDeclare";
+       public static final String THIS_OR_TARGET_IN_DECLARE = "thisOrTargetInDeclare";
+       public static final String ABSTRACT_POINTCUT = "abstractPointcut";
+       public static final String POINCUT_NOT_CONCRETE = "abstractPointcutNotMadeConcrete";
+       public static final String POINTCUT_NOT_VISIBLE = "pointcutNotVisible";
+       public static final String CONFLICTING_INHERITED_POINTCUTS = "conflictingInheritedPointcuts";
+       public static final String CIRCULAR_POINTCUT = "circularPointcutDeclaration";
+       public static final String CANT_FIND_POINTCUT = "cantFindPointcut";
+       public static final String EXACT_TYPE_PATTERN_REQD = "exactTypePatternRequired";
+       public static final String CANT_BIND_TYPE = "cantBindType";
+       public static final String WILDCARD_NOT_ALLOWED = "wildcardTypePatternNotAllowed";
+       public static final String FIELDS_CANT_HAVE_VOID_TYPE = "fieldCantBeVoid";
+       public static final String NO_NEWARRAY_JOINPOINTS_BY_DEFAULT = "noNewArrayJoinpointsByDefault";
+       public static final String UNSUPPORTED_POINTCUT_PRIMITIVE = "unsupportedPointcutPrimitive";
+       public static final String MISSING_TYPE_PREVENTS_MATCH = "missingTypePreventsMatch";
+       
+       public static final String DECP_OBJECT = "decpObject";
+       public static final String CANT_EXTEND_SELF="cantExtendSelf";
+       public static final String INTERFACE_CANT_EXTEND_CLASS="interfaceExtendClass";
+       public static final String DECP_HIERARCHY_ERROR = "decpHierarchy";
+       
+       public static final String MULTIPLE_MATCHES_IN_PRECEDENCE = "multipleMatchesInPrecedence";
+       public static final String TWO_STARS_IN_PRECEDENCE = "circularityInPrecedenceStar";
+       public static final String CLASSES_IN_PRECEDENCE = "nonAspectTypesInPrecedence";
+       public static final String TWO_PATTERN_MATCHES_IN_PRECEDENCE = "circularityInPrecedenceTwo";
+       
+       public static final String NOT_THROWABLE = "notThrowable";
+       
+       public static final String ITD_CONS_ON_ASPECT = "itdConsOnAspect";
+       public static final String ITD_RETURN_TYPE_MISMATCH = "returnTypeMismatch";
+       public static final String ITD_PARAM_TYPE_MISMATCH = "paramTypeMismatch";
+       public static final String ITD_VISIBILITY_REDUCTION = "visibilityReduction";
+       public static final String ITD_DOESNT_THROW = "doesntThrow";
+       public static final String ITD_OVERRIDDEN_STATIC = "overriddenStatic";
+       public static final String ITD_OVERIDDING_STATIC = "overridingStatic";
+       public static final String ITD_CONFLICT = "itdConflict";
+       public static final String ITD_MEMBER_CONFLICT = "itdMemberConflict";
+       public static final String ITD_NON_EXPOSED_IMPLEMENTOR = "itdNonExposedImplementor";
+       public static final String ITD_ABSTRACT_MUST_BE_PUBLIC_ON_INTERFACE = "itdAbstractMustBePublicOnInterface";
+       public static final String CANT_OVERRIDE_FINAL_MEMBER = "cantOverrideFinalMember";
+       
+       public static final String NON_VOID_RETURN = "nonVoidReturn";
+       public static final String INCOMPATIBLE_RETURN_TYPE="incompatibleReturnType";
+       public static final String CANT_THROW_CHECKED = "cantThrowChecked";
+       public static final String CIRCULAR_DEPENDENCY = "circularDependency";
+       
+       public static final String MISSING_PER_CLAUSE = "missingPerClause";
+       public static final String WRONG_PER_CLAUSE = "wrongPerClause";
+       
+       public static final String ALREADY_WOVEN = "alreadyWoven";
+       public static final String REWEAVABLE_MODE = "reweavableMode";
+       public static final String PROCESSING_REWEAVABLE = "processingReweavable";
+       public static final String MISSING_REWEAVABLE_TYPE = "missingReweavableType";
+       public static final String VERIFIED_REWEAVABLE_TYPE = "verifiedReweavableType";
+       public static final String ASPECT_NEEDED = "aspectNeeded";
+    public static final String REWEAVABLE_ASPECT_NOT_REGISTERED = "reweavableAspectNotRegistered";
+
+    public static final String CANT_FIND_TYPE = "cantFindType";
+       public static final String CANT_FIND_CORE_TYPE = "cantFindCoreType";
+       public static final String CANT_FIND_TYPE_WITHINPCD = "cantFindTypeWithinpcd";
+    public static final String CANT_FIND_TYPE_DURING_AROUND_WEAVE = "cftDuringAroundWeave";
+    public static final String CANT_FIND_TYPE_DURING_AROUND_WEAVE_PREINIT = "cftDuringAroundWeavePreinit";
+    public static final String CANT_FIND_TYPE_EXCEPTION_TYPE = "cftExceptionType";
+    public static final String CANT_FIND_TYPE_ARG_TYPE = "cftArgType";
+    public static final String CANT_FIND_PARENT_TYPE = "cantFindParentType";
+    public static final String CANT_FIND_PARENT_TYPE_NO_SUB = "cantFindParentTypeNoSub";
+    public static final String CANT_FIND_TYPE_FIELDS = "cantFindTypeFields";
+    public static final String CANT_FIND_TYPE_SUPERCLASS = "cantFindTypeSuperclass";
+    public static final String CANT_FIND_TYPE_INTERFACES = "cantFindTypeInterfaces";
+    public static final String CANT_FIND_TYPE_METHODS = "cantFindTypeMethods";
+    public static final String CANT_FIND_TYPE_POINTCUTS = "cantFindTypePointcuts";
+    public static final String CANT_FIND_TYPE_MODIFIERS = "cantFindTypeModifiers";
+    public static final String CANT_FIND_TYPE_ANNOTATION = "cantFindTypeAnnotation";
+    public static final String CANT_FIND_TYPE_ASSIGNABLE = "cantFindTypeAssignable";
+    public static final String CANT_FIND_TYPE_COERCEABLE = "cantFindTypeCoerceable";
+    public static final String CANT_FIND_TYPE_JOINPOINT = "cantFindTypeJoinPoint";
+    public static final String CANT_FIND_TYPE_INTERFACE_METHODS = "cantFindTypeInterfaceMethods";
+       
+       public static final String DECP_BINARY_LIMITATION = "decpBinaryLimitation";
+       public static final String OVERWRITE_JSR45 = "overwriteJSR45";
+       public static final String IF_IN_PERCLAUSE = "ifInPerClause";
+       public static final String IF_LEXICALLY_IN_CFLOW = "ifLexicallyInCflow";
+       public static final String ONLY_BEFORE_ON_HANDLER = "onlyBeforeOnHandler";
+       public static final String NO_AROUND_ON_SYNCHRONIZATION = "noAroundOnSynchronization";
+       public static final String AROUND_ON_PREINIT = "aroundOnPreInit";
+       public static final String AROUND_ON_INIT = "aroundOnInit";
+       public static final String AROUND_ON_INTERFACE_STATICINIT = "aroundOnInterfaceStaticInit";
+       
+       public static final String PROBLEM_GENERATING_METHOD = "problemGeneratingMethod";
+       public static final String CLASS_TOO_BIG = "classTooBig";
+       
+       public static final String ZIPFILE_ENTRY_MISSING = "zipfileEntryMissing";
+       public static final String ZIPFILE_ENTRY_INVALID = "zipfileEntryInvalid";
+       public static final String DIRECTORY_ENTRY_MISSING = "directoryEntryMissing";
+       public static final String OUTJAR_IN_INPUT_PATH = "outjarInInputPath";
+       
+       
+       public static final String XLINT_LOAD_ERROR = "problemLoadingXLint";
+       public static final String XLINTDEFAULT_LOAD_ERROR = "unableToLoadXLintDefault";
+       public static final String XLINTDEFAULT_LOAD_PROBLEM = "errorLoadingXLintDefault";
+       public static final String XLINT_KEY_ERROR = "invalidXLintKey";
+       public static final String XLINT_VALUE_ERROR = "invalidXLintMessageKind";
+       
+       public static final String UNBOUND_FORMAL = "unboundFormalInPC";
+       public static final String AMBIGUOUS_BINDING = "ambiguousBindingInPC";
+       public static final String AMBIGUOUS_BINDING_IN_OR = "ambiguousBindingInOrPC";
+       public static final String NEGATION_DOESNT_ALLOW_BINDING = "negationDoesntAllowBinding";
+       
+    // Java5 messages
+       public static final String ITDC_ON_ENUM_NOT_ALLOWED = "itdcOnEnumNotAllowed";
+       public static final String ITDM_ON_ENUM_NOT_ALLOWED = "itdmOnEnumNotAllowed";
+       public static final String ITDF_ON_ENUM_NOT_ALLOWED = "itdfOnEnumNotAllowed";
+       public static final String CANT_DECP_ON_ENUM_TO_IMPL_INTERFACE = "cantDecpOnEnumToImplInterface";
+       public static final String CANT_DECP_ON_ENUM_TO_EXTEND_CLASS = "cantDecpOnEnumToExtendClass";
+       public static final String CANT_DECP_TO_MAKE_ENUM_SUPERTYPE = "cantDecpToMakeEnumSupertype";
+       public static final String ITDC_ON_ANNOTATION_NOT_ALLOWED = "itdcOnAnnotationNotAllowed";
+       public static final String ITDM_ON_ANNOTATION_NOT_ALLOWED = "itdmOnAnnotationNotAllowed";
+       public static final String ITDF_ON_ANNOTATION_NOT_ALLOWED = "itdfOnAnnotationNotAllowed";
+       public static final String CANT_DECP_ON_ANNOTATION_TO_IMPL_INTERFACE = "cantDecpOnAnnotationToImplInterface";
+       public static final String CANT_DECP_ON_ANNOTATION_TO_EXTEND_CLASS = "cantDecpOnAnnotationToExtendClass";
+       public static final String CANT_DECP_TO_MAKE_ANNOTATION_SUPERTYPE = "cantDecpToMakeAnnotationSupertype";
+       public static final String REFERENCE_TO_NON_ANNOTATION_TYPE = "referenceToNonAnnotationType";
+       public static final String BINDING_NON_RUNTIME_RETENTION_ANNOTATION = "bindingNonRuntimeRetentionAnnotation";
+       
+       public static final String INCORRECT_TARGET_FOR_DECLARE_ANNOTATION = "incorrectTargetForDeclareAnnotation";
+       public static final String NO_MATCH_BECAUSE_SOURCE_RETENTION = "noMatchBecauseSourceRetention";
+       
+       // Annotation Value messages
+       public static final String INVALID_ANNOTATION_VALUE = "invalidAnnotationValue";
+       public static final String UNKNOWN_ANNOTATION_VALUE = "unknownAnnotationValue";
+       
+       // < Java5 messages
+       public static final String ATANNOTATION_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "atannotationNeedsJava5";
+       public static final String ATWITHIN_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "atwithinNeedsJava5";
+       public static final String ATWITHINCODE_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "atwithincodeNeedsJava5";
+       public static final String ATTHIS_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "atthisNeedsJava5";
+       public static final String ATTARGET_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "attargetNeedsJava5";
+       public static final String ATARGS_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "atargsNeedsJava5";
+       public static final String DECLARE_ATTYPE_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "declareAtTypeNeedsJava5";
+       public static final String DECLARE_ATMETHOD_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "declareAtMethodNeedsJava5";
+       public static final String DECLARE_ATFIELD_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "declareAtFieldNeedsJava5";
+       public static final String DECLARE_ATCONS_ONLY_SUPPORTED_AT_JAVA5_LEVEL = "declareAtConsNeedsJava5";
+       public static final String ANNOTATIONS_NEED_JAVA5 = "annotationsRequireJava5";
+       
+       // Generics
+       public static final String CANT_DECP_MULTIPLE_PARAMETERIZATIONS="cantDecpMultipleParameterizations";
+       public static final String HANDLER_PCD_DOESNT_SUPPORT_PARAMETERS="noParameterizedTypePatternInHandler";
+       public static final String INCORRECT_NUMBER_OF_TYPE_ARGUMENTS = "incorrectNumberOfTypeArguments";
+       public static final String VIOLATES_TYPE_VARIABLE_BOUNDS = "violatesTypeVariableBounds";
+       public static final String NO_STATIC_INIT_JPS_FOR_PARAMETERIZED_TYPES = "noStaticInitJPsForParameterizedTypes";
+       public static final String NOT_A_GENERIC_TYPE="notAGenericType";
+       public static final String WITHIN_PCD_DOESNT_SUPPORT_PARAMETERS="noParameterizedTypePatternInWithin";
+       public static final String THIS_AND_TARGET_DONT_SUPPORT_PARAMETERS="noParameterizedTypesInThisAndTarget";
+       public static final String GET_AND_SET_DONT_SUPPORT_DEC_TYPE_PARAMETERS="noParameterizedTypesInGetAndSet";
+       public static final String NO_INIT_JPS_FOR_PARAMETERIZED_TYPES = "noInitJPsForParameterizedTypes";
+       public static final String NO_GENERIC_THROWABLES = "noGenericThrowables";
+       public static final String WITHINCODE_DOESNT_SUPPORT_PARAMETERIZED_DECLARING_TYPES="noParameterizedDeclaringTypesWithinCode";
+       public static final String EXECUTION_DOESNT_SUPPORT_PARAMETERIZED_DECLARING_TYPES="noParameterizedDeclaringTypesInExecution";
+       public static final String CALL_DOESNT_SUPPORT_PARAMETERIZED_DECLARING_TYPES="noParameterizedDeclaringTypesInCall";
+       public static final String CANT_REFERENCE_POINTCUT_IN_RAW_TYPE="noRawTypePointcutReferences";
+       
+       public static final String HAS_MEMBER_NOT_ENABLED="hasMemberNotEnabled";
+       
+       // @AspectJ
+       public static final String RETURNING_FORMAL_NOT_DECLARED_IN_ADVICE = "returningFormalNotDeclaredInAdvice";
+       public static final String THROWN_FORMAL_NOT_DECLARED_IN_ADVICE = "thrownFormalNotDeclaredInAdvice";
+       
+       public static String format(String key) {
+               return bundle.getString(key);
+       }
+       
+       public static String format(String key, Object insert) {
+               return MessageFormat.format(bundle.getString(key),new Object[] {insert});
+       }
+
+       public static String format(String key, Object insert1, Object insert2) {
+               return MessageFormat.format(bundle.getString(key),new Object[] {insert1,insert2});
+       }
+
+       public static String format(String key, Object insert1, Object insert2, Object insert3) {
+               return MessageFormat.format(bundle.getString(key),new Object[] {insert1, insert2, insert3});
+       }
+
+       public static String format(String key, Object insert1, Object insert2, Object insert3, Object insert4) {
+               return MessageFormat.format(bundle.getString(key),new Object[] {insert1, insert2, insert3, insert4});
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/WeaverStateInfo.java b/org.aspectj.matcher/src/org/aspectj/weaver/WeaverStateInfo.java
new file mode 100644 (file)
index 0000000..c1cca45
--- /dev/null
@@ -0,0 +1,476 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.aspectj.bridge.IMessage;
+
+/**
+ * WeaverStateInfo represents how a type was processed. It is used by the weaver to determine how a type was previously treated and
+ * whether reweaving is allowed. The format in the data stream is:
+ * 
+ * Byte: Kind. UNTOUCHED|WOVEN|EXTENDED - If extended it can have two extra bits set 'REWEAVABLE' and 'REWEAVABLE_COMPRESSION_BIT'
+ * Short: typeMungerCount - how many type mungers have affected this type <UnresolvedType & ResolvedTypeMunger>: The type mungers
+ * themselves If we are reweavable then we also have: Short: Number of aspects that touched this type in some way when it was
+ * previously woven <String> The fully qualified name of each type Int: Length of class file data (i.e. the unwovenclassfile)
+ * Byte[]: The class file data, compressed if REWEAVABLE_COMPRESSION_BIT set.
+ */
+
+public class WeaverStateInfo {
+       private List/* Entry */typeMungers;
+       private boolean oldStyle;
+
+       private boolean reweavable;
+       private boolean reweavableCompressedMode; // If true, unwovenClassFile is uncompressed on read
+       private boolean reweavableDiffMode; // if true, unwovenClassFile is written and read as a diff
+
+       private Set /* String */aspectsAffectingType; // These must exist in the world for reweaving to be valid
+       private byte[] unwovenClassFile; // Original 'untouched' class file
+       private static boolean reweavableDefault = true; // ajh02: changed from false;
+       private static boolean reweavableCompressedModeDefault = false;
+       private static boolean reweavableDiffModeDefault = true;
+
+       // when serializing the WeaverStateInfo we come to adding the reweavable data,
+       // we'd like to add a diff of the unwovenClassFile and the wovenClassFile,
+       // but we don't have the wovenClassFile yet as we're still in the process of making it.
+       // so we put this key there instead as a stub.
+       // Then when the wovenClassFile has been made, replaceKeyWithDiff is called.
+       private static byte[] key = { -51, 34, 105, 56, -34, 65, 45, 78, -26, 125, 114, 97, 98, 1, -1, -42 };
+       private boolean unwovenClassFileIsADiff = false;
+
+       private WeaverStateInfo() {
+               // this(new ArrayList(), false,reweavableDefault,reweavableCompressedModeDefault,reweavableDiffModeDefault);
+       }
+
+       public WeaverStateInfo(boolean reweavable) {
+               this(new ArrayList(), false, reweavable, reweavableCompressedModeDefault, reweavableDiffModeDefault);
+       }
+
+       private WeaverStateInfo(List typeMungers, boolean oldStyle, boolean reweavableMode, boolean reweavableCompressedMode,
+                       boolean reweavableDiffMode) {
+               this.typeMungers = typeMungers;
+               this.oldStyle = oldStyle;
+               this.reweavable = reweavableMode;
+               this.reweavableCompressedMode = reweavableCompressedMode;
+               this.reweavableDiffMode = reweavableMode ? reweavableDiffMode : false;
+               this.aspectsAffectingType = new HashSet();
+               this.unwovenClassFile = null;
+       }
+
+       public static void setReweavableModeDefaults(boolean mode, boolean compress, boolean diff) {
+               reweavableDefault = mode;
+               reweavableCompressedModeDefault = compress;
+               reweavableDiffModeDefault = diff;
+       }
+
+       private static final int UNTOUCHED = 0, WOVEN = 2, EXTENDED = 3;
+
+       // Use 'bits' for these capabilities - only valid in EXTENDED mode
+       private static final byte REWEAVABLE_BIT = 1 << 4;
+       private static final byte REWEAVABLE_COMPRESSION_BIT = 1 << 5;
+       private static final byte REWEAVABLE_DIFF_BIT = 1 << 6;
+
+       /** See comments on write() */
+       public static final WeaverStateInfo read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               byte b = s.readByte();
+
+               boolean isReweavable = ((b & REWEAVABLE_BIT) != 0);
+               if (isReweavable) {
+                       b = (byte) (b - REWEAVABLE_BIT);
+               }
+
+               boolean isReweavableCompressed = ((b & REWEAVABLE_COMPRESSION_BIT) != 0);
+               if (isReweavableCompressed) {
+                       b = (byte) (b - REWEAVABLE_COMPRESSION_BIT);
+               }
+
+               boolean isReweavableDiff = ((b & REWEAVABLE_DIFF_BIT) != 0);
+               if (isReweavableDiff) {
+                       b = (byte) (b - REWEAVABLE_DIFF_BIT);
+               }
+
+               switch (b) {
+               case UNTOUCHED:
+                       throw new RuntimeException("unexpected UNWOVEN");
+               case WOVEN:
+                       return new WeaverStateInfo(Collections.EMPTY_LIST, true, isReweavable, isReweavableCompressed, isReweavableDiff);
+               case EXTENDED:
+                       int n = s.readShort();
+                       List l = new ArrayList();
+                       for (int i = 0; i < n; i++) {
+                               UnresolvedType aspectType = UnresolvedType.read(s);
+                               ResolvedTypeMunger typeMunger = ResolvedTypeMunger.read(s, context);
+                               l.add(new Entry(aspectType, typeMunger));
+                       }
+                       WeaverStateInfo wsi = new WeaverStateInfo(l, false, isReweavable, isReweavableCompressed, isReweavableDiff);
+                       readAnyReweavableData(wsi, s);
+                       return wsi;
+               }
+               throw new RuntimeException("bad WeaverState.Kind: " + b + ".  File was :"
+                               + (context == null ? "unknown" : context.makeSourceLocation(0, 0).toString()));
+       }
+
+       private static class Entry {
+               public UnresolvedType aspectType;
+               public ResolvedTypeMunger typeMunger;
+
+               public Entry(UnresolvedType aspectType, ResolvedTypeMunger typeMunger) {
+                       this.aspectType = aspectType;
+                       this.typeMunger = typeMunger;
+               }
+
+               public String toString() {
+                       return "<" + aspectType + ", " + typeMunger + ">";
+               }
+       }
+
+       /**
+        * Serialize the WeaverStateInfo. Various bits are set within the 'kind' flag to indicate the structure of the attribute. In
+        * reweavable diff mode a 'marker' is inserted at the start of the attribute to indicate where the final calculated diff should
+        * be inserted. When the key is replaced with the diff, the 'kind' byte moves to the front of the attribute - thats why in the
+        * read logic you'll see it expecting the kind as the first byte.
+        */
+       public void write(DataOutputStream s) throws IOException {
+               if (oldStyle || reweavableCompressedMode) {
+                       throw new RuntimeException("shouldn't be writing this");
+               }
+
+               byte weaverStateInfoKind = EXTENDED;
+               if (reweavable)
+                       weaverStateInfoKind |= REWEAVABLE_BIT;
+
+               if (reweavableDiffMode) {
+                       s.write(key); // put key in so we can replace it with the diff later
+                       weaverStateInfoKind |= REWEAVABLE_DIFF_BIT;
+               }
+
+               s.writeByte(weaverStateInfoKind);
+
+               int n = typeMungers.size();
+               s.writeShort(n);
+               for (int i = 0; i < n; i++) {
+                       Entry e = (Entry) typeMungers.get(i);
+                       e.aspectType.write(s);
+                       e.typeMunger.write(s);
+               }
+               writeAnyReweavableData(this, s);
+       }
+
+       public void addConcreteMunger(ConcreteTypeMunger munger) {
+               typeMungers.add(new Entry(munger.getAspectType(), munger.getMunger()));
+       }
+
+       public String toString() {
+               return "WeaverStateInfo(" + typeMungers + ", " + oldStyle + ")";
+       }
+
+       public List getTypeMungers(ResolvedType onType) {
+               World world = onType.getWorld();
+               List ret = new ArrayList();
+               for (Iterator i = typeMungers.iterator(); i.hasNext();) {
+                       Entry entry = (Entry) i.next();
+                       ResolvedType aspectType = world.resolve(entry.aspectType, true);
+                       if (aspectType.isMissing()) {
+                               world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.ASPECT_NEEDED, entry.aspectType, onType),
+                                               onType.getSourceLocation(), null);
+                               continue;
+                       }
+
+                       ret.add(new TemporaryTypeMunger(entry.typeMunger, aspectType));
+               }
+               return ret;
+       }
+
+       public boolean isOldStyle() {
+               return oldStyle;
+       }
+
+       public byte[] getUnwovenClassFileData(byte wovenClassFile[]) {
+               if (unwovenClassFileIsADiff) {
+                       unwovenClassFile = applyDiff(wovenClassFile, unwovenClassFile);
+                       unwovenClassFileIsADiff = false;
+               }
+               return unwovenClassFile;
+       }
+
+       public void setUnwovenClassFileData(byte[] data) {
+               unwovenClassFile = data;
+       }
+
+       public boolean isReweavable() {
+               return reweavable;
+       }
+
+       public void setReweavable(boolean rw) {
+               reweavable = rw;
+       }
+
+       public void addAspectsAffectingType(Collection /* String */aspects) {
+               aspectsAffectingType.addAll(aspects);
+       }
+
+       public void addAspectAffectingType(String aspectType) {
+               aspectsAffectingType.add(aspectType);
+       }
+
+       public Set /* String */getAspectsAffectingType() {
+               return this.aspectsAffectingType;
+       }
+
+       private static void readAnyReweavableData(WeaverStateInfo wsi, DataInputStream s) throws IOException {
+               if (wsi.isReweavable()) {
+                       // Load list of aspects that need to exist in the world for reweaving to be 'legal'
+                       int numberAspectsAffectingType = s.readShort();
+                       for (int i = 0; i < numberAspectsAffectingType; i++) {
+                               wsi.addAspectAffectingType(s.readUTF());
+                       }
+
+                       int unwovenClassFileSize = s.readInt();
+                       byte[] classData = null;
+                       // the unwovenClassFile may have been compressed:
+                       if (wsi.reweavableCompressedMode) {
+                               classData = new byte[unwovenClassFileSize];
+                               ZipInputStream zis = new ZipInputStream(s);
+                               ZipEntry zen = zis.getNextEntry();
+                               int current = 0;
+                               int bytesToGo = unwovenClassFileSize;
+                               while (bytesToGo > 0) {
+                                       int amount = zis.read(classData, current, bytesToGo);
+                                       current += amount;
+                                       bytesToGo -= amount;
+                               }
+                               zis.closeEntry();
+                               if (bytesToGo != 0)
+                                       throw new IOException("ERROR whilst reading compressed reweavable data, expected " + unwovenClassFileSize
+                                                       + " bytes, only found " + current);
+                       } else {
+                               classData = new byte[unwovenClassFileSize];
+                               int bytesread = s.read(classData);
+                               if (bytesread != unwovenClassFileSize)
+                                       throw new IOException("ERROR whilst reading reweavable data, expected " + unwovenClassFileSize
+                                                       + " bytes, only found " + bytesread);
+                       }
+
+                       // if it was diffMode we'll have to remember to apply the diff if someone
+                       // asks for the unwovenClassFile
+                       wsi.unwovenClassFileIsADiff = wsi.reweavableDiffMode;
+                       wsi.setUnwovenClassFileData(classData);
+               }
+       }
+
+       /**
+        * Here is the cleverness for reweavable diff mode. The class file on disk contains, inside the weaverstateinfo attribute, a
+        * diff that can be applied to 'itself' to recover the original class - which can then be rewoven.
+        */
+       public byte[] replaceKeyWithDiff(byte wovenClassFile[]) {
+               // we couldn't have made the diff earlier
+               // as we didn't have the wovenClassFile
+               // so we left a key there as a marker to come back to
+
+               if (reweavableDiffMode) {
+                       ByteArrayOutputStream arrayStream = new ByteArrayOutputStream();
+                       DataOutputStream s = new DataOutputStream(arrayStream);
+
+                       int endOfKey = findEndOfKey(wovenClassFile);
+                       int startOfKey = endOfKey - key.length;
+                       // the length of the wsi attribute is written infront of it in the classFile,
+                       // swapping the diff for the key will probably change the length of the wsi,
+                       // so we'll have to fiddle with the four 'int length' bytes
+                       int oldLengthLocation = startOfKey - 4;
+                       int oldLength = readInt(wovenClassFile, oldLengthLocation);
+                       wovenClassFile = deleteInArray(wovenClassFile, startOfKey, endOfKey); // delete the key
+
+                       byte[] wovenClassFileUpToWSI = new byte[oldLengthLocation];
+                       System.arraycopy(wovenClassFile, 0, wovenClassFileUpToWSI, 0, oldLengthLocation);
+
+                       byte[] diff = generateDiff(wovenClassFileUpToWSI, unwovenClassFile);
+                       try { // put the length of the diff infront of the diff
+                               s.writeInt(diff.length);
+                               s.write(diff);
+                       } catch (IOException e) {
+                       }
+                       diff = arrayStream.toByteArray();
+                       // we have to swap the oldLength for the new one,
+                       // and add the diff, using the oldLength to work out where it should go :)
+
+                       int newLength = oldLength - key.length + diff.length;
+                       byte newLengthBytes[] = serializeInt(newLength);
+
+                       // swap in the serialized newLength for the oldOne:
+                       wovenClassFile[oldLengthLocation] = newLengthBytes[0];
+                       wovenClassFile[oldLengthLocation + 1] = newLengthBytes[1];
+                       wovenClassFile[oldLengthLocation + 2] = newLengthBytes[2];
+                       wovenClassFile[oldLengthLocation + 3] = newLengthBytes[3];
+
+                       // add the diff
+                       wovenClassFile = insertArray(diff, wovenClassFile, oldLengthLocation + 4 + oldLength - key.length);
+               }
+               return wovenClassFile;
+       }
+
+       private static final int findEndOfKey(byte[] wovenClassFile) {
+               // looks through the classfile backwards (as the attributes are all near the end)
+               for (int i = wovenClassFile.length - 1; i > 0; i--)
+                       if (endOfKeyHere(wovenClassFile, i)) {
+                               return i + 1;
+                       }
+               throw new RuntimeException("key not found in wovenClassFile"); // should never happen
+       }
+
+       private static final boolean endOfKeyHere(byte lookIn[], int i) {
+               for (int j = 0; j < key.length; j++)
+                       if (key[key.length - 1 - j] != lookIn[i - j]) {
+                               return false;
+                       }
+               return true;
+       }
+
+       private static final byte[] insertArray(byte toInsert[], byte original[], int offset) {
+               byte result[] = new byte[original.length + toInsert.length];
+               System.arraycopy(original, 0, result, 0, offset);
+               System.arraycopy(toInsert, 0, result, offset, toInsert.length);
+               System.arraycopy(original, offset, result, offset + toInsert.length, original.length - offset);
+               return result;
+       }
+
+       private static final int readInt(byte[] a, int offset) {
+               ByteArrayInputStream b = new ByteArrayInputStream(a, offset, 4);
+               DataInputStream d = new DataInputStream(b);
+               int length = -1;
+               try {
+                       length = d.readInt();
+               } catch (IOException e) {
+                       throw (new RuntimeException("readInt called with a bad array or offset")); // should never happen
+               }
+               return length;
+       }
+
+       private static final byte[] deleteInArray(byte a[], int start, int end) {
+               int lengthToDelete = end - start;
+               byte result[] = new byte[a.length - lengthToDelete]; // make a new array
+               System.arraycopy(a, 0, result, 0, start); // copy in the bit before the deleted bit
+               System.arraycopy(a, end, result, start, a.length - end); // copy in the bit after the deleted bit
+               return result;
+       }
+
+       // ajh02: a quick note about the diff format...
+       //
+       // classfiles consist of:
+       // 8 bytes: magic number and minor and major versions,
+       // 2 bytes: its constant pool count
+       // n bytes: the rest of the class file
+       //
+       // weaving a classfile never changes the classfile's first 8 bytes,
+       // and after the constant pool count there's usually a run of bytes that weaving didn't change
+       // hereafter referred to as the run
+       //
+       // so the diff consists of:
+       // 2 bytes: its constant pool count
+       // 4 bytes: length of the run
+       // n bytes: the rest of the unwovenClassFile
+
+       byte[] generateDiff(byte[] wovenClassFile, byte[] unWovenClassFile) {
+
+               // find how long the run is
+               int lookingAt = 10;
+               int shorterLength = (wovenClassFile.length < unWovenClassFile.length) ? wovenClassFile.length : unWovenClassFile.length;
+               while (lookingAt < shorterLength && (wovenClassFile[lookingAt] == unWovenClassFile[lookingAt])) {
+                       lookingAt++;
+               }
+               int lengthInCommon = lookingAt - 10;
+               byte[] diff = new byte[unWovenClassFile.length - 4 - lengthInCommon];
+
+               // first 2 bytes of the diff are the constant pool count
+               diff[0] = unWovenClassFile[8];
+               diff[1] = unWovenClassFile[9];
+
+               // then 4 bytes saying how long the run is
+               byte[] lengthInCommonBytes = serializeInt(lengthInCommon);
+               diff[2] = lengthInCommonBytes[0];
+               diff[3] = lengthInCommonBytes[1];
+               diff[4] = lengthInCommonBytes[2];
+               diff[5] = lengthInCommonBytes[3];
+
+               // then we just dump the rest of the unWovenClassFile verbatim
+               System.arraycopy(unWovenClassFile, 10 + lengthInCommon, diff, 6, diff.length - 6);
+
+               return diff;
+       }
+
+       byte[] applyDiff(byte[] wovenClassFile, byte[] diff) {
+
+               int lengthInCommon = readInt(diff, 2);
+               byte[] unWovenClassFile = new byte[4 + diff.length + lengthInCommon];
+
+               // copy the first 8 bytes from the wovenClassFile
+               System.arraycopy(wovenClassFile, 0, unWovenClassFile, 0, 8);
+
+               // copy the constant pool count from the diff
+               unWovenClassFile[8] = diff[0];
+               unWovenClassFile[9] = diff[1];
+
+               // copy the run from the wovenClassFile
+               System.arraycopy(wovenClassFile, 10, unWovenClassFile, 10, lengthInCommon);
+
+               // copy the stuff after the run from the diff
+               System.arraycopy(diff, 6, unWovenClassFile, 10 + lengthInCommon, diff.length - 6);
+
+               return unWovenClassFile;
+       }
+
+       private byte[] serializeInt(int i) {
+               ByteArrayOutputStream bos = new ByteArrayOutputStream(4);
+               DataOutputStream dos = new DataOutputStream(bos);
+               try {
+                       dos.writeInt(i);
+               } catch (IOException e) {
+               }
+               return bos.toByteArray();
+       }
+
+       private static void writeAnyReweavableData(WeaverStateInfo wsi, DataOutputStream s) throws IOException {
+               if (wsi.isReweavable()) {
+                       // Write out list of aspects that must exist next time we try and weave this class
+                       s.writeShort(wsi.aspectsAffectingType.size());
+                       if (wsi.aspectsAffectingType.size() > 0) {
+                               for (Iterator iter = wsi.aspectsAffectingType.iterator(); iter.hasNext();) {
+                                       String type = (String) iter.next();
+                                       s.writeUTF(type);
+                               }
+                       }
+                       byte[] data = wsi.unwovenClassFile;
+
+                       // if we're not in diffMode, write the unwovenClassFile now,
+                       // otherwise we'll insert it as a diff later
+                       if (!wsi.reweavableDiffMode) {
+                               s.writeInt(data.length);
+                               s.write(wsi.unwovenClassFile);
+                       }
+               }
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/WildcardedUnresolvedType.java b/org.aspectj.matcher/src/org/aspectj/weaver/WildcardedUnresolvedType.java
new file mode 100644 (file)
index 0000000..5888bc8
--- /dev/null
@@ -0,0 +1,69 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement     initial implementation 
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+/**
+ * Represents a wildcarded bound for a generic type, this can be unbounded '?' or bounded via extends '? extends Foo' or
+ * super '? super Foo'. The signature for a ? is in fact "*" and the erasure signature is the upper bound which defaults
+ * to java.lang.Object if nothing is specified. On resolution, this becomes a BoundedReferenceType
+ * 
+ * @author Andy Clement
+ */
+public class WildcardedUnresolvedType extends UnresolvedType {
+
+    // TODO does not cope with extra bounds '? extends A & B & C'
+    
+    public static final int UNBOUND = 0;
+
+    public static final int EXTENDS = 1;
+
+    public static final int SUPER = 2;
+    
+    public static final WildcardedUnresolvedType QUESTIONMARK = new WildcardedUnresolvedType("*", UnresolvedType.OBJECT, null);
+
+    private int boundKind = UNBOUND; // UNBOUND, EXTENDS, SUPER
+
+    private UnresolvedType lowerBound;
+
+    private UnresolvedType upperBound;
+
+    public WildcardedUnresolvedType(String signature, UnresolvedType upperBound, UnresolvedType lowerBound) {
+        super(signature, (upperBound == null ? UnresolvedType.OBJECT.signature : upperBound.signatureErasure));
+        this.typeKind = TypeKind.WILDCARD;
+        this.upperBound = upperBound;
+        this.lowerBound = lowerBound;
+        if (signature.charAt(0) == '-') boundKind = SUPER;
+        if (signature.charAt(0) == '+') boundKind = EXTENDS;
+    }
+
+    public UnresolvedType getUpperBound() {
+        return upperBound;
+    }
+
+    public UnresolvedType getLowerBound() {
+        return lowerBound;
+    }
+
+    public boolean isExtends() {
+        return boundKind == EXTENDS;
+    }
+
+    public boolean isSuper() {
+        return boundKind == SUPER;
+    }
+
+    public boolean isUnbound() {
+        return boundKind == UNBOUND;
+    }
+
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/World.java b/org.aspectj.matcher/src/org/aspectj/weaver/World.java
new file mode 100644 (file)
index 0000000..7cba4d4
--- /dev/null
@@ -0,0 +1,1286 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ *               2005 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation
+ *     Adrian Colyer, Andy Clement, overhaul for generics 
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.Message;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.bridge.IMessage.Kind;
+import org.aspectj.bridge.context.PinpointingMessageHandler;
+import org.aspectj.util.IStructureModel;
+import org.aspectj.weaver.UnresolvedType.TypeKind;
+import org.aspectj.weaver.patterns.DeclarePrecedence;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.tools.PointcutDesignatorHandler;
+import org.aspectj.weaver.tools.Trace;
+import org.aspectj.weaver.tools.TraceFactory;
+
+/**
+ * A World is a collection of known types and crosscutting members.
+ */
+public abstract class World implements Dump.INode {
+       /** handler for any messages produced during resolution etc. */
+       private IMessageHandler messageHandler = IMessageHandler.SYSTEM_ERR;
+
+       /**
+        * handler for cross-reference information produced during the weaving process
+        */
+       private ICrossReferenceHandler xrefHandler = null;
+
+       /**
+        * Currently 'active' scope in which to lookup (resolve) typevariable references
+        */
+       private TypeVariableDeclaringElement typeVariableLookupScope;
+
+       /** The heart of the world, a map from type signatures to resolved types */
+       protected TypeMap typeMap = new TypeMap(this); // Signature to ResolvedType
+
+       /** New pointcut designators this world supports */
+       private Set pointcutDesignators;
+
+       // see pr145963
+       /** Should we create the hierarchy for binary classes and aspects */
+       public static boolean createInjarHierarchy = true;
+
+       /** Calculator for working out aspect precedence */
+       private final AspectPrecedenceCalculator precedenceCalculator;
+
+       /** All of the type and shadow mungers known to us */
+       private final CrosscuttingMembersSet crosscuttingMembersSet = new CrosscuttingMembersSet(this);
+
+       /** The structure model for the compilation */
+       private IStructureModel model = null;
+
+       /** for processing Xlint messages */
+       private Lint lint = new Lint(this);
+
+       /** XnoInline option setting passed down to weaver */
+       private boolean XnoInline;
+
+       /** XlazyTjp option setting passed down to weaver */
+       private boolean XlazyTjp;
+
+       /** XhasMember option setting passed down to weaver */
+       private boolean XhasMember = false;
+
+       /**
+        * Xpinpoint controls whether we put out developer info showing the source of messages
+        */
+       private boolean Xpinpoint = false;
+
+       /** When behaving in a Java 5 way autoboxing is considered */
+       private boolean behaveInJava5Way = false;
+
+       /** Determines if this world could be used for multiple compiles */
+       private boolean incrementalCompileCouldFollow = false;
+
+       /** The level of the aspectjrt.jar the code we generate needs to run on */
+       private String targetAspectjRuntimeLevel = Constants.RUNTIME_LEVEL_DEFAULT;
+
+       /** Flags for the new joinpoints that are 'optional' */
+       private boolean optionalJoinpoint_ArrayConstruction = false; // Command line
+       // flag:
+       // "-Xjoinpoints:arrayconstruction"
+       private boolean optionalJoinpoint_Synchronization = false; // Command line
+       // flag:
+       // "-Xjoinpoints:synchronization"
+
+       private boolean addSerialVerUID = false;
+
+       private Properties extraConfiguration = null;
+       private boolean checkedAdvancedConfiguration = false;
+       private boolean synchronizationPointcutsInUse = false;
+       // Xset'table options
+       private boolean runMinimalMemory = false;
+       private boolean shouldPipelineCompilation = true;
+       private boolean shouldGenerateStackMaps = false;
+       protected boolean bcelRepositoryCaching = xsetBCEL_REPOSITORY_CACHING_DEFAULT.equalsIgnoreCase("true");
+       private boolean fastMethodPacking = false;
+       private boolean completeBinaryTypes = false;
+       public boolean forDEBUG_structuralChangesCode = false;
+       public boolean forDEBUG_bridgingCode = false;
+
+       private static Trace trace = TraceFactory.getTraceFactory().getTrace(World.class);
+
+       private long errorThreshold;
+       private long warningThreshold;
+
+       /**
+        * A list of RuntimeExceptions containing full stack information for every type we couldn't find.
+        */
+       private List dumpState_cantFindTypeExceptions = null;
+
+       /**
+        * Play God. On the first day, God created the primitive types and put them in the type map.
+        */
+       protected World() {
+               super();
+               if (trace.isTraceEnabled())
+                       trace.enter("<init>", this);
+               Dump.registerNode(this.getClass(), this);
+               typeMap.put("B", ResolvedType.BYTE);
+               typeMap.put("S", ResolvedType.SHORT);
+               typeMap.put("I", ResolvedType.INT);
+               typeMap.put("J", ResolvedType.LONG);
+               typeMap.put("F", ResolvedType.FLOAT);
+               typeMap.put("D", ResolvedType.DOUBLE);
+               typeMap.put("C", ResolvedType.CHAR);
+               typeMap.put("Z", ResolvedType.BOOLEAN);
+               typeMap.put("V", ResolvedType.VOID);
+               precedenceCalculator = new AspectPrecedenceCalculator(this);
+               if (trace.isTraceEnabled())
+                       trace.exit("<init>");
+       }
+
+       /**
+        * Dump processing when a fatal error occurs
+        */
+       public void accept(Dump.IVisitor visitor) {
+               // visitor.visitObject("Extra configuration:");
+               // visitor.visitList(extraConfiguration.);
+               visitor.visitObject("Shadow mungers:");
+               visitor.visitList(crosscuttingMembersSet.getShadowMungers());
+               visitor.visitObject("Type mungers:");
+               visitor.visitList(crosscuttingMembersSet.getTypeMungers());
+               visitor.visitObject("Late Type mungers:");
+               visitor.visitList(crosscuttingMembersSet.getLateTypeMungers());
+               if (dumpState_cantFindTypeExceptions != null) {
+                       visitor.visitObject("Cant find type problems:");
+                       visitor.visitList(dumpState_cantFindTypeExceptions);
+                       dumpState_cantFindTypeExceptions = null;
+               }
+       }
+
+       // ==========================================================================
+       // ===
+       // T Y P E R E S O L U T I O N
+       // ==========================================================================
+       // ===
+
+       /**
+        * Resolve a type that we require to be present in the world
+        */
+       public ResolvedType resolve(UnresolvedType ty) {
+               return resolve(ty, false);
+       }
+
+       /**
+        * Attempt to resolve a type - the source location gives you some context in which resolution is taking place. In the case of an
+        * error where we can't find the type - we can then at least report why (source location) we were trying to resolve it.
+        */
+       public ResolvedType resolve(UnresolvedType ty, ISourceLocation isl) {
+               ResolvedType ret = resolve(ty, true);
+               if (ResolvedType.isMissing(ty)) {
+                       // IMessage msg = null;
+                       getLint().cantFindType.signal(WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE, ty.getName()), isl);
+                       // if (isl!=null) {
+                       // msg = MessageUtil.error(WeaverMessages.format(WeaverMessages.
+                       // CANT_FIND_TYPE,ty.getName()),isl);
+                       // } else {
+                       // msg = MessageUtil.error(WeaverMessages.format(WeaverMessages.
+                       // CANT_FIND_TYPE,ty.getName()));
+                       // }
+                       // messageHandler.handleMessage(msg);
+               }
+               return ret;
+       }
+
+       /**
+        * Convenience method for resolving an array of unresolved types in one hit. Useful for e.g. resolving type parameters in
+        * signatures.
+        */
+       public ResolvedType[] resolve(UnresolvedType[] types) {
+               if (types == null)
+                       return new ResolvedType[0];
+
+               ResolvedType[] ret = new ResolvedType[types.length];
+               for (int i = 0; i < types.length; i++) {
+                       ret[i] = resolve(types[i]);
+               }
+               return ret;
+       }
+
+       /**
+        * Resolve a type. This the hub of type resolution. The resolved type is added to the type map by signature.
+        */
+       public ResolvedType resolve(UnresolvedType ty, boolean allowMissing) {
+
+               // special resolution processing for already resolved types.
+               if (ty instanceof ResolvedType) {
+                       ResolvedType rty = (ResolvedType) ty;
+                       rty = resolve(rty);
+                       return rty;
+               }
+
+               // dispatch back to the type variable reference to resolve its
+               // constituent parts
+               // don't do this for other unresolved types otherwise you'll end up in a
+               // loop
+               if (ty.isTypeVariableReference()) {
+                       return ty.resolve(this);
+               }
+
+               // if we've already got a resolved type for the signature, just return
+               // it
+               // after updating the world
+               String signature = ty.getSignature();
+               ResolvedType ret = typeMap.get(signature);
+               if (ret != null) {
+                       ret.world = this; // Set the world for the RTX
+                       return ret;
+               } else if (signature.equals("?") || signature.equals("*")) {
+                       // might be a problem here, not sure '?' should make it to here as a
+                       // signature, the
+                       // proper signature for wildcard '?' is '*'
+                       // fault in generic wildcard, can't be done earlier because of init
+                       // issues
+                       // TODO ought to be shared single instance representing this
+                       ResolvedType something = new BoundedReferenceType("*", "Ljava/lang/Object", this);
+                       typeMap.put("?", something);
+                       return something;
+               }
+
+               // no existing resolved type, create one
+               if (ty.isArray()) {
+                       ResolvedType componentType = resolve(ty.getComponentType(), allowMissing);
+                       // String brackets =
+                       // signature.substring(0,signature.lastIndexOf("[")+1);
+                       ret = new ArrayReferenceType(signature, "[" + componentType.getErasureSignature(), this, componentType);
+               } else {
+                       ret = resolveToReferenceType(ty, allowMissing);
+                       if (!allowMissing && ret.isMissing()) {
+                               ret = handleRequiredMissingTypeDuringResolution(ty);
+                       }
+                       if (completeBinaryTypes) {
+                               completeBinaryType(ret);
+                       }
+               }
+
+               // Pulling in the type may have already put the right entry in the map
+               if (typeMap.get(signature) == null && !ret.isMissing()) {
+                       typeMap.put(signature, ret);
+               }
+               return ret;
+       }
+
+       /**
+        * Called when a type is resolved - enables its type hierarchy to be finished off before we proceed
+        */
+       protected void completeBinaryType(ResolvedType ret) {
+       }
+
+       /**
+        * Return true if the classloader relating to this world is definetly the one that will define the specified class. Return false
+        * otherwise or we don't know for certain.
+        */
+       public boolean isLocallyDefined(String classname) {
+               return false;
+       }
+
+       /**
+        * We tried to resolve a type and couldn't find it...
+        */
+       private ResolvedType handleRequiredMissingTypeDuringResolution(UnresolvedType ty) {
+               // defer the message until someone asks a question of the type that we
+               // can't answer
+               // just from the signature.
+               // MessageUtil.error(messageHandler,
+               // WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName()));
+               if (dumpState_cantFindTypeExceptions == null) {
+                       dumpState_cantFindTypeExceptions = new ArrayList();
+               }
+               if (dumpState_cantFindTypeExceptions.size() < 100) { // limit growth
+                       dumpState_cantFindTypeExceptions.add(new RuntimeException("Can't find type " + ty.getName()));
+               }
+               return new MissingResolvedTypeWithKnownSignature(ty.getSignature(), this);
+       }
+
+       /**
+        * Some TypeFactory operations create resolved types directly, but these won't be in the typeMap - this resolution process puts
+        * them there. Resolved types are also told their world which is needed for the special autoboxing resolved types.
+        */
+       public ResolvedType resolve(ResolvedType ty) {
+               if (ty.isTypeVariableReference())
+                       return ty; // until type variables have proper sigs...
+               ResolvedType resolved = typeMap.get(ty.getSignature());
+               if (resolved == null) {
+                       typeMap.put(ty.getSignature(), ty);
+                       resolved = ty;
+               }
+               resolved.world = this;
+               return resolved;
+       }
+
+       /**
+        * Convenience method for finding a type by name and resolving it in one step.
+        */
+       public ResolvedType resolve(String name) {
+               // trace.enter("resolve", this, new Object[] {name});
+               ResolvedType ret = resolve(UnresolvedType.forName(name));
+               // trace.exit("resolve", ret);
+               return ret;
+       }
+
+       public ResolvedType resolve(String name, boolean allowMissing) {
+               return resolve(UnresolvedType.forName(name), allowMissing);
+       }
+
+       /**
+        * Resolve to a ReferenceType - simple, raw, parameterized, or generic. Raw, parameterized, and generic versions of a type share
+        * a delegate.
+        */
+       private final ResolvedType resolveToReferenceType(UnresolvedType ty, boolean allowMissing) {
+               if (ty.isParameterizedType()) {
+                       // ======= parameterized types ================
+                       ResolvedType rt = resolveGenericTypeFor(ty, allowMissing);
+                       if (rt.isMissing())
+                               return rt;
+                       ReferenceType genericType = (ReferenceType) rt;
+                       ReferenceType parameterizedType = TypeFactory.createParameterizedType(genericType, ty.typeParameters, this);
+                       return parameterizedType;
+
+               } else if (ty.isGenericType()) {
+                       // ======= generic types ======================
+                       ReferenceType genericType = (ReferenceType) resolveGenericTypeFor(ty, false);
+                       return genericType;
+
+               } else if (ty.isGenericWildcard()) {
+                       // ======= generic wildcard types =============
+                       return resolveGenericWildcardFor((WildcardedUnresolvedType) ty);
+               } else {
+                       // ======= simple and raw types ===============
+                       String erasedSignature = ty.getErasureSignature();
+                       ReferenceType simpleOrRawType = new ReferenceType(erasedSignature, this);
+                       if (ty.needsModifiableDelegate())
+                               simpleOrRawType.setNeedsModifiableDelegate(true);
+                       ReferenceTypeDelegate delegate = resolveDelegate(simpleOrRawType);
+                       // 117854
+                       // if (delegate == null) return ResolvedType.MISSING;
+                       if (delegate == null)
+                               return new MissingResolvedTypeWithKnownSignature(ty.getSignature(), erasedSignature, this);// ResolvedType
+                       // .
+                       // MISSING
+                       // ;
+
+                       if (delegate.isGeneric() && behaveInJava5Way) {
+                               // ======== raw type ===========
+                               simpleOrRawType.typeKind = TypeKind.RAW;
+                               ReferenceType genericType = makeGenericTypeFrom(delegate, simpleOrRawType);
+                               // name =
+                               // ReferenceType.fromTypeX(UnresolvedType.forRawTypeNames(
+                               // ty.getName()),this);
+                               simpleOrRawType.setDelegate(delegate);
+                               genericType.setDelegate(delegate);
+                               simpleOrRawType.setGenericType(genericType);
+                               return simpleOrRawType;
+
+                       } else {
+                               // ======== simple type =========
+                               simpleOrRawType.setDelegate(delegate);
+                               return simpleOrRawType;
+                       }
+               }
+       }
+
+       /**
+        * Attempt to resolve a type that should be a generic type.
+        */
+       public ResolvedType resolveGenericTypeFor(UnresolvedType anUnresolvedType, boolean allowMissing) {
+               // Look up the raw type by signature
+               String rawSignature = anUnresolvedType.getRawType().getSignature();
+               ResolvedType rawType = typeMap.get(rawSignature);
+               if (rawType == null) {
+                       rawType = resolve(UnresolvedType.forSignature(rawSignature), allowMissing);
+                       typeMap.put(rawSignature, rawType);
+               }
+               if (rawType.isMissing())
+                       return rawType;
+
+               // Does the raw type know its generic form? (It will if we created the
+               // raw type from a source type, it won't if its been created just
+               // through
+               // being referenced, e.g. java.util.List
+               ResolvedType genericType = rawType.getGenericType();
+
+               // There is a special case to consider here (testGenericsBang_pr95993
+               // highlights it)
+               // You may have an unresolvedType for a parameterized type but it
+               // is backed by a simple type rather than a generic type. This occurs
+               // for
+               // inner types of generic types that inherit their enclosing types
+               // type variables.
+               if (rawType.isSimpleType() && (anUnresolvedType.typeParameters == null || anUnresolvedType.typeParameters.length == 0)) {
+                       rawType.world = this;
+                       return rawType;
+               }
+
+               if (genericType != null) {
+                       genericType.world = this;
+                       return genericType;
+               } else {
+                       // Fault in the generic that underpins the raw type ;)
+                       ReferenceTypeDelegate delegate = resolveDelegate((ReferenceType) rawType);
+                       ReferenceType genericRefType = makeGenericTypeFrom(delegate, ((ReferenceType) rawType));
+                       ((ReferenceType) rawType).setGenericType(genericRefType);
+                       genericRefType.setDelegate(delegate);
+                       ((ReferenceType) rawType).setDelegate(delegate);
+                       return genericRefType;
+               }
+       }
+
+       private ReferenceType makeGenericTypeFrom(ReferenceTypeDelegate delegate, ReferenceType rawType) {
+               String genericSig = delegate.getDeclaredGenericSignature();
+               if (genericSig != null) {
+                       return new ReferenceType(UnresolvedType.forGenericTypeSignature(rawType.getSignature(), delegate
+                                       .getDeclaredGenericSignature()), this);
+               } else {
+                       return new ReferenceType(UnresolvedType.forGenericTypeVariables(rawType.getSignature(), delegate.getTypeVariables()),
+                                       this);
+               }
+       }
+
+       /**
+        * Go from an unresolved generic wildcard (represented by UnresolvedType) to a resolved version (BoundedReferenceType).
+        */
+       private ReferenceType resolveGenericWildcardFor(WildcardedUnresolvedType aType) {
+               BoundedReferenceType ret = null;
+               // FIXME asc doesnt take account of additional interface bounds (e.g. ?
+               // super R & Serializable - can you do that?)
+               if (aType.isExtends()) {
+                       ReferenceType upperBound = (ReferenceType) resolve(aType.getUpperBound());
+                       ret = new BoundedReferenceType(upperBound, true, this);
+               } else if (aType.isSuper()) {
+                       ReferenceType lowerBound = (ReferenceType) resolve(aType.getLowerBound());
+                       ret = new BoundedReferenceType(lowerBound, false, this);
+               } else {
+                       // must be ? on its own!
+                       ret = new BoundedReferenceType("*", "Ljava/lang/Object", this);
+               }
+               return ret;
+       }
+
+       /**
+        * Find the ReferenceTypeDelegate behind this reference type so that it can fulfill its contract.
+        */
+       protected abstract ReferenceTypeDelegate resolveDelegate(ReferenceType ty);
+
+       /**
+        * Special resolution for "core" types like OBJECT. These are resolved just like any other type, but if they are not found it is
+        * more serious and we issue an error message immediately.
+        */
+       // OPTIMIZE streamline path for core types? They are just simple types,
+       // could look straight in the typemap?
+       public ResolvedType getCoreType(UnresolvedType tx) {
+               ResolvedType coreTy = resolve(tx, true);
+               if (coreTy.isMissing()) {
+                       MessageUtil.error(messageHandler, WeaverMessages.format(WeaverMessages.CANT_FIND_CORE_TYPE, tx.getName()));
+               }
+               return coreTy;
+       }
+
+       /**
+        * Lookup a type by signature, if not found then build one and put it in the map.
+        */
+       public ReferenceType lookupOrCreateName(UnresolvedType ty) {
+               String signature = ty.getSignature();
+               ReferenceType ret = lookupBySignature(signature);
+               if (ret == null) {
+                       ret = ReferenceType.fromTypeX(ty, this);
+                       typeMap.put(signature, ret);
+               }
+               return ret;
+       }
+
+       /**
+        * Lookup a reference type in the world by its signature. Returns null if not found.
+        */
+       public ReferenceType lookupBySignature(String signature) {
+               return (ReferenceType) typeMap.get(signature);
+       }
+
+       // ==========================================================================
+       // ===
+       // T Y P E R E S O L U T I O N -- E N D
+       // ==========================================================================
+       // ===
+
+       /**
+        * Member resolution is achieved by resolving the declaring type and then looking up the member in the resolved declaring type.
+        */
+       public ResolvedMember resolve(Member member) {
+               ResolvedType declaring = member.getDeclaringType().resolve(this);
+               if (declaring.isRawType())
+                       declaring = declaring.getGenericType();
+               ResolvedMember ret;
+               if (member.getKind() == Member.FIELD) {
+                       ret = declaring.lookupField(member);
+               } else {
+                       ret = declaring.lookupMethod(member);
+               }
+
+               if (ret != null)
+                       return ret;
+
+               return declaring.lookupSyntheticMember(member);
+       }
+
+       public abstract IWeavingSupport getWeavingSupport();
+
+       /**
+        * Create an advice shadow munger from the given advice attribute
+        */
+       // public abstract Advice createAdviceMunger(AjAttribute.AdviceAttribute
+       // attribute, Pointcut pointcut, Member signature);
+       /**
+        * Create an advice shadow munger for the given advice kind
+        */
+       public final Advice createAdviceMunger(AdviceKind kind, Pointcut p, Member signature, int extraParameterFlags,
+                       IHasSourceLocation loc) {
+               AjAttribute.AdviceAttribute attribute = new AjAttribute.AdviceAttribute(kind, p, extraParameterFlags, loc.getStart(), loc
+                               .getEnd(), loc.getSourceContext());
+               return getWeavingSupport().createAdviceMunger(attribute, p, signature);
+       }
+
+       /**
+        * Same signature as org.aspectj.util.PartialOrder.PartialComparable.compareTo
+        */
+       public int compareByPrecedence(ResolvedType aspect1, ResolvedType aspect2) {
+               return precedenceCalculator.compareByPrecedence(aspect1, aspect2);
+       }
+
+       public Integer getPrecedenceIfAny(ResolvedType aspect1, ResolvedType aspect2) {
+               return precedenceCalculator.getPrecedenceIfAny(aspect1, aspect2);
+       }
+
+       /**
+        * compares by precedence with the additional rule that a super-aspect is sorted before its sub-aspects
+        */
+       public int compareByPrecedenceAndHierarchy(ResolvedType aspect1, ResolvedType aspect2) {
+               return precedenceCalculator.compareByPrecedenceAndHierarchy(aspect1, aspect2);
+       }
+
+       // simple property getter and setters
+       // ===========================================================
+
+       /**
+        * Nobody should hold onto a copy of this message handler, or setMessageHandler won't work right.
+        */
+       public IMessageHandler getMessageHandler() {
+               return messageHandler;
+       }
+
+       public void setMessageHandler(IMessageHandler messageHandler) {
+               if (this.isInPinpointMode()) {
+                       this.messageHandler = new PinpointingMessageHandler(messageHandler);
+               } else {
+                       this.messageHandler = messageHandler;
+               }
+       }
+
+       /**
+        * convenenience method for creating and issuing messages via the message handler - if you supply two locations you will get two
+        * messages.
+        */
+       public void showMessage(Kind kind, String message, ISourceLocation loc1, ISourceLocation loc2) {
+               if (loc1 != null) {
+                       messageHandler.handleMessage(new Message(message, kind, null, loc1));
+                       if (loc2 != null) {
+                               messageHandler.handleMessage(new Message(message, kind, null, loc2));
+                       }
+               } else {
+                       messageHandler.handleMessage(new Message(message, kind, null, loc2));
+               }
+       }
+
+       public void setCrossReferenceHandler(ICrossReferenceHandler xrefHandler) {
+               this.xrefHandler = xrefHandler;
+       }
+
+       /**
+        * Get the cross-reference handler for the world, may be null.
+        */
+       public ICrossReferenceHandler getCrossReferenceHandler() {
+               return xrefHandler;
+       }
+
+       public void setTypeVariableLookupScope(TypeVariableDeclaringElement scope) {
+               typeVariableLookupScope = scope;
+       }
+
+       public TypeVariableDeclaringElement getTypeVariableLookupScope() {
+               return typeVariableLookupScope;
+       }
+
+       public List getDeclareParents() {
+               return crosscuttingMembersSet.getDeclareParents();
+       }
+
+       public List getDeclareAnnotationOnTypes() {
+               return crosscuttingMembersSet.getDeclareAnnotationOnTypes();
+       }
+
+       public List getDeclareAnnotationOnFields() {
+               return crosscuttingMembersSet.getDeclareAnnotationOnFields();
+       }
+
+       public List getDeclareAnnotationOnMethods() {
+               return crosscuttingMembersSet.getDeclareAnnotationOnMethods();
+       }
+
+       public List getDeclareSoft() {
+               return crosscuttingMembersSet.getDeclareSofts();
+       }
+
+       public CrosscuttingMembersSet getCrosscuttingMembersSet() {
+               return crosscuttingMembersSet;
+       }
+
+       public IStructureModel getModel() {
+               return model;
+       }
+
+       public void setModel(IStructureModel model) {
+               this.model = model;
+       }
+
+       public Lint getLint() {
+               return lint;
+       }
+
+       public void setLint(Lint lint) {
+               this.lint = lint;
+       }
+
+       public boolean isXnoInline() {
+               return XnoInline;
+       }
+
+       public void setXnoInline(boolean xnoInline) {
+               XnoInline = xnoInline;
+       }
+
+       public boolean isXlazyTjp() {
+               return XlazyTjp;
+       }
+
+       public void setXlazyTjp(boolean b) {
+               XlazyTjp = b;
+       }
+
+       public boolean isHasMemberSupportEnabled() {
+               return XhasMember;
+       }
+
+       public void setXHasMemberSupportEnabled(boolean b) {
+               XhasMember = b;
+       }
+
+       public boolean isInPinpointMode() {
+               return Xpinpoint;
+       }
+
+       public void setPinpointMode(boolean b) {
+               Xpinpoint = b;
+       }
+
+       public void setBehaveInJava5Way(boolean b) {
+               behaveInJava5Way = b;
+       }
+
+       /**
+        * Set the error and warning threashold which can be taken from CompilerOptions (see bug 129282)
+        * 
+        * @param errorThreshold
+        * @param warningThreshold
+        */
+       public void setErrorAndWarningThreshold(long errorThreshold, long warningThreshold) {
+               this.errorThreshold = errorThreshold;
+               this.warningThreshold = warningThreshold;
+       }
+
+       /**
+        * @return true if ignoring the UnusedDeclaredThrownException and false if this compiler option is set to error or warning
+        */
+       public boolean isIgnoringUnusedDeclaredThrownException() {
+               // the 0x800000 is CompilerOptions.UnusedDeclaredThrownException
+               // which is ASTNode.bit24
+               if ((errorThreshold & 0x800000) != 0 || (warningThreshold & 0x800000) != 0)
+                       return false;
+               return true;
+       }
+
+       public void performExtraConfiguration(String config) {
+               if (config == null)
+                       return;
+               // Bunch of name value pairs to split
+               extraConfiguration = new Properties();
+               int pos = -1;
+               while ((pos = config.indexOf(",")) != -1) {
+                       String nvpair = config.substring(0, pos);
+                       int pos2 = nvpair.indexOf("=");
+                       if (pos2 != -1) {
+                               String n = nvpair.substring(0, pos2);
+                               String v = nvpair.substring(pos2 + 1);
+                               extraConfiguration.setProperty(n, v);
+                       }
+                       config = config.substring(pos + 1);
+               }
+               if (config.length() > 0) {
+                       int pos2 = config.indexOf("=");
+                       if (pos2 != -1) {
+                               String n = config.substring(0, pos2);
+                               String v = config.substring(pos2 + 1);
+                               extraConfiguration.setProperty(n, v);
+                       }
+               }
+               ensureAdvancedConfigurationProcessed();
+       }
+
+       /**
+        * may return null
+        */
+       public Properties getExtraConfiguration() {
+               return extraConfiguration;
+       }
+
+       public final static String xsetWEAVE_JAVA_PACKAGES = "weaveJavaPackages"; // default
+       // false
+       // -
+       // controls
+       // LTW
+       public final static String xsetWEAVE_JAVAX_PACKAGES = "weaveJavaxPackages"; // default
+       // false
+       // -
+       // controls
+       // LTW
+       public final static String xsetCAPTURE_ALL_CONTEXT = "captureAllContext"; // default
+       // false
+       public final static String xsetRUN_MINIMAL_MEMORY = "runMinimalMemory"; // default
+       // true
+       public final static String xsetDEBUG_STRUCTURAL_CHANGES_CODE = "debugStructuralChangesCode"; // default
+       // false
+       public final static String xsetDEBUG_BRIDGING = "debugBridging"; // default
+       // false
+       public final static String xsetBCEL_REPOSITORY_CACHING = "bcelRepositoryCaching";
+       public final static String xsetPIPELINE_COMPILATION = "pipelineCompilation";
+       public final static String xsetGENERATE_STACKMAPS = "generateStackMaps";
+       public final static String xsetPIPELINE_COMPILATION_DEFAULT = "true";
+       public final static String xsetCOMPLETE_BINARY_TYPES = "completeBinaryTypes";
+       public final static String xsetCOMPLETE_BINARY_TYPES_DEFAULT = "false";
+       public final static String xsetBCEL_REPOSITORY_CACHING_DEFAULT = "true";
+       public final static String xsetFAST_PACK_METHODS = "fastPackMethods"; // default
+
+       // TRUE
+
+       public boolean isInJava5Mode() {
+               return behaveInJava5Way;
+       }
+
+       public void setTargetAspectjRuntimeLevel(String s) {
+               targetAspectjRuntimeLevel = s;
+       }
+
+       public void setOptionalJoinpoints(String jps) {
+               if (jps == null)
+                       return;
+               if (jps.indexOf("arrayconstruction") != -1)
+                       optionalJoinpoint_ArrayConstruction = true;
+               if (jps.indexOf("synchronization") != -1)
+                       optionalJoinpoint_Synchronization = true;
+       }
+
+       public boolean isJoinpointArrayConstructionEnabled() {
+               return optionalJoinpoint_ArrayConstruction;
+       }
+
+       public boolean isJoinpointSynchronizationEnabled() {
+               return optionalJoinpoint_Synchronization;
+       }
+
+       public String getTargetAspectjRuntimeLevel() {
+               return targetAspectjRuntimeLevel;
+       }
+
+       // OPTIMIZE are users falling foul of not supplying -1.5 and so targetting
+       // the old runtime?
+       public boolean isTargettingAspectJRuntime12() {
+               boolean b = false; // pr116679
+               if (!isInJava5Mode())
+                       b = true;
+               else
+                       b = getTargetAspectjRuntimeLevel().equals(org.aspectj.weaver.Constants.RUNTIME_LEVEL_12);
+               // System.err.println("Asked if targetting runtime 1.2 , returning: "+b);
+               return b;
+       }
+
+       /*
+        * Map of types in the world, can have 'references' to expendable ones which can be garbage collected to recover memory. An
+        * expendable type is a reference type that is not exposed to the weaver (ie just pulled in for type resolution purposes).
+        */
+       protected static class TypeMap {
+
+               private static boolean debug = false;
+
+               // Strategy for entries in the expendable map
+               public final static int DONT_USE_REFS = 0; // Hang around forever
+               public final static int USE_WEAK_REFS = 1; // Collected asap
+               public final static int USE_SOFT_REFS = 2; // Collected when short on
+               // memory
+
+               // SECRETAPI - Can switch to a policy of choice ;)
+               public static int policy = USE_SOFT_REFS;
+
+               // Map of types that never get thrown away
+               private final Map /* String -> ResolvedType */tMap = new HashMap();
+
+               // Map of types that may be ejected from the cache if we need space
+               private final Map expendableMap = Collections.synchronizedMap(new WeakHashMap());
+
+               private final World w;
+
+               // profiling tools...
+               private boolean memoryProfiling = false;
+               private int maxExpendableMapSize = -1;
+               private int collectedTypes = 0;
+               private final ReferenceQueue rq = new ReferenceQueue();
+
+               private static Trace trace = TraceFactory.getTraceFactory().getTrace(World.TypeMap.class);
+
+               TypeMap(World w) {
+                       if (trace.isTraceEnabled())
+                               trace.enter("<init>", this, w);
+                       this.w = w;
+                       memoryProfiling = false;// !w.getMessageHandler().isIgnoring(Message.
+                       // INFO);
+                       if (trace.isTraceEnabled())
+                               trace.exit("<init>");
+               }
+
+               /**
+                * Add a new type into the map, the key is the type signature. Some types do *not* go in the map, these are ones involving
+                * *member* type variables. The reason is that when all you have is the signature which gives you a type variable name, you
+                * cannot guarantee you are using the type variable in the same way as someone previously working with a similarly named
+                * type variable. So, these do not go into the map: - TypeVariableReferenceType. - ParameterizedType where a member type
+                * variable is involved. - BoundedReferenceType when one of the bounds is a type variable.
+                * 
+                * definition: "member type variables" - a tvar declared on a generic method/ctor as opposed to those you see declared on a
+                * generic type.
+                */
+               public ResolvedType put(String key, ResolvedType type) {
+                       if (type.isParameterizedType() && type.isParameterizedWithTypeVariable()) {
+                               if (debug)
+                                       System.err
+                                                       .println("Not putting a parameterized type that utilises member declared type variables into the typemap: key="
+                                                                       + key + " type=" + type);
+                               return type;
+                       }
+                       if (type.isTypeVariableReference()) {
+                               if (debug)
+                                       System.err.println("Not putting a type variable reference type into the typemap: key=" + key + " type=" + type);
+                               return type;
+                       }
+                       // this test should be improved - only avoid putting them in if one
+                       // of the
+                       // bounds is a member type variable
+                       if (type instanceof BoundedReferenceType) {
+                               if (debug)
+                                       System.err.println("Not putting a bounded reference type into the typemap: key=" + key + " type=" + type);
+                               return type;
+                       }
+                       if (type instanceof MissingResolvedTypeWithKnownSignature) {
+                               if (debug)
+                                       System.err.println("Not putting a missing type into the typemap: key=" + key + " type=" + type);
+                               return type;
+                       }
+
+                       if ((type instanceof ReferenceType) && (((ReferenceType) type).getDelegate() == null) && w.isExpendable(type)) {
+                               if (debug)
+                                       System.err.println("Not putting expendable ref type with null delegate into typemap: key=" + key + " type="
+                                                       + type);
+                               return type;
+                       }
+
+                       if (w.isExpendable(type)) {
+                               // Dont use reference queue for tracking if not profiling...
+                               if (policy == USE_WEAK_REFS) {
+                                       if (memoryProfiling)
+                                               expendableMap.put(key, new WeakReference(type, rq));
+                                       else
+                                               expendableMap.put(key, new WeakReference(type));
+                               } else if (policy == USE_SOFT_REFS) {
+                                       if (memoryProfiling)
+                                               expendableMap.put(key, new SoftReference(type, rq));
+                                       else
+                                               expendableMap.put(key, new SoftReference(type));
+                               } else {
+                                       expendableMap.put(key, type);
+                               }
+                               if (memoryProfiling && expendableMap.size() > maxExpendableMapSize) {
+                                       maxExpendableMapSize = expendableMap.size();
+                               }
+                               return type;
+                       } else {
+                               return (ResolvedType) tMap.put(key, type);
+                       }
+               }
+
+               public void report() {
+                       if (!memoryProfiling)
+                               return;
+                       checkq();
+                       w.getMessageHandler().handleMessage(
+                                       MessageUtil.info("MEMORY: world expendable type map reached maximum size of #" + maxExpendableMapSize
+                                                       + " entries"));
+                       w.getMessageHandler().handleMessage(
+                                       MessageUtil.info("MEMORY: types collected through garbage collection #" + collectedTypes + " entries"));
+               }
+
+               public void checkq() {
+                       if (!memoryProfiling)
+                               return;
+                       while (rq.poll() != null)
+                               collectedTypes++;
+               }
+
+               /**
+                * Lookup a type by its signature, always look in the real map before the expendable map
+                */
+               public ResolvedType get(String key) {
+                       checkq();
+                       ResolvedType ret = (ResolvedType) tMap.get(key);
+                       if (ret == null) {
+                               if (policy == USE_WEAK_REFS) {
+                                       WeakReference ref = (WeakReference) expendableMap.get(key);
+                                       if (ref != null) {
+                                               ret = (ResolvedType) ref.get();
+                                       }
+                               } else if (policy == USE_SOFT_REFS) {
+                                       SoftReference ref = (SoftReference) expendableMap.get(key);
+                                       if (ref != null) {
+                                               ret = (ResolvedType) ref.get();
+                                       }
+                               } else {
+                                       return (ResolvedType) expendableMap.get(key);
+                               }
+                       }
+                       return ret;
+               }
+
+               /** Remove a type from the map */
+               public ResolvedType remove(String key) {
+                       ResolvedType ret = (ResolvedType) tMap.remove(key);
+                       if (ret == null) {
+                               if (policy == USE_WEAK_REFS) {
+                                       WeakReference wref = (WeakReference) expendableMap.remove(key);
+                                       if (wref != null)
+                                               ret = (ResolvedType) wref.get();
+                               } else if (policy == USE_SOFT_REFS) {
+                                       SoftReference wref = (SoftReference) expendableMap.remove(key);
+                                       if (wref != null)
+                                               ret = (ResolvedType) wref.get();
+                               } else {
+                                       ret = (ResolvedType) expendableMap.remove(key);
+                               }
+                       }
+                       return ret;
+               }
+
+               // public ResolvedType[] getAllTypes() {
+               // List/* ResolvedType */results = new ArrayList();
+               //
+               // collectTypes(expendableMap, results);
+               // collectTypes(tMap, results);
+               // return (ResolvedType[]) results.toArray(new
+               // ResolvedType[results.size()]);
+               // }
+               //
+               // private void collectTypes(Map map, List/* ResolvedType */results) {
+               // for (Iterator iterator = map.keySet().iterator();
+               // iterator.hasNext();) {
+               // String key = (String) iterator.next();
+               // ResolvedType type = get(key);
+               // if (type != null)
+               // results.add(type);
+               // else
+               // System.err.println("null!:" + key);
+               // }
+               // }
+
+       }
+
+       /**
+        * Reference types we don't intend to weave may be ejected from the cache if we need the space.
+        */
+       protected boolean isExpendable(ResolvedType type) {
+               return (!type.equals(UnresolvedType.OBJECT) && (!type.isExposedToWeaver()) && (!type.isPrimitiveType()));
+       }
+
+       /**
+        * This class is used to compute and store precedence relationships between aspects.
+        */
+       private static class AspectPrecedenceCalculator {
+
+               private final World world;
+               private final Map cachedResults;
+
+               public AspectPrecedenceCalculator(World forSomeWorld) {
+                       world = forSomeWorld;
+                       cachedResults = new HashMap();
+               }
+
+               /**
+                * Ask every declare precedence in the world to order the two aspects. If more than one declare precedence gives an
+                * ordering, and the orderings conflict, then that's an error.
+                */
+               public int compareByPrecedence(ResolvedType firstAspect, ResolvedType secondAspect) {
+                       PrecedenceCacheKey key = new PrecedenceCacheKey(firstAspect, secondAspect);
+                       if (cachedResults.containsKey(key)) {
+                               return ((Integer) cachedResults.get(key)).intValue();
+                       } else {
+                               int order = 0;
+                               DeclarePrecedence orderer = null; // Records the declare
+                               // precedence statement that
+                               // gives the first ordering
+                               for (Iterator i = world.getCrosscuttingMembersSet().getDeclareDominates().iterator(); i.hasNext();) {
+                                       DeclarePrecedence d = (DeclarePrecedence) i.next();
+                                       int thisOrder = d.compare(firstAspect, secondAspect);
+                                       if (thisOrder != 0) {
+                                               if (orderer == null)
+                                                       orderer = d;
+                                               if (order != 0 && order != thisOrder) {
+                                                       ISourceLocation[] isls = new ISourceLocation[2];
+                                                       isls[0] = orderer.getSourceLocation();
+                                                       isls[1] = d.getSourceLocation();
+                                                       Message m = new Message("conflicting declare precedence orderings for aspects: "
+                                                                       + firstAspect.getName() + " and " + secondAspect.getName(), null, true, isls);
+                                                       world.getMessageHandler().handleMessage(m);
+                                               } else {
+                                                       order = thisOrder;
+                                               }
+                                       }
+                               }
+                               cachedResults.put(key, new Integer(order));
+                               return order;
+                       }
+               }
+
+               public Integer getPrecedenceIfAny(ResolvedType aspect1, ResolvedType aspect2) {
+                       return (Integer) cachedResults.get(new PrecedenceCacheKey(aspect1, aspect2));
+               }
+
+               public int compareByPrecedenceAndHierarchy(ResolvedType firstAspect, ResolvedType secondAspect) {
+                       if (firstAspect.equals(secondAspect))
+                               return 0;
+
+                       int ret = compareByPrecedence(firstAspect, secondAspect);
+                       if (ret != 0)
+                               return ret;
+
+                       if (firstAspect.isAssignableFrom(secondAspect))
+                               return -1;
+                       else if (secondAspect.isAssignableFrom(firstAspect))
+                               return +1;
+
+                       return 0;
+               }
+
+               private static class PrecedenceCacheKey {
+                       public ResolvedType aspect1;
+                       public ResolvedType aspect2;
+
+                       public PrecedenceCacheKey(ResolvedType a1, ResolvedType a2) {
+                               aspect1 = a1;
+                               aspect2 = a2;
+                       }
+
+                       public boolean equals(Object obj) {
+                               if (!(obj instanceof PrecedenceCacheKey))
+                                       return false;
+                               PrecedenceCacheKey other = (PrecedenceCacheKey) obj;
+                               return (aspect1 == other.aspect1 && aspect2 == other.aspect2);
+                       }
+
+                       public int hashCode() {
+                               return aspect1.hashCode() + aspect2.hashCode();
+                       }
+               }
+       }
+
+       public void validateType(UnresolvedType type) {
+       }
+
+       // --- with java5 we can get into a recursive mess if we aren't careful when
+       // resolving types (*cough* java.lang.Enum) ---
+
+       // --- this first map is for java15 delegates which may try and recursively
+       // access the same type variables.
+       // --- I would rather stash this against a reference type - but we don't
+       // guarantee referencetypes are unique for
+       // so we can't :(
+       private final Map workInProgress1 = new HashMap();
+
+       public TypeVariable[] getTypeVariablesCurrentlyBeingProcessed(Class baseClass) {
+               return (TypeVariable[]) workInProgress1.get(baseClass);
+       }
+
+       public void recordTypeVariablesCurrentlyBeingProcessed(Class baseClass, TypeVariable[] typeVariables) {
+               workInProgress1.put(baseClass, typeVariables);
+       }
+
+       public void forgetTypeVariablesCurrentlyBeingProcessed(Class baseClass) {
+               workInProgress1.remove(baseClass);
+       }
+
+       public void setAddSerialVerUID(boolean b) {
+               addSerialVerUID = b;
+       }
+
+       public boolean isAddSerialVerUID() {
+               return addSerialVerUID;
+       }
+
+       /** be careful calling this - pr152257 */
+       public void flush() {
+               typeMap.expendableMap.clear();
+       }
+
+       public void ensureAdvancedConfigurationProcessed() {
+               // Check *once* whether the user has switched asm support off
+               if (!checkedAdvancedConfiguration) {
+                       Properties p = getExtraConfiguration();
+                       if (p != null) {
+
+                               String s = p.getProperty(xsetBCEL_REPOSITORY_CACHING, xsetBCEL_REPOSITORY_CACHING_DEFAULT);
+                               bcelRepositoryCaching = s.equalsIgnoreCase("true");
+                               if (!bcelRepositoryCaching) {
+                                       getMessageHandler().handleMessage(
+                                                       MessageUtil
+                                                                       .info("[bcelRepositoryCaching=false] AspectJ will not use a bcel cache for class information"));
+                               }
+
+                               s = p.getProperty(xsetFAST_PACK_METHODS, "true");
+                               fastMethodPacking = s.equalsIgnoreCase("true");
+
+                               s = p.getProperty(xsetPIPELINE_COMPILATION, xsetPIPELINE_COMPILATION_DEFAULT);
+                               shouldPipelineCompilation = s.equalsIgnoreCase("true");
+
+                               s = p.getProperty(xsetGENERATE_STACKMAPS, "false");
+                               shouldGenerateStackMaps = s.equalsIgnoreCase("true");
+
+                               s = p.getProperty(xsetCOMPLETE_BINARY_TYPES, xsetCOMPLETE_BINARY_TYPES_DEFAULT);
+                               completeBinaryTypes = s.equalsIgnoreCase("true");
+                               if (completeBinaryTypes) {
+                                       getMessageHandler().handleMessage(
+                                                       MessageUtil.info("[completeBinaryTypes=true] Completion of binary types activated"));
+                               }
+
+                               s = p.getProperty(xsetRUN_MINIMAL_MEMORY, "false");
+                               runMinimalMemory = s.equalsIgnoreCase("true");
+                               // if (runMinimalMemory)
+                               // getMessageHandler().handleMessage(MessageUtil.info(
+                               // "[runMinimalMemory=true] Optimizing bcel processing (and cost of performance) to use less memory"
+                               // ));
+
+                               s = p.getProperty(xsetDEBUG_STRUCTURAL_CHANGES_CODE, "false");
+                               forDEBUG_structuralChangesCode = s.equalsIgnoreCase("true");
+
+                               s = p.getProperty(xsetDEBUG_BRIDGING, "false");
+                               forDEBUG_bridgingCode = s.equalsIgnoreCase("true");
+
+                       }
+                       checkedAdvancedConfiguration = true;
+               }
+       }
+
+       public boolean isRunMinimalMemory() {
+               ensureAdvancedConfigurationProcessed();
+               return runMinimalMemory;
+       }
+
+       public boolean shouldFastPackMethods() {
+               ensureAdvancedConfigurationProcessed();
+               return fastMethodPacking;
+       }
+
+       public boolean shouldPipelineCompilation() {
+               ensureAdvancedConfigurationProcessed();
+               return shouldPipelineCompilation;
+       }
+
+       public boolean shouldGenerateStackMaps() {
+               ensureAdvancedConfigurationProcessed();
+               return shouldGenerateStackMaps;
+       }
+
+       public void setIncrementalCompileCouldFollow(boolean b) {
+               incrementalCompileCouldFollow = b;
+       }
+
+       public boolean couldIncrementalCompileFollow() {
+               return incrementalCompileCouldFollow;
+       }
+
+       public void setSynchronizationPointcutsInUse() {
+               if (trace.isTraceEnabled())
+                       trace.enter("setSynchronizationPointcutsInUse", this);
+               synchronizationPointcutsInUse = true;
+               if (trace.isTraceEnabled())
+                       trace.exit("setSynchronizationPointcutsInUse");
+       }
+
+       public boolean areSynchronizationPointcutsInUse() {
+               return synchronizationPointcutsInUse;
+       }
+
+       /**
+        * Register a new pointcut designator handler with the world - this can be used by any pointcut parsers attached to the world.
+        * 
+        * @param designatorHandler handler for the new pointcut
+        */
+       public void registerPointcutHandler(PointcutDesignatorHandler designatorHandler) {
+               if (pointcutDesignators == null)
+                       pointcutDesignators = new HashSet();
+               pointcutDesignators.add(designatorHandler);
+       }
+
+       public Set getRegisteredPointcutHandlers() {
+               if (pointcutDesignators == null)
+                       return Collections.EMPTY_SET;
+               return pointcutDesignators;
+       }
+
+       public void reportMatch(ShadowMunger munger, Shadow shadow) {
+
+       }
+
+       public void reportCheckerMatch(Checker checker, Shadow shadow) {
+       }
+
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/XlintDefault.properties b/org.aspectj.matcher/src/org/aspectj/weaver/XlintDefault.properties
new file mode 100644 (file)
index 0000000..f88f24e
--- /dev/null
@@ -0,0 +1,47 @@
+invalidAbsoluteTypeName = warning
+invalidWildcardTypeName = ignore
+
+unresolvableMember = warning
+
+typeNotExposedToWeaver = warning
+
+shadowNotInStructure = ignore
+
+unmatchedSuperTypeInCall = warning
+
+canNotImplementLazyTjp = ignore
+multipleAdviceStoppingLazyTjp=ignore
+noGuardForLazyTjp=ignore
+
+uncheckedAdviceConversion = warning
+
+needsSerialVersionUIDField = ignore
+brokeSerialVersionCompatibility = ignore
+
+noInterfaceCtorJoinpoint = warning
+
+noJoinpointsForBridgeMethods = warning
+cantMatchArrayTypeOnVarargs = ignore
+enumAsTargetForDecpIgnored = warning
+annotationAsTargetForDecpIgnored = warning
+adviceDidNotMatch = warning
+invalidTargetForAnnotation = warning
+elementAlreadyAnnotated = warning
+runtimeExceptionNotSoftened = warning
+uncheckedArgument = warning
+noExplicitConstructorCall = warning
+
+aspectExcludedByConfiguration = ignore
+
+unmatchedTargetKind = warning
+
+cantFindType = error
+cantFindTypeAffectingJPMatch = warning
+
+unorderedAdviceAtShadow=ignore
+swallowedExceptionInCatchBlock=ignore
+calculatingSerialVersionUID=ignore
+advisingSynchronizedMethods=warning
+mustWeaveXmlDefinedAspects=warning
+
+missingAspectForReweaving=error
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/ASTNode.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/ASTNode.java
new file mode 100644 (file)
index 0000000..7e8b083
--- /dev/null
@@ -0,0 +1,22 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+public abstract class ASTNode {
+
+    public ASTNode() {
+        super();
+    }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/And.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/And.java
new file mode 100644 (file)
index 0000000..8679d48
--- /dev/null
@@ -0,0 +1,51 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+
+public class And extends Test {
+       Test left, right;
+
+       public And(Test left, Test right) {
+               super();
+               this.left = left;
+               this.right = right;
+       }
+
+       public void accept(ITestVisitor v) {
+               v.visit(this);
+       }
+       
+       public String toString() {
+               return "(" + left + " && " + right + ")";
+       }
+
+       public boolean equals(Object other) {
+               if (other instanceof And) {
+                       And o = (And) other;
+                       return o.left.equals(left) && o.right.equals(right);
+               } else {
+                       return false;
+               }
+       }
+
+    public Test getLeft() {
+        return left;
+    }
+
+    public Test getRight() {
+        return right;
+    }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/Call.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/Call.java
new file mode 100644 (file)
index 0000000..1a1b52a
--- /dev/null
@@ -0,0 +1,41 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.Member;
+
+public class Call extends Test {
+       // assert m.return value is boolean
+       private final Member method;
+       private final Expr[] args;
+
+       public Call(Member m, Expr[] args) {
+               super();
+               this.method = m;
+               this.args = args;
+       }
+
+       public void accept(ITestVisitor v) {
+               v.visit(this);
+       }
+
+       public Expr[] getArgs() {
+               return args;
+       }
+
+       public Member getMethod() {
+               return method;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/CallExpr.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/CallExpr.java
new file mode 100644 (file)
index 0000000..e8191a4
--- /dev/null
@@ -0,0 +1,48 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ResolvedType;
+
+public class CallExpr extends Expr {
+       // assert m.return value is boolean
+       private final Member method;
+       private final Expr[] args;
+       private final ResolvedType returnType; // yes, stored in method as well, but that one isn't resolved
+
+       public CallExpr(Member m, Expr[] args, ResolvedType returnType) {
+               super();
+               this.method = m;
+               this.args = args;
+               this.returnType = returnType;
+       }
+
+       public void accept(IExprVisitor v) {
+               v.visit(this);
+       }
+
+       public Expr[] getArgs() {
+               return args;
+       }
+
+       public Member getMethod() {
+               return method;
+       }
+
+       public ResolvedType getType() {
+               return returnType;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/Expr.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/Expr.java
new file mode 100644 (file)
index 0000000..1b22c8f
--- /dev/null
@@ -0,0 +1,34 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ResolvedType;
+
+public abstract class Expr extends ASTNode {
+
+       public Expr() {
+               super();
+       }
+
+       public static final Expr[] NONE = new Expr[0];
+
+       public abstract void accept(IExprVisitor v);
+
+       public abstract ResolvedType getType();
+
+       public static CallExpr makeCallExpr(Member member, Expr[] exprs, ResolvedType returnType) {
+               return new CallExpr(member, exprs, returnType);
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/FieldGet.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/FieldGet.java
new file mode 100644 (file)
index 0000000..2e145e3
--- /dev/null
@@ -0,0 +1,44 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ResolvedType;
+
+public class FieldGet extends Expr {
+       Member field;
+       ResolvedType resolvedType;
+
+       public FieldGet(Member field, ResolvedType resolvedType) {
+               super();
+               this.field = field;
+               this.resolvedType = resolvedType;
+       }
+
+       public ResolvedType getType() {
+               return resolvedType;
+       }
+
+       public String toString() {
+               return "(FieldGet " + field + ")";
+       }
+
+       public void accept(IExprVisitor v) {
+               v.visit(this);
+       }
+
+       public Member getField() {
+               return field;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/FieldGetCall.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/FieldGetCall.java
new file mode 100644 (file)
index 0000000..64aaf4b
--- /dev/null
@@ -0,0 +1,47 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.Member;
+
+public class FieldGetCall extends Test {
+       // assert m.return value is boolean
+       private final Member field;
+       private final Member method;
+       private final Expr[] args;
+
+       public FieldGetCall(Member f, Member m, Expr[] args) {
+               super();
+               this.field = f;
+               this.method = m;
+               this.args = args;
+       }
+
+       public void accept(ITestVisitor v) {
+               v.visit(this);
+       }
+
+       public Expr[] getArgs() {
+               return args;
+       }
+
+       public Member getMethod() {
+               return method;
+       }
+
+       public Member getField() {
+               return field;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/HasAnnotation.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/HasAnnotation.java
new file mode 100644 (file)
index 0000000..885e9d0
--- /dev/null
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+
+public class HasAnnotation extends Test {
+
+    private Var v;
+    private ResolvedType annType;
+    
+    public HasAnnotation(Var v, ResolvedType annType) {
+        super();
+        this.v = v;
+        this.annType = annType;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.aspectj.weaver.ast.Test#accept(org.aspectj.weaver.ast.ITestVisitor)
+     */
+    public void accept(ITestVisitor v) {
+        v.visit(this);
+    }
+
+       public String toString() {
+               return "(" + v + " has annotation @" + annType + ")";
+       }
+
+       public boolean equals(Object other) {
+               if (other instanceof HasAnnotation) {
+                   HasAnnotation o = (HasAnnotation) other;
+                       return o.v.equals(v) && o.annType.equals(annType);
+               } else {
+                       return false;
+               }
+       }
+       
+       public int hashCode() {
+               return v.hashCode()*37+annType.hashCode();
+       }
+
+    public Var getVar() {
+        return v;
+    }
+
+    public UnresolvedType getAnnotationType() {
+        return annType;
+    } 
+    
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/IExprVisitor.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/IExprVisitor.java
new file mode 100644 (file)
index 0000000..89e0b3d
--- /dev/null
@@ -0,0 +1,23 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver.ast;
+
+public interface IExprVisitor {
+
+       void visit(Var i);
+
+       void visit(FieldGet fieldGet);
+
+       void visit(CallExpr callExpr);
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/ITestVisitor.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/ITestVisitor.java
new file mode 100644 (file)
index 0000000..fc99272
--- /dev/null
@@ -0,0 +1,31 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.internal.tools.MatchingContextBasedTest;
+
+
+public interface ITestVisitor {
+
+       void visit(And e);
+       void visit(Instanceof i);
+       void visit(Not not);
+       void visit(Or or);
+       void visit(Literal literal);
+       void visit(Call call);
+       void visit(FieldGetCall fieldGetCall);
+       void visit(HasAnnotation hasAnnotation);
+       void visit(MatchingContextBasedTest matchingContextTest);
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/Instanceof.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/Instanceof.java
new file mode 100644 (file)
index 0000000..feec6a2
--- /dev/null
@@ -0,0 +1,56 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.UnresolvedType;
+
+public class Instanceof extends Test {
+       Var var;
+       UnresolvedType type;
+
+       public Instanceof(Var left, UnresolvedType right) {
+               super();
+               this.var = left;
+               this.type = right;
+       }
+
+       public void accept(ITestVisitor v) {
+               v.visit(this);
+       }
+       
+       public String toString() {
+               return "(" + var + " instanceof " + type + ")";
+       }
+
+       public boolean equals(Object other) {
+               if (other instanceof Instanceof) {
+                       Instanceof o = (Instanceof) other;
+                       return o.var.equals(var) && o.type.equals(type);
+               } else {
+                       return false;
+               }
+       }
+       
+       public int hashCode() {
+               return var.hashCode()*37+type.hashCode();
+       }
+
+    public Var getVar() {
+        return var;
+    }
+
+    public UnresolvedType getType() {
+        return type;
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/Literal.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/Literal.java
new file mode 100644 (file)
index 0000000..bb7968e
--- /dev/null
@@ -0,0 +1,39 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+
+public final class Literal extends Test {
+
+       boolean noTest;
+       boolean val;
+
+       private Literal(boolean val, boolean noTest) {
+               super();
+               this.val = val;
+               this.noTest = noTest;
+       }
+       
+       public void accept(ITestVisitor v) {
+               v.visit(this);
+       }
+       
+       public static final Literal TRUE = new Literal(true, false);
+       public static final Literal FALSE = new Literal(false, false);
+//     public static final Literal NO_TEST = new Literal(false, true);
+       
+       public String toString() {
+               return noTest ? "NO_TEST" : val ? "TRUE" : "FALSE";
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/Not.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/Not.java
new file mode 100644 (file)
index 0000000..366a193
--- /dev/null
@@ -0,0 +1,49 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+
+public class Not extends Test {
+       Test test;
+
+       public Not(Test test) {
+               super();
+               this.test = test;
+       }
+
+       public void accept(ITestVisitor v) {
+               v.visit(this);
+       }
+       
+       public Test getBody() {
+               return test;
+       }
+       
+       public String toString() {
+               return "!" + test;
+       }
+
+       public boolean equals(Object other) {
+               if (other instanceof Not) {
+                       Not o = (Not) other;
+                       return o.test.equals(test);
+               } else {
+                       return false;
+               }
+       }
+       
+       public int hashCode() {
+               return test.hashCode();
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/Or.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/Or.java
new file mode 100644 (file)
index 0000000..b3143df
--- /dev/null
@@ -0,0 +1,56 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+public class Or extends Test {
+       Test left, right;
+
+       public Or(Test left, Test right) {
+               super();
+               this.left = left;
+               this.right = right;
+       }
+
+       public void accept(ITestVisitor v) {
+               v.visit(this);
+       }
+       
+       public String toString() {
+               return "(" + left + " || " + right + ")";
+       }
+
+       public boolean equals(Object other) {
+               if (other instanceof Or) {
+                       Or o = (Or) other;
+                       return o.left.equals(left) && o.right.equals(right);
+               } else {
+                       return false;
+               }
+       }
+
+    public int hashCode() {
+        int result = 19;
+        result = 37*result + left.hashCode();
+        result = 37*result + right.hashCode();
+        return result;
+    }
+
+    public Test getLeft() {
+        return left;
+    }
+
+    public Test getRight() {
+        return right;
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/Test.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/Test.java
new file mode 100644 (file)
index 0000000..8da7694
--- /dev/null
@@ -0,0 +1,95 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ResolvedType;
+
+public abstract class Test extends ASTNode {
+
+    public Test() {
+        super();
+    }
+    
+    public abstract void accept(ITestVisitor v);
+    
+    public static Test makeAnd(Test a, Test b) {
+//     if (a == Literal.NO_TEST) return b;
+//     if (b == Literal.NO_TEST) return a;
+        if (a == Literal.TRUE) {
+            if (b == Literal.TRUE) {
+                return a;
+            } else {
+                return b;
+            }
+        } else if (b == Literal.TRUE) {
+            return a;
+        } else if (a == Literal.FALSE || b == Literal.FALSE) {
+            return Literal.FALSE;
+        } else {
+            return new And(a, b);
+        }   
+    }
+    
+    public static Test makeOr(Test a, Test b) {
+//     if (a == Literal.NO_TEST) return a;
+//     if (b == Literal.NO_TEST) return b;
+        if (a == Literal.FALSE) {
+               return b;
+        } else if (b == Literal.FALSE) {
+            return a;
+        } else if (a == Literal.TRUE || b == Literal.TRUE) {
+            return Literal.TRUE;
+        } else {
+            return new Or(a, b);
+        }   
+    }
+    
+    public static Test makeNot(Test a) {
+        if (a instanceof Not) {
+            return ((Not) a).getBody();
+        } else if (a == Literal.TRUE) {
+            return Literal.FALSE;
+        } else if (a == Literal.FALSE) {
+            return Literal.TRUE;
+//        } else if (a == Literal.NO_TEST) {
+//             return a;
+        } else {
+            return new Not(a);
+        }
+    }
+    
+    // uses our special rules that anything matches object
+    public static Test makeInstanceof(Var v, ResolvedType ty) {
+        if (ty.equals(ResolvedType.OBJECT)) return Literal.TRUE;
+        
+        Test e;
+        if (ty.isAssignableFrom(v.getType())) e = Literal.TRUE;
+        else if (! ty.isCoerceableFrom(v.getType())) e = Literal.FALSE;
+        else e = new Instanceof(v, ty);
+        return e;
+    }
+    
+    public static Test makeHasAnnotation(Var v, ResolvedType annTy) {
+        return new HasAnnotation(v,annTy);
+    }
+    
+    public static Test makeCall(Member m, Expr[] args) {
+       return new Call(m, args);
+    }
+    public static Test makeFieldGetCall(Member f, Member m, Expr[] args) {
+       return new FieldGetCall(f, m, args);
+    }
+    
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ast/Var.java b/org.aspectj.matcher/src/org/aspectj/weaver/ast/Var.java
new file mode 100644 (file)
index 0000000..230cfea
--- /dev/null
@@ -0,0 +1,47 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.ResolvedType;
+
+public class Var extends Expr {
+       ResolvedType variableType;
+
+       public Var(ResolvedType variableType) {
+               super();
+               this.variableType = variableType;
+       }
+
+       public ResolvedType getType() {
+               return variableType;
+       }
+
+       public String toString() {
+               return "(Var " + variableType + ")";
+       }
+
+       public void accept(IExprVisitor v) {
+               v.visit(this);
+       }
+
+       /**
+        * For an annotation this will return a variable that can access a specific field of the annotation (of the specified type) TODO
+        * what kind of behaviour happens for two annotation fields of the same type?
+        * 
+        * @param formalType
+        * @return
+        */
+       public Var getAccessorForValue(ResolvedType formalType) {
+               throw new IllegalStateException("Only makes sense for annotation variables");
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/MatchingContextBasedTest.java b/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/MatchingContextBasedTest.java
new file mode 100644 (file)
index 0000000..b5a78e0
--- /dev/null
@@ -0,0 +1,43 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.internal.tools;
+
+import org.aspectj.weaver.ast.ITestVisitor;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.tools.MatchingContext;
+import org.aspectj.weaver.tools.ContextBasedMatcher;
+
+/**
+ * Test that uses MatchingContext to match (or not)
+ *
+ */
+public class MatchingContextBasedTest extends Test {
+
+       private final ContextBasedMatcher matcher;
+       
+       public MatchingContextBasedTest(ContextBasedMatcher pc) {
+               this.matcher = pc;
+       }
+       
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.ast.Test#accept(org.aspectj.weaver.ast.ITestVisitor)
+        */
+       public void accept(ITestVisitor v) {
+               v.visit(this);
+       }
+       
+       public boolean matches(MatchingContext context) {
+               return this.matcher.matchesDynamically(context);
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutDesignatorHandlerBasedPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutDesignatorHandlerBasedPointcut.java
new file mode 100644 (file)
index 0000000..04b1554
--- /dev/null
@@ -0,0 +1,157 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.internal.tools;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.patterns.Bindings;
+import org.aspectj.weaver.patterns.ExposedState;
+import org.aspectj.weaver.patterns.FastMatchInfo;
+import org.aspectj.weaver.patterns.IScope;
+import org.aspectj.weaver.patterns.PatternNodeVisitor;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.reflect.ReflectionFastMatchInfo;
+import org.aspectj.weaver.reflect.ReflectionShadow;
+import org.aspectj.weaver.reflect.ReflectionWorld;
+import org.aspectj.weaver.tools.ContextBasedMatcher;
+import org.aspectj.weaver.tools.MatchingContext;
+
+/**
+ * Implementation of Pointcut that is backed by a user-extension
+ * pointcut designator handler.
+ *
+ */
+public class PointcutDesignatorHandlerBasedPointcut extends Pointcut{
+
+       private final ContextBasedMatcher matcher;
+       private final ReflectionWorld world;
+       
+       public PointcutDesignatorHandlerBasedPointcut(
+                       ContextBasedMatcher expr, 
+                       ReflectionWorld world) {
+               this.matcher = expr;
+               this.world = world;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#getPointcutKind()
+        */
+       public byte getPointcutKind() {
+               return Pointcut.USER_EXTENSION;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
+        */
+       public FuzzyBoolean fastMatch(FastMatchInfo info) {
+               if (info instanceof ReflectionFastMatchInfo) {
+                       try {
+                               return FuzzyBoolean.fromBoolean(
+                                       this.matcher.couldMatchJoinPointsInType(
+                                                       Class.forName(info.getType().getName(),false,world.getClassLoader()),
+                                                       ((ReflectionFastMatchInfo)info).getMatchingContext())
+                                       );
+                       } catch (ClassNotFoundException cnfEx) {
+                               return FuzzyBoolean.MAYBE;
+                       }
+               }
+               throw new IllegalStateException("Can only match user-extension pcds against Reflection FastMatchInfo objects");
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#couldMatchKinds()
+        */
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#matchInternal(org.aspectj.weaver.Shadow)
+        */
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               if (shadow instanceof ReflectionShadow) {
+                       MatchingContext context = ((ReflectionShadow)shadow).getMatchingContext();
+                       org.aspectj.weaver.tools.FuzzyBoolean match = 
+                               this.matcher.matchesStatically(context);
+                       if (match == org.aspectj.weaver.tools.FuzzyBoolean.MAYBE) {
+                               return FuzzyBoolean.MAYBE;
+                       } else if (match == org.aspectj.weaver.tools.FuzzyBoolean.YES) {
+                               return FuzzyBoolean.YES;
+                       } else if (match == org.aspectj.weaver.tools.FuzzyBoolean.NO) {
+                               return FuzzyBoolean.NO;
+                       }
+               }
+               throw new IllegalStateException("Can only match user-extension pcds against Reflection shadows (not BCEL)");
+       }
+       
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings)
+        */
+       protected void resolveBindings(IScope scope, Bindings bindings) {
+               // no-op
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedType, org.aspectj.weaver.ResolvedType, org.aspectj.weaver.IntMap)
+        */
+       protected Pointcut concretize1(ResolvedType inAspect,
+                       ResolvedType declaringType, IntMap bindings) {
+               return this;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#findResidueInternal(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
+        */
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               if (!this.matcher.mayNeedDynamicTest()) {
+                       return Literal.TRUE;
+               } else {
+                       // could be more efficient here!
+                       matchInternal(shadow);
+                       return new MatchingContextBasedTest(this.matcher);
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#parameterizeWith(java.util.Map)
+        */
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               return this;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               throw new UnsupportedOperationException("can't write custom pointcut designator expressions to stream");
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PatternNode#accept(org.aspectj.weaver.patterns.PatternNodeVisitor, java.lang.Object)
+        */
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               //visitor.visit(this);
+               // no-op?
+               return data;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java
new file mode 100644 (file)
index 0000000..29f8e02
--- /dev/null
@@ -0,0 +1,343 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.internal.tools;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.patterns.AbstractPatternNodeVisitor;
+import org.aspectj.weaver.patterns.AnnotationPointcut;
+import org.aspectj.weaver.patterns.ArgsAnnotationPointcut;
+import org.aspectj.weaver.patterns.ArgsPointcut;
+import org.aspectj.weaver.patterns.CflowPointcut;
+import org.aspectj.weaver.patterns.ExposedState;
+import org.aspectj.weaver.patterns.IfPointcut;
+import org.aspectj.weaver.patterns.NotAnnotationTypePattern;
+import org.aspectj.weaver.patterns.NotPointcut;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.patterns.ThisOrTargetAnnotationPointcut;
+import org.aspectj.weaver.patterns.ThisOrTargetPointcut;
+import org.aspectj.weaver.patterns.WithinAnnotationPointcut;
+import org.aspectj.weaver.patterns.WithinCodeAnnotationPointcut;
+import org.aspectj.weaver.reflect.ReflectionFastMatchInfo;
+import org.aspectj.weaver.reflect.ReflectionShadow;
+import org.aspectj.weaver.reflect.ShadowMatchImpl;
+import org.aspectj.weaver.tools.DefaultMatchingContext;
+import org.aspectj.weaver.tools.MatchingContext;
+import org.aspectj.weaver.tools.PointcutExpression;
+import org.aspectj.weaver.tools.PointcutParameter;
+import org.aspectj.weaver.tools.ShadowMatch;
+
+/**
+ * Map from weaver.tools interface to internal Pointcut implementation...
+ */
+public class PointcutExpressionImpl implements PointcutExpression {
+       
+       private World world;
+       private Pointcut pointcut;
+       private String expression;
+       private PointcutParameter[] parameters;
+       private MatchingContext matchContext = new DefaultMatchingContext();
+       
+       public PointcutExpressionImpl(Pointcut pointcut, String expression, PointcutParameter[] params, World inWorld) {
+               this.pointcut = pointcut;
+               this.expression = expression;
+               this.world = inWorld;
+               this.parameters = params;
+               if (this.parameters == null) this.parameters = new PointcutParameter[0];
+       }
+       
+       public Pointcut getUnderlyingPointcut() {
+               return this.pointcut;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.tools.PointcutExpression#setMatchingContext(org.aspectj.weaver.tools.MatchingContext)
+        */
+       public void setMatchingContext(MatchingContext aMatchContext) {
+               this.matchContext = aMatchContext;
+       }
+       
+       public boolean couldMatchJoinPointsInType(Class aClass) {
+               ResolvedType matchType = world.resolve(aClass.getName());
+               ReflectionFastMatchInfo info = new ReflectionFastMatchInfo(matchType,null,this.matchContext);
+               return pointcut.fastMatch(info).maybeTrue();
+       }
+       
+       public boolean mayNeedDynamicTest() {
+               HasPossibleDynamicContentVisitor visitor = new HasPossibleDynamicContentVisitor();
+               pointcut.traverse(visitor, null);
+               return visitor.hasDynamicContent();
+       }
+       
+       private ExposedState getExposedState() {
+               return new ExposedState(parameters.length);
+       }
+
+       public ShadowMatch matchesMethodExecution(Method aMethod) {
+               return matchesExecution(aMethod);
+       }
+       
+       public ShadowMatch matchesConstructorExecution(Constructor aConstructor) {
+               return matchesExecution(aConstructor);
+       }
+       
+       private ShadowMatch matchesExecution(Member aMember) {
+               Shadow s = ReflectionShadow.makeExecutionShadow(world, aMember,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(aMember);
+               sm.setWithinCode(null);
+               sm.setWithinType(aMember.getDeclaringClass());
+               return sm;
+       }
+       
+       public ShadowMatch matchesStaticInitialization(Class aClass) {
+               Shadow s = ReflectionShadow.makeStaticInitializationShadow(world, aClass,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(null);
+               sm.setWithinCode(null);
+               sm.setWithinType(aClass);
+               return sm;
+       }       
+       
+       public ShadowMatch matchesAdviceExecution(Method aMethod) {
+               Shadow s = ReflectionShadow.makeAdviceExecutionShadow(world, aMethod,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(aMethod);
+               sm.setWithinCode(null);
+               sm.setWithinType(aMethod.getDeclaringClass());
+               return sm;
+       }
+       
+       public ShadowMatch matchesInitialization(Constructor aConstructor) {
+               Shadow s = ReflectionShadow.makeInitializationShadow(world, aConstructor,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(aConstructor);
+               sm.setWithinCode(null);
+               sm.setWithinType(aConstructor.getDeclaringClass());
+               return sm;
+       }
+       
+       public ShadowMatch matchesPreInitialization(Constructor aConstructor) {
+               Shadow s = ReflectionShadow.makePreInitializationShadow(world, aConstructor,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(aConstructor);
+               sm.setWithinCode(null);
+               sm.setWithinType(aConstructor.getDeclaringClass());
+               return sm;
+       }
+       
+       public ShadowMatch matchesMethodCall(Method aMethod, Member withinCode) {
+               Shadow s = ReflectionShadow.makeCallShadow(world, aMethod, withinCode,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(aMethod);
+               sm.setWithinCode(withinCode);
+               sm.setWithinType(withinCode.getDeclaringClass());
+               return sm;
+       }
+       
+       public ShadowMatch matchesMethodCall(Method aMethod, Class callerType) {
+               Shadow s = ReflectionShadow.makeCallShadow(world, aMethod, callerType,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(aMethod);
+               sm.setWithinCode(null);
+               sm.setWithinType(callerType);
+               return sm;
+       }
+       
+       public ShadowMatch matchesConstructorCall(Constructor aConstructor, Class callerType) {
+               Shadow s = ReflectionShadow.makeCallShadow(world, aConstructor, callerType,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(aConstructor);
+               sm.setWithinCode(null);
+               sm.setWithinType(callerType);
+               return sm;
+       }
+       
+       public ShadowMatch matchesConstructorCall(Constructor aConstructor, Member withinCode) {
+               Shadow s = ReflectionShadow.makeCallShadow(world, aConstructor,withinCode,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(aConstructor);
+               sm.setWithinCode(withinCode);
+               sm.setWithinType(withinCode.getDeclaringClass());
+               return sm;
+       }
+
+       public ShadowMatch matchesHandler(Class exceptionType, Class handlingType) {
+               Shadow s = ReflectionShadow.makeHandlerShadow(world,exceptionType,handlingType,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(null);
+               sm.setWithinCode(null);
+               sm.setWithinType(handlingType);
+               return sm;
+       }
+       
+       public ShadowMatch matchesHandler(Class exceptionType, Member withinCode) {
+               Shadow s = ReflectionShadow.makeHandlerShadow(world,exceptionType,withinCode,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(null);
+               sm.setWithinCode(withinCode);
+               sm.setWithinType(withinCode.getDeclaringClass());
+               return sm;
+       }
+       
+       public ShadowMatch matchesFieldGet(Field aField, Class withinType) {
+               Shadow s = ReflectionShadow.makeFieldGetShadow(world, aField, withinType,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(aField);
+               sm.setWithinCode(null);
+               sm.setWithinType(withinType);
+               return sm;
+       }
+       
+       public ShadowMatch matchesFieldGet(Field aField, Member withinCode) {
+               Shadow s = ReflectionShadow.makeFieldGetShadow(world, aField, withinCode,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(aField);
+               sm.setWithinCode(withinCode);
+               sm.setWithinType(withinCode.getDeclaringClass());
+               return sm;
+       }
+       
+       public ShadowMatch matchesFieldSet(Field aField, Class withinType) {
+               Shadow s = ReflectionShadow.makeFieldSetShadow(world, aField, withinType,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(aField);
+               sm.setWithinCode(null);
+               sm.setWithinType(withinType);
+               return sm;
+       }
+       
+       public ShadowMatch matchesFieldSet(Field aField, Member withinCode) {
+               Shadow s = ReflectionShadow.makeFieldSetShadow(world, aField, withinCode,this.matchContext);
+               ShadowMatchImpl sm = getShadowMatch(s);
+               sm.setSubject(aField);
+               sm.setWithinCode(withinCode);
+               sm.setWithinType(withinCode.getDeclaringClass());
+               return sm;
+       }
+       
+       private ShadowMatchImpl getShadowMatch(Shadow forShadow) {
+               org.aspectj.util.FuzzyBoolean match = pointcut.match(forShadow);
+               Test residueTest = Literal.TRUE;
+               ExposedState state = getExposedState();
+               if (match.maybeTrue()) {
+                       residueTest = pointcut.findResidue(forShadow, state);
+               }
+               ShadowMatchImpl sm = new ShadowMatchImpl(match,residueTest,state,parameters);
+               sm.setMatchingContext(this.matchContext);
+               return sm;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.tools.PointcutExpression#getPointcutExpression()
+        */
+       public String getPointcutExpression() {
+               return expression;
+       }
+
+       private static class HasPossibleDynamicContentVisitor extends AbstractPatternNodeVisitor {
+               private boolean hasDynamicContent = false;
+               
+               public boolean hasDynamicContent() { return hasDynamicContent; }
+               
+               public Object visit(WithinAnnotationPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+               
+               public Object visit(WithinCodeAnnotationPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+               
+               public Object visit(AnnotationPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+               
+               public Object visit(ArgsAnnotationPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+               
+               public Object visit(ArgsPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+
+               public Object visit(CflowPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+               
+               public Object visit(IfPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+               
+               public Object visit(NotAnnotationTypePattern node, Object data) {
+                       return node.getNegatedPattern().accept(this, data);
+               }
+               
+               public Object visit(NotPointcut node, Object data) {
+                       return node.getNegatedPointcut().accept(this, data);
+               }
+               
+               public Object visit(ThisOrTargetAnnotationPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+               
+               public Object visit(ThisOrTargetPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+               
+       }
+       
+       public static class Handler implements Member {
+
+               private Class decClass;
+               private Class exType;
+               
+               public Handler(Class decClass, Class exType) {
+                       this.decClass = decClass;
+                       this.exType = exType;
+               }
+               
+               public int getModifiers() {
+                       return 0;
+               }
+
+               public Class getDeclaringClass() {
+                       return decClass;
+               }
+
+               public String getName() {
+                       return null;
+               }
+
+               public Class getHandledExceptionType() {
+                       return exType;
+               }
+
+               public boolean isSynthetic() {
+                       return false;
+               }
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/TypePatternMatcherImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/TypePatternMatcherImpl.java
new file mode 100644 (file)
index 0000000..8ce4bce
--- /dev/null
@@ -0,0 +1,34 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.internal.tools;
+
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.patterns.TypePattern;
+import org.aspectj.weaver.reflect.ReflectionBasedReferenceTypeDelegateFactory;
+import org.aspectj.weaver.tools.TypePatternMatcher;
+
+public class TypePatternMatcherImpl implements TypePatternMatcher {
+
+       private final TypePattern pattern;
+       private final World world;
+
+       public TypePatternMatcherImpl(TypePattern pattern, World world) {
+               this.pattern = pattern;
+               this.world = world;             
+       }
+       
+       public boolean matches(Class aClass) {
+               ResolvedType rt = 
+                       ReflectionBasedReferenceTypeDelegateFactory.resolveTypeInWorld(aClass,world);
+               return pattern.matchesStatically(rt);
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java
new file mode 100644 (file)
index 0000000..1423443
--- /dev/null
@@ -0,0 +1,467 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.patterns.Pointcut.MatchesNothingPointcut;
+
+/**
+ * @author colyer
+ * 
+ */
+public abstract class AbstractPatternNodeVisitor implements PatternNodeVisitor {
+
+       public Object visit(AnyTypePattern node, Object data) {
+               return node;
+       }
+
+       public Object visit(NoTypePattern node, Object data) {
+               return node;
+       }
+
+       public Object visit(EllipsisTypePattern node, Object data) {
+               return node;
+       }
+
+       public Object visit(AnyWithAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       public Object visit(AnyAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       public Object visit(EllipsisAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       public Object visit(AndAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       public Object visit(AndPointcut node, Object data) {
+               return node;
+       }
+
+       public Object visit(AndTypePattern node, Object data) {
+               return node;
+       }
+
+       public Object visit(AnnotationPatternList node, Object data) {
+               return node;
+       }
+
+       public Object visit(AnnotationPointcut node, Object data) {
+               return node;
+       }
+
+       public Object visit(ArgsAnnotationPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ArgsPointcut, java.lang.Object)
+        */
+       public Object visit(ArgsPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.BindingAnnotationTypePattern,
+        * java.lang.Object)
+        */
+       public Object visit(BindingAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.BindingTypePattern, java.lang.Object)
+        */
+       public Object visit(BindingTypePattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.CflowPointcut, java.lang.Object)
+        */
+       public Object visit(CflowPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ConcreteCflowPointcut, java.lang.Object)
+        */
+       public Object visit(ConcreteCflowPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.DeclareAnnotation, java.lang.Object)
+        */
+       public Object visit(DeclareAnnotation node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.DeclareErrorOrWarning, java.lang.Object)
+        */
+       public Object visit(DeclareErrorOrWarning node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.DeclareParents, java.lang.Object)
+        */
+       public Object visit(DeclareParents node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.DeclarePrecedence, java.lang.Object)
+        */
+       public Object visit(DeclarePrecedence node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.DeclareSoft, java.lang.Object)
+        */
+       public Object visit(DeclareSoft node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ExactAnnotationTypePattern,
+        * java.lang.Object)
+        */
+       public Object visit(ExactAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ExactTypePattern, java.lang.Object)
+        */
+       public Object visit(ExactTypePattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.HandlerPointcut, java.lang.Object)
+        */
+       public Object visit(HandlerPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.IfPointcut, java.lang.Object)
+        */
+       public Object visit(IfPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.KindedPointcut, java.lang.Object)
+        */
+       public Object visit(KindedPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ModifiersPattern, java.lang.Object)
+        */
+       public Object visit(ModifiersPattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.NamePattern, java.lang.Object)
+        */
+       public Object visit(NamePattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.NotAnnotationTypePattern,
+        * java.lang.Object)
+        */
+       public Object visit(NotAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.NotPointcut, java.lang.Object)
+        */
+       public Object visit(NotPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.NotTypePattern, java.lang.Object)
+        */
+       public Object visit(NotTypePattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.OrAnnotationTypePattern, java.lang.Object)
+        */
+       public Object visit(OrAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.OrPointcut, java.lang.Object)
+        */
+       public Object visit(OrPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.OrTypePattern, java.lang.Object)
+        */
+       public Object visit(OrTypePattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.PerCflow, java.lang.Object)
+        */
+       public Object visit(PerCflow node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.PerFromSuper, java.lang.Object)
+        */
+       public Object visit(PerFromSuper node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.PerObject, java.lang.Object)
+        */
+       public Object visit(PerObject node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.PerSingleton, java.lang.Object)
+        */
+       public Object visit(PerSingleton node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.PerTypeWithin, java.lang.Object)
+        */
+       public Object visit(PerTypeWithin node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.PatternNode, java.lang.Object)
+        */
+       public Object visit(PatternNode node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ReferencePointcut, java.lang.Object)
+        */
+       public Object visit(ReferencePointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.SignaturePattern, java.lang.Object)
+        */
+       public Object visit(SignaturePattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ThisOrTargetAnnotationPointcut,
+        * java.lang.Object)
+        */
+       public Object visit(ThisOrTargetAnnotationPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ThisOrTargetPointcut, java.lang.Object)
+        */
+       public Object visit(ThisOrTargetPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ThrowsPattern, java.lang.Object)
+        */
+       public Object visit(ThrowsPattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.TypePatternList, java.lang.Object)
+        */
+       public Object visit(TypePatternList node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.WildAnnotationTypePattern,
+        * java.lang.Object)
+        */
+       public Object visit(WildAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.WildTypePattern, java.lang.Object)
+        */
+       public Object visit(WildTypePattern node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.WithinAnnotationPointcut,
+        * java.lang.Object)
+        */
+       public Object visit(WithinAnnotationPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.WithinCodeAnnotationPointcut,
+        * java.lang.Object)
+        */
+       public Object visit(WithinCodeAnnotationPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.WithinPointcut, java.lang.Object)
+        */
+       public Object visit(WithinPointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.WithincodePointcut, java.lang.Object)
+        */
+       public Object visit(WithincodePointcut node, Object data) {
+               return node;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.Pointcut.MatchesNothingPointcut,
+        * java.lang.Object)
+        */
+       public Object visit(MatchesNothingPointcut node, Object data) {
+               return node;
+       }
+
+       public Object visit(TypeVariablePattern node, Object data) {
+               return node;
+       }
+
+       public Object visit(TypeVariablePatternList node, Object data) {
+               return node;
+       }
+
+       public Object visit(HasMemberTypePattern node, Object data) {
+               return node;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AndAnnotationTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AndAnnotationTypePattern.java
new file mode 100644 (file)
index 0000000..4392a19
--- /dev/null
@@ -0,0 +1,127 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
+import org.aspectj.weaver.ResolvedType;
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class AndAnnotationTypePattern extends AnnotationTypePattern {
+
+       private AnnotationTypePattern left;
+       private AnnotationTypePattern right;
+       
+       public AndAnnotationTypePattern(AnnotationTypePattern left, AnnotationTypePattern right) {
+               this.left = left;
+               this.right = right;
+               setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
+       }
+
+       public FuzzyBoolean matches(AnnotatedElement annotated) {
+               return left.matches(annotated).and(right.matches(annotated));
+       }
+       
+       public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations ) {
+               return left.matches(annotated,parameterAnnotations).and(right.matches(annotated,parameterAnnotations));
+       }
+
+       public void resolve(World world) {
+               left.resolve(world);
+               right.resolve(world);
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.AnnotationTypePattern#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings, boolean)
+        */
+       public AnnotationTypePattern resolveBindings(IScope scope,
+                       Bindings bindings, boolean allowBinding) {
+               left = left.resolveBindings(scope,bindings,allowBinding);
+               right =right.resolveBindings(scope,bindings,allowBinding);
+               return this;
+       }
+       
+       public AnnotationTypePattern parameterizeWith(Map typeVariableMap,World w) {
+               AnnotationTypePattern newLeft = left.parameterizeWith(typeVariableMap,w);
+               AnnotationTypePattern newRight = right.parameterizeWith(typeVariableMap,w);
+               AndAnnotationTypePattern ret = new AndAnnotationTypePattern(newLeft,newRight);
+               ret.copyLocationFrom(this);
+               if (this.isForParameterAnnotationMatch()) ret.setForParameterAnnotationMatch();
+               return ret;
+       }
+       
+       public static AnnotationTypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               AnnotationTypePattern p = new AndAnnotationTypePattern(
+                               AnnotationTypePattern.read(s,context),
+                               AnnotationTypePattern.read(s,context));
+               p.readLocation(context,s);
+               if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160) {
+                       if (s.readBoolean()) p.setForParameterAnnotationMatch();                        
+               }
+               return p;               
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(AnnotationTypePattern.AND);
+               left.write(s);
+               right.write(s);
+               writeLocation(s);
+               s.writeBoolean(isForParameterAnnotationMatch());
+       }
+       
+       public boolean equals(Object obj) {
+               if (!(obj instanceof AndAnnotationTypePattern)) return false;
+               AndAnnotationTypePattern other = (AndAnnotationTypePattern) obj;
+               return (left.equals(other.left) && right.equals(other.right) && left.isForParameterAnnotationMatch()==right.isForParameterAnnotationMatch());
+       }
+       
+       public int hashCode() {
+               int result = 17;
+               result = result*37 + left.hashCode();
+               result = result*37 + right.hashCode();
+               result = result*37 + (isForParameterAnnotationMatch()?0:1);
+               return result;          
+       }
+       
+       public String toString() {
+               return left.toString() + " " + right.toString();
+       }
+       
+       public AnnotationTypePattern getLeft() { return left; }
+       public AnnotationTypePattern getRight() { return right; }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               left.traverse(visitor,ret);
+               right.traverse(visitor,ret);
+               return ret;
+       }
+
+       public void setForParameterAnnotationMatch() {
+               left.setForParameterAnnotationMatch();
+               right.setForParameterAnnotationMatch();
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AndPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AndPointcut.java
new file mode 100644 (file)
index 0000000..58608a7
--- /dev/null
@@ -0,0 +1,129 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Test;
+
+public class AndPointcut extends Pointcut {
+       Pointcut left, right;  // exposed for testing
+
+       private int couldMatchKinds;
+       
+       public AndPointcut(Pointcut left, Pointcut right) {
+               super();
+               this.left = left;
+               this.right = right;
+               this.pointcutKind = AND;
+               setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
+               couldMatchKinds = left.couldMatchKinds() & right.couldMatchKinds();
+       }
+       
+       public int couldMatchKinds() {
+               return couldMatchKinds;
+       }
+
+       public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               return left.fastMatch(type).and(right.fastMatch(type));
+       }
+       
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               FuzzyBoolean leftMatch = left.match(shadow);
+               if (leftMatch.alwaysFalse()) return leftMatch;
+               return leftMatch.and(right.match(shadow));
+       }
+       
+       public String toString() {
+               return "(" + left.toString() + " && " + right.toString() + ")";
+       }
+       
+       public boolean equals(Object other) { 
+               if (!(other instanceof AndPointcut)) return false;
+               AndPointcut o = (AndPointcut)other;
+               return o.left.equals(left) && o.right.equals(right);
+       }
+    
+    public int hashCode() {
+        int result = 19;
+        result = 37*result + left.hashCode();
+        result = 37*result + right.hashCode();
+        return result;
+    }
+
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               left.resolveBindings(scope, bindings);
+               right.resolveBindings(scope, bindings);
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.AND);
+               left.write(s);
+               right.write(s);
+               writeLocation(s);
+       }
+       
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               AndPointcut ret = new AndPointcut(Pointcut.read(s, context), Pointcut.read(s, context));
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               return Test.makeAnd(left.findResidue(shadow, state), right.findResidue(shadow, state));
+       }
+
+       public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               AndPointcut ret =  new AndPointcut(left.concretize(inAspect, declaringType, bindings),
+                                                                                  right.concretize(inAspect, declaringType, bindings));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               AndPointcut ret =  new AndPointcut(left.parameterizeWith(typeVariableMap,w),
+                                                                                   right.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       public Pointcut getLeft() {
+               return left;
+       }
+
+       public Pointcut getRight() {
+               return right;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               left.traverse(visitor,ret);
+               right.traverse(visitor,ret);
+               return ret;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AndTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AndTypePattern.java
new file mode 100644 (file)
index 0000000..ebf79de
--- /dev/null
@@ -0,0 +1,176 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+/**
+ * left && right
+ * 
+ * <p>any binding to formals is explicitly forbidden for any composite by the language
+ * 
+ * @author Erik Hilsdale
+ * @author Jim Hugunin
+ */
+public class AndTypePattern extends TypePattern {
+       private TypePattern left, right;
+       
+       public AndTypePattern(TypePattern left, TypePattern right) {
+               super(false,false);  //?? we override all methods that care about includeSubtypes
+               this.left = left;
+               this.right = right;
+               setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
+       }
+
+       protected boolean couldEverMatchSameTypesAs(TypePattern other) {
+               return true; // don't dive into ands yet....
+       }
+       public FuzzyBoolean matchesInstanceof(ResolvedType type) {
+               return left.matchesInstanceof(type).and(right.matchesInstanceof(type));
+       }
+
+       protected boolean matchesExactly(ResolvedType type) {
+               //??? if these had side-effects, this sort-circuit could be a mistake
+               return left.matchesExactly(type) && right.matchesExactly(type);
+       }
+       
+       protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
+               return left.matchesExactly(type,annotatedType) && right.matchesExactly(type,annotatedType);             
+       }
+       
+       public boolean matchesStatically(ResolvedType type) {
+               return left.matchesStatically(type) && right.matchesStatically(type);
+       }
+       
+       public void setIsVarArgs(boolean isVarArgs) {
+               this.isVarArgs = isVarArgs;
+               left.setIsVarArgs(isVarArgs);
+               right.setIsVarArgs(isVarArgs);
+       }
+       
+       public void setAnnotationTypePattern(AnnotationTypePattern annPatt) {
+               if (annPatt == AnnotationTypePattern.ANY) return;
+               if (left.annotationPattern == AnnotationTypePattern.ANY) {
+                       left.setAnnotationTypePattern(annPatt);
+               } else {
+                       left.setAnnotationTypePattern(
+                                       new AndAnnotationTypePattern(left.annotationPattern,annPatt));
+               }
+               if (right.annotationPattern == AnnotationTypePattern.ANY) {
+                       right.setAnnotationTypePattern(annPatt);                        
+               } else {
+                       right.setAnnotationTypePattern(
+                                       new AndAnnotationTypePattern(right.annotationPattern,annPatt));                 
+               }
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(TypePattern.AND);
+               left.write(s);
+               right.write(s);
+               writeLocation(s);
+       }
+       
+       public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               AndTypePattern ret = new AndTypePattern(TypePattern.read(s, context), TypePattern.read(s, context));
+               ret.readLocation(context, s);
+               if (ret.left.isVarArgs && ret.right.isVarArgs) ret.isVarArgs = true;
+               return ret;
+       }
+
+       public TypePattern resolveBindings(
+               IScope scope,
+               Bindings bindings,
+               boolean allowBinding, boolean requireExactType)
+       {
+               if (requireExactType) return notExactType(scope);
+               left = left.resolveBindings(scope, bindings, false, false);
+               right = right.resolveBindings(scope, bindings, false, false);
+               return this;
+       }
+       
+       public TypePattern parameterizeWith(Map typeVariableMap,World w) {
+               TypePattern newLeft = left.parameterizeWith(typeVariableMap,w);
+               TypePattern newRight = right.parameterizeWith(typeVariableMap,w);
+               AndTypePattern ret = new AndTypePattern(newLeft,newRight);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public String toString() {
+               StringBuffer buff = new StringBuffer();
+               if (annotationPattern != AnnotationTypePattern.ANY) {
+                       buff.append('(');
+                       buff.append(annotationPattern.toString());
+                       buff.append(' ');
+               }
+               buff.append('(');
+               buff.append(left.toString());
+               buff.append(" && ");
+               buff.append(right.toString());
+               buff.append(')');
+               if (annotationPattern != AnnotationTypePattern.ANY) {
+                       buff.append(')');
+               }
+               return buff.toString();
+       }
+
+    public TypePattern getLeft() {
+        return left;
+    }
+
+    public TypePattern getRight() {
+        return right;
+    }
+
+       public boolean equals(Object obj) {
+               if (! (obj instanceof AndTypePattern)) return false;
+               AndTypePattern atp = (AndTypePattern) obj;
+               return left.equals(atp.left) && right.equals(atp.right);
+       }
+
+       public boolean isStarAnnotation() {
+               return left.isStarAnnotation() && right.isStarAnnotation();
+       }
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       public int hashCode() {
+               int ret = 17;
+               ret = ret + 37 * left.hashCode();
+               ret = ret + 37 * right.hashCode();
+               return ret;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               left.traverse(visitor, ret);
+               right.traverse(visitor, ret);
+               return ret;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationPatternList.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationPatternList.java
new file mode 100644 (file)
index 0000000..f423eb3
--- /dev/null
@@ -0,0 +1,203 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class AnnotationPatternList extends PatternNode {
+
+       private AnnotationTypePattern[] typePatterns;
+       int ellipsisCount = 0;
+       
+       public static final AnnotationPatternList EMPTY =
+               new AnnotationPatternList(new AnnotationTypePattern[] {});
+       
+       public static final AnnotationPatternList ANY =
+           new AnnotationPatternList(new AnnotationTypePattern[] {AnnotationTypePattern.ELLIPSIS});
+       
+       public AnnotationPatternList() {
+               typePatterns = new AnnotationTypePattern[0];
+               ellipsisCount = 0;
+       }
+
+       public AnnotationPatternList(AnnotationTypePattern[] arguments) {
+               this.typePatterns = arguments;
+               for (int i=0; i<arguments.length; i++) {
+                       if (arguments[i] == AnnotationTypePattern.ELLIPSIS) ellipsisCount++;
+               }
+       }
+       
+       public AnnotationPatternList(List l) {
+               this((AnnotationTypePattern[]) l.toArray(new AnnotationTypePattern[l.size()]));
+       }
+
+       protected AnnotationTypePattern[] getAnnotationPatterns() {
+               return typePatterns;
+       }
+       
+       public AnnotationPatternList parameterizeWith(Map typeVariableMap,World w) {
+               AnnotationTypePattern[] parameterizedPatterns = new AnnotationTypePattern[this.typePatterns.length];
+               for (int i = 0; i < parameterizedPatterns.length; i++) {
+                       parameterizedPatterns[i] = this.typePatterns[i].parameterizeWith(typeVariableMap,w);
+               }
+               AnnotationPatternList ret = new AnnotationPatternList(parameterizedPatterns);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public void resolve(World inWorld) {
+               for (int i = 0; i < typePatterns.length; i++) {
+                       typePatterns[i].resolve(inWorld);
+               }
+       }
+       
+       public FuzzyBoolean matches(ResolvedType[] someArgs) {
+               // do some quick length tests first
+               int numArgsMatchedByEllipsis = (someArgs.length + ellipsisCount) - typePatterns.length;
+               if (numArgsMatchedByEllipsis < 0) return FuzzyBoolean.NO;
+               if ((numArgsMatchedByEllipsis > 0) && (ellipsisCount == 0)) {
+                       return FuzzyBoolean.NO;
+               }
+               // now work through the args and the patterns, skipping at ellipsis
+       FuzzyBoolean ret = FuzzyBoolean.YES;
+       int argsIndex = 0;
+       for (int i = 0; i < typePatterns.length; i++) {
+                       if (typePatterns[i] == AnnotationTypePattern.ELLIPSIS) {
+                               // match ellipsisMatchCount args
+                               argsIndex += numArgsMatchedByEllipsis;
+                       } else if (typePatterns[i] == AnnotationTypePattern.ANY) {
+                               argsIndex++;
+                       } else {
+                               // match the argument type at argsIndex with the ExactAnnotationTypePattern
+                               // we know it is exact because nothing else is allowed in args
+                               if (someArgs[argsIndex].isPrimitiveType()) return FuzzyBoolean.NO; // can never match
+                               ExactAnnotationTypePattern ap = (ExactAnnotationTypePattern)typePatterns[i];
+                               FuzzyBoolean matches = ap.matchesRuntimeType(someArgs[argsIndex]);
+                               if (matches == FuzzyBoolean.NO) {
+                                       return FuzzyBoolean.MAYBE;  // could still match at runtime
+                               } else {
+                                       argsIndex++;
+                                       ret = ret.and(matches);
+                               }
+                       }
+               }       
+       return ret;
+       }
+       
+       public int size() { return typePatterns.length; }
+       
+       public AnnotationTypePattern get(int index) {
+               return typePatterns[index];
+       }
+
+       public AnnotationPatternList resolveBindings(IScope scope, Bindings bindings, boolean allowBinding) {
+               for (int i=0; i<typePatterns.length; i++) {
+                       AnnotationTypePattern p = typePatterns[i];
+                       if (p != null) {
+                               typePatterns[i] = typePatterns[i].resolveBindings(scope, bindings, allowBinding);
+                       }
+               }
+               return this;
+       }
+       
+       public AnnotationPatternList resolveReferences(IntMap bindings) {
+               int len = typePatterns.length;
+               AnnotationTypePattern[] ret = new AnnotationTypePattern[len];
+               for (int i=0; i < len; i++) {
+                       ret[i] = typePatterns[i].remapAdviceFormals(bindings);
+               }
+               return new AnnotationPatternList(ret);
+       }
+
+    public String toString() {
+       StringBuffer buf = new StringBuffer();
+       buf.append("(");
+       for (int i=0, len=typePatterns.length; i < len; i++) {
+               AnnotationTypePattern type = typePatterns[i];
+               if (i > 0) buf.append(", ");
+               if (type == AnnotationTypePattern.ELLIPSIS) {
+                       buf.append("..");
+               } else {
+                       String annPatt = type.toString();
+                       buf.append(annPatt.startsWith("@") ? annPatt.substring(1) : annPatt);
+               }
+       }
+       buf.append(")");
+       return buf.toString();
+    }
+    
+       public boolean equals(Object other) {
+               if (!(other instanceof AnnotationPatternList)) return false;
+               AnnotationPatternList o = (AnnotationPatternList)other;
+               int len = o.typePatterns.length;
+               if (len != this.typePatterns.length) return false;
+               for (int i=0; i<len; i++) {
+                       if (!this.typePatterns[i].equals(o.typePatterns[i])) return false;
+               }
+               return true;
+       }
+       
+    public int hashCode() {
+        int result = 41;
+        for (int i = 0, len = typePatterns.length; i < len; i++) {
+            result = 37*result + typePatterns[i].hashCode();
+        }
+        return result;
+    }
+    
+       public static AnnotationPatternList read(VersionedDataInputStream s, ISourceContext context) throws IOException  {
+               short len = s.readShort();
+               AnnotationTypePattern[] arguments = new AnnotationTypePattern[len];
+               for (int i=0; i<len; i++) {
+                       arguments[i] = AnnotationTypePattern.read(s, context);
+               }
+               AnnotationPatternList ret = new AnnotationPatternList(arguments);
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeShort(typePatterns.length);
+               for (int i=0; i<typePatterns.length; i++) {
+                       typePatterns[i].write(s);
+               }
+               writeLocation(s);
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor, data);
+               for (int i = 0; i < typePatterns.length; i++) {
+                       typePatterns[i].traverse(visitor,ret);
+               }
+               return ret;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationPointcut.java
new file mode 100644 (file)
index 0000000..184615b
--- /dev/null
@@ -0,0 +1,318 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ConcreteTypeMunger;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.NewFieldTypeMunger;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.ShadowMunger;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.ast.Var;
+
+/**
+ * (at)Annotation((at)Foo) or (at)Annotation(foo)<br>
+ * <p>
+ * Matches any join point where the subject of the join point has an annotation matching the annotationTypePattern:
+ * 
+ * <br>
+ * Join Point Kind - Subject <br>
+ * ================================ <br>
+ * method call - the target method <br>
+ * method execution - the method <br>
+ * constructor call - the constructor <br>
+ * constructor execution - the constructor <br>
+ * get - the target field <br>
+ * set - the target field <br>
+ * adviceexecution - the advice <br>
+ * initialization - the constructor <br>
+ * preinitialization - the constructor <br>
+ * staticinitialization - the type being initialized <br>
+ * handler - the declared type of the handled exception <br>
+ */
+public class AnnotationPointcut extends NameBindingPointcut {
+
+       private ExactAnnotationTypePattern annotationTypePattern;
+       private String declarationText;
+
+       public AnnotationPointcut(ExactAnnotationTypePattern type) {
+               super();
+               this.annotationTypePattern = type;
+               this.pointcutKind = Pointcut.ANNOTATION;
+               buildDeclarationText();
+       }
+
+       public AnnotationPointcut(ExactAnnotationTypePattern type, ShadowMunger munger) {
+               this(type);
+               buildDeclarationText();
+       }
+
+       public ExactAnnotationTypePattern getAnnotationTypePattern() {
+               return annotationTypePattern;
+       }
+
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;
+       }
+
+       public Pointcut parameterizeWith(Map typeVariableMap, World w) {
+               AnnotationPointcut ret = new AnnotationPointcut((ExactAnnotationTypePattern) annotationTypePattern.parameterizeWith(
+                               typeVariableMap, w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
+        */
+       public FuzzyBoolean fastMatch(FastMatchInfo info) {
+               if (info.getKind() == Shadow.StaticInitialization) {
+                       return annotationTypePattern.fastMatches(info.getType());
+               } else {
+                       return FuzzyBoolean.MAYBE;
+               }
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
+        */
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               AnnotatedElement toMatchAgainst = null;
+               Member member = shadow.getSignature();
+               ResolvedMember rMember = member.resolve(shadow.getIWorld());
+
+               if (rMember == null) {
+                       if (member.getName().startsWith(NameMangler.PREFIX)) {
+                               return FuzzyBoolean.NO;
+                       }
+                       shadow.getIWorld().getLint().unresolvableMember.signal(member.toString(), getSourceLocation());
+                       return FuzzyBoolean.NO;
+               }
+
+               Shadow.Kind kind = shadow.getKind();
+               if (kind == Shadow.StaticInitialization) {
+                       toMatchAgainst = rMember.getDeclaringType().resolve(shadow.getIWorld());
+               } else if ((kind == Shadow.ExceptionHandler)) {
+                       toMatchAgainst = rMember.getParameterTypes()[0].resolve(shadow.getIWorld());
+               } else {
+                       toMatchAgainst = rMember;
+                       // FIXME asc I'd like to get rid of this bit of logic altogether, shame ITD fields don't have an effective sig attribute
+                       // FIXME asc perf cache the result of discovering the member that contains the real annotations
+                       if (rMember.isAnnotatedElsewhere()) {
+                               if (kind == Shadow.FieldGet || kind == Shadow.FieldSet) {
+                                       // FIXME asc should include supers with getInterTypeMungersIncludingSupers ?
+                                       List mungers = rMember.getDeclaringType().resolve(shadow.getIWorld()).getInterTypeMungers();
+                                       for (Iterator iter = mungers.iterator(); iter.hasNext();) {
+                                               ConcreteTypeMunger typeMunger = (ConcreteTypeMunger) iter.next();
+                                               if (typeMunger.getMunger() instanceof NewFieldTypeMunger) {
+                                                       ResolvedMember fakerm = typeMunger.getSignature();
+                                                       if (fakerm.equals(member)) {
+                                                               ResolvedMember ajcMethod = AjcMemberMaker.interFieldInitializer(fakerm, typeMunger.getAspectType());
+                                                               ResolvedMember rmm = findMethod(typeMunger.getAspectType(), ajcMethod);
+                                                               toMatchAgainst = rmm;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               annotationTypePattern.resolve(shadow.getIWorld());
+               return annotationTypePattern.matches(toMatchAgainst);
+       }
+
+       private ResolvedMember findMethod(ResolvedType aspectType, ResolvedMember ajcMethod) {
+               ResolvedMember decMethods[] = aspectType.getDeclaredMethods();
+               for (int i = 0; i < decMethods.length; i++) {
+                       ResolvedMember member = decMethods[i];
+                       if (member.equals(ajcMethod))
+                               return member;
+               }
+               return null;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope,
+        * org.aspectj.weaver.patterns.Bindings)
+        */
+       protected void resolveBindings(IScope scope, Bindings bindings) {
+               if (!scope.getWorld().isInJava5Mode()) {
+                       scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.ATANNOTATION_ONLY_SUPPORTED_AT_JAVA5_LEVEL),
+                                       getSourceLocation()));
+                       return;
+               }
+               annotationTypePattern = (ExactAnnotationTypePattern) annotationTypePattern.resolveBindings(scope, bindings, true);
+               // must be either a Var, or an annotation type pattern
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedType, org.aspectj.weaver.IntMap)
+        */
+       protected Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               ExactAnnotationTypePattern newType = (ExactAnnotationTypePattern) annotationTypePattern.remapAdviceFormals(bindings);
+               Pointcut ret = new AnnotationPointcut(newType, bindings.getEnclosingAdvice());
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               if (annotationTypePattern instanceof BindingAnnotationFieldTypePattern) {
+                       if (shadow.getKind() != Shadow.MethodExecution) {
+                               shadow.getIWorld().getMessageHandler().handleMessage(
+                                               MessageUtil.error(
+                                                               "Annotation field binding is only supported at method-execution join points (compiler limitation)",
+                                                               getSourceLocation()));
+                               return Literal.TRUE; // exit quickly, error will prevent weaving
+                       }
+                       BindingAnnotationFieldTypePattern btp = (BindingAnnotationFieldTypePattern) annotationTypePattern;
+                       ResolvedType formalType = btp.getFormalType().resolve(shadow.getIWorld());
+                       UnresolvedType annoType = btp.getAnnotationType();
+                       // TODO 2 need to sort out appropriate creation of the AnnotationAccessFieldVar - what happens for
+                       // reflective (ReflectionShadow) access to types?
+                       Var var = shadow.getKindedAnnotationVar(annoType);
+                       if (var == null) {
+                               throw new BCException("Unexpected problem locating annotation at join point '" + shadow + "'");
+                       }
+                       state.set(btp.getFormalIndex(), var.getAccessorForValue(formalType));
+               } else if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
+                       BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern) annotationTypePattern;
+                       UnresolvedType annotationType = btp.getAnnotationType();
+                       Var var = shadow.getKindedAnnotationVar(annotationType);
+
+                       // At this point, var *could* be null. The only reason this could happen (if we aren't failing...)
+                       // is if another binding annotation designator elsewhere in the pointcut is going to expose the annotation
+                       // eg. (execution(* a*(..)) && @annotation(foo)) || (execution(* b*(..)) && @this(foo))
+                       // where sometimes @annotation will be providing the value, and sometimes
+                       // @this will be providing the value (see pr138223)
+
+                       // If we are here for other indecipherable reasons (it's not the case above...) then
+                       // you might want to uncomment this next bit of code to collect the diagnostics
+                       // if (var == null) throw new BCException("Impossible! annotation=["+annotationType+
+                       // "]  shadow=["+shadow+" at "+shadow.getSourceLocation()+
+                       // "]    pointcut is at ["+getSourceLocation()+"]");
+                       if (var == null) {
+                               if (matchInternal(shadow).alwaysTrue())
+                                       return Literal.TRUE;
+                               else
+                                       return Literal.FALSE;
+                       }
+                       state.set(btp.getFormalIndex(), var);
+               }
+
+               if (matchInternal(shadow).alwaysTrue())
+                       return Literal.TRUE;
+               else
+                       return Literal.FALSE;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
+        */
+       public List getBindingAnnotationTypePatterns() {
+               if (annotationTypePattern instanceof BindingPattern) { // BindingAnnotationTypePattern) {
+                       List l = new ArrayList();
+                       l.add(annotationTypePattern);
+                       return l;
+               } else
+                       return Collections.EMPTY_LIST;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
+        */
+       public List getBindingTypePatterns() {
+               return Collections.EMPTY_LIST;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.ANNOTATION);
+               annotationTypePattern.write(s);
+               writeLocation(s);
+       }
+
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               AnnotationTypePattern type = AnnotationTypePattern.read(s, context);
+               AnnotationPointcut ret = new AnnotationPointcut((ExactAnnotationTypePattern) type);
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof AnnotationPointcut))
+                       return false;
+               AnnotationPointcut o = (AnnotationPointcut) other;
+               return o.annotationTypePattern.equals(this.annotationTypePattern);
+       }
+
+       public int hashCode() {
+               int result = 17;
+               result = 37 * result + annotationTypePattern.hashCode();
+               return result;
+       }
+
+       public void buildDeclarationText() {
+               StringBuffer buf = new StringBuffer();
+               buf.append("@annotation(");
+               String annPatt = annotationTypePattern.toString();
+               buf.append(annPatt.startsWith("@") ? annPatt.substring(1) : annPatt);
+               buf.append(")");
+               this.declarationText = buf.toString();
+       }
+
+       public String toString() {
+               return this.declarationText;
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this, data);
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationTypePattern.java
new file mode 100644 (file)
index 0000000..e9ea854
--- /dev/null
@@ -0,0 +1,130 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+public abstract class AnnotationTypePattern extends PatternNode {
+
+       public static final AnnotationTypePattern ANY = new AnyAnnotationTypePattern();
+       public static final AnnotationTypePattern ELLIPSIS = new EllipsisAnnotationTypePattern();
+       public static final AnnotationTypePattern[] NONE = new AnnotationTypePattern[0];
+       private boolean isForParameterAnnotationMatch;
+       
+       /**
+        * TODO: write, read, equals & hashcode both in annotation hierarachy and
+        * in altered TypePattern hierarchy
+        */
+       protected AnnotationTypePattern() {
+               super();
+       }
+       
+       public abstract FuzzyBoolean matches(AnnotatedElement annotated);
+       public abstract FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations);
+       
+       public FuzzyBoolean fastMatches(AnnotatedElement annotated) {
+               return FuzzyBoolean.MAYBE;
+       }
+       
+       public AnnotationTypePattern remapAdviceFormals(IntMap bindings) {
+               return this;
+       }
+       
+       public abstract void resolve(World world);
+       
+       public abstract AnnotationTypePattern parameterizeWith(Map/*name -> ResolvedType*/ typeVariableMap,World w);
+       
+       public boolean isAny() { return false; }
+       
+       /**
+        * This can modify in place, or return a new TypePattern if the type changes.
+        */
+    public AnnotationTypePattern resolveBindings(IScope scope, Bindings bindings, 
+                                                                            boolean allowBinding)
+    { 
+       return this;
+    }
+
+
+       public static final byte EXACT = 1;
+       public static final byte BINDING = 2;
+       public static final byte NOT = 3;
+       public static final byte OR = 4;
+       public static final byte AND = 5;
+       public static final byte ELLIPSIS_KEY = 6;
+       public static final byte ANY_KEY = 7;
+       public static final byte WILD = 8;
+    public static final byte EXACTFIELD = 9;
+    public static final byte BINDINGFIELD = 10;
+
+       public static AnnotationTypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               byte key = s.readByte();
+               switch(key) {
+                       case EXACT: return ExactAnnotationTypePattern.read(s, context);
+                       case BINDING: return BindingAnnotationTypePattern.read(s, context);
+                       case NOT: return NotAnnotationTypePattern.read(s, context);
+                       case OR: return OrAnnotationTypePattern.read(s, context);
+                       case AND: return AndAnnotationTypePattern.read(s, context);
+                       case WILD: return WildAnnotationTypePattern.read(s,context);
+            case EXACTFIELD:
+                return ExactAnnotationFieldTypePattern.read(s, context);
+            case BINDINGFIELD:
+                return BindingAnnotationFieldTypePattern.read(s, context);
+                       case ELLIPSIS_KEY: return ELLIPSIS;
+                       case ANY_KEY: return ANY;
+               }
+               throw new BCException("unknown TypePattern kind: " + key);
+       }
+
+       public void setForParameterAnnotationMatch() { isForParameterAnnotationMatch = true; }
+       public boolean isForParameterAnnotationMatch() { return isForParameterAnnotationMatch; }
+
+}
+
+
+class EllipsisAnnotationTypePattern extends AnnotationTypePattern {
+
+       public FuzzyBoolean matches(AnnotatedElement annotated) {
+               return FuzzyBoolean.NO;
+       }
+
+       public FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations) {
+               return FuzzyBoolean.NO;
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(AnnotationTypePattern.ELLIPSIS_KEY);
+       }
+
+       public void resolve(World world) {
+       }
+
+       public String toString() { return ".."; }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+    
+    public AnnotationTypePattern parameterizeWith(Map arg0,World w) {
+       return this;
+    }
+    
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnyAnnotationTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnyAnnotationTypePattern.java
new file mode 100644 (file)
index 0000000..4a2f30a
--- /dev/null
@@ -0,0 +1,55 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors
+ * Andy Clement - extracted from AnnotationTypePattern
+ * ******************************************************************/
+ package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ResolvedType;
+
+public class AnyAnnotationTypePattern extends AnnotationTypePattern {
+
+    public FuzzyBoolean fastMatches(AnnotatedElement annotated) {
+        return FuzzyBoolean.YES;
+    }
+    
+       public FuzzyBoolean matches(AnnotatedElement annotated) {
+               return FuzzyBoolean.YES;
+       }
+       
+       public FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations) {
+               return FuzzyBoolean.YES;
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(AnnotationTypePattern.ANY_KEY);
+       }
+       
+       public void resolve(World world) {
+       }
+       
+       public String toString() { return "@ANY"; }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+    
+    public boolean isAny() { return true; }
+    
+    public AnnotationTypePattern parameterizeWith(Map arg0,World w) {
+       return this;
+    }
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java
new file mode 100644 (file)
index 0000000..5c749ca
--- /dev/null
@@ -0,0 +1,245 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.ast.Var;
+
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class ArgsAnnotationPointcut extends NameBindingPointcut {
+
+       private AnnotationPatternList arguments;
+       private String declarationText;
+
+       /**
+        * 
+        */
+       public ArgsAnnotationPointcut(AnnotationPatternList arguments) {
+               super();
+               this.arguments = arguments;
+               this.pointcutKind = ATARGS;
+               buildDeclarationText();
+       }
+
+    public AnnotationPatternList getArguments() {
+        return arguments;
+    }
+
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;  // empty args() matches jps with no args
+       }
+       
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               ArgsAnnotationPointcut ret = new ArgsAnnotationPointcut(arguments.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
+        */
+       public FuzzyBoolean fastMatch(FastMatchInfo info) {
+               return FuzzyBoolean.MAYBE;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
+        */
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               arguments.resolve(shadow.getIWorld());
+               FuzzyBoolean ret =
+                       arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes()));
+               return ret;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings)
+        */
+       protected void resolveBindings(IScope scope, Bindings bindings) {
+               if (!scope.getWorld().isInJava5Mode()) {
+                       scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.ATARGS_ONLY_SUPPORTED_AT_JAVA5_LEVEL),
+                                       getSourceLocation()));
+                       return;
+               }
+               arguments.resolveBindings(scope, bindings, true);
+               if (arguments.ellipsisCount > 1) {
+                       scope.message(IMessage.ERROR, this,
+                                       "uses more than one .. in args (compiler limitation)");
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedType, org.aspectj.weaver.IntMap)
+        */
+       protected Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               if (isDeclare(bindings.getEnclosingAdvice())) {
+                         // Enforce rule about which designators are supported in declare
+                         inAspect.getWorld().showMessage(IMessage.ERROR,
+                                       WeaverMessages.format(WeaverMessages.ARGS_IN_DECLARE),
+                                       bindings.getEnclosingAdvice().getSourceLocation(), null);
+                         return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+               }
+               AnnotationPatternList list = arguments.resolveReferences(bindings);
+               Pointcut ret = new ArgsAnnotationPointcut(list);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
+        */
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               int len = shadow.getArgCount();
+       
+               // do some quick length tests first
+               int numArgsMatchedByEllipsis = (len + arguments.ellipsisCount) - arguments.size();
+               if (numArgsMatchedByEllipsis < 0) return Literal.FALSE;  // should never happen
+               if ((numArgsMatchedByEllipsis > 0) && (arguments.ellipsisCount == 0)) {
+                       return Literal.FALSE; // should never happen
+               }
+               // now work through the args and the patterns, skipping at ellipsis
+       Test ret = Literal.TRUE;
+       int argsIndex = 0;
+       for (int i = 0; i < arguments.size(); i++) {
+                       if (arguments.get(i) == AnnotationTypePattern.ELLIPSIS) {
+                               // match ellipsisMatchCount args
+                               argsIndex += numArgsMatchedByEllipsis;
+                       } else if (arguments.get(i) == AnnotationTypePattern.ANY) {
+                               argsIndex++;
+                       } else {
+                               // match the argument type at argsIndex with the ExactAnnotationTypePattern
+                               // we know it is exact because nothing else is allowed in args
+                               ExactAnnotationTypePattern ap = (ExactAnnotationTypePattern)arguments.get(i);
+                               UnresolvedType argType = shadow.getArgType(argsIndex);
+                               ResolvedType rArgType = argType.resolve(shadow.getIWorld());
+                               if (rArgType.isMissing()) {
+                                       shadow.getIWorld().getLint().cantFindType.signal(
+                                                       new String[] {WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_ARG_TYPE,argType.getName())},
+                                                       shadow.getSourceLocation(),
+                                                       new ISourceLocation[]{getSourceLocation()}
+                                                       );
+//                       IMessage msg = new Message(
+//                         WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_ARG_TYPE,argType.getName()),
+//                         "",IMessage.ERROR,shadow.getSourceLocation(),null,new ISourceLocation[]{getSourceLocation()});
+                   }
+
+                               ResolvedType rAnnType = ap.getAnnotationType().resolve(shadow.getIWorld());
+                               if (ap instanceof BindingAnnotationTypePattern) {
+                                       BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)ap;
+                                       Var annvar = shadow.getArgAnnotationVar(argsIndex,rAnnType);
+                                       state.set(btp.getFormalIndex(),annvar);
+                               }
+                               if (!ap.matches(rArgType).alwaysTrue()) {
+                                       // we need a test...
+                                       ret = Test.makeAnd(ret,
+                                                               Test.makeHasAnnotation(
+                                                                               shadow.getArgVar(argsIndex),
+                                                                               rAnnType));
+                               }                       
+                               argsIndex++;
+                       }
+               }       
+       return ret;
+       }
+
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
+        */
+       public List getBindingAnnotationTypePatterns() {
+               List l = new ArrayList();
+               AnnotationTypePattern[] pats = arguments.getAnnotationPatterns();
+               for (int i = 0; i < pats.length; i++) {
+                       if (pats[i] instanceof BindingAnnotationTypePattern) {
+                               l.add(pats[i]);
+                       }
+               }
+               return l;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
+        */
+       public List getBindingTypePatterns() {
+               return Collections.EMPTY_LIST; 
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.ATARGS);
+               arguments.write(s);
+               writeLocation(s);
+       }
+       
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               AnnotationPatternList annotationPatternList = AnnotationPatternList.read(s,context);
+               ArgsAnnotationPointcut ret = new ArgsAnnotationPointcut(annotationPatternList);
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       public boolean equals(Object obj) {
+               if (!(obj instanceof ArgsAnnotationPointcut)) return false;
+               ArgsAnnotationPointcut other = (ArgsAnnotationPointcut) obj;
+               return other.arguments.equals(arguments);
+       }
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       public int hashCode() {
+               return 17 + 37*arguments.hashCode();
+       }
+       
+       /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    private void buildDeclarationText() {
+        StringBuffer buf = new StringBuffer("@args");
+        buf.append(arguments.toString());
+        this.declarationText = buf.toString();
+    }
+    
+    public String toString() { return this.declarationText; }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsPointcut.java
new file mode 100644 (file)
index 0000000..68d2d62
--- /dev/null
@@ -0,0 +1,307 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+
+/**
+ * args(arguments)
+ * 
+ * @author Erik Hilsdale
+ * @author Jim Hugunin
+ */
+public class ArgsPointcut extends NameBindingPointcut {
+       private static final String ASPECTJ_JP_SIGNATURE_PREFIX = "Lorg/aspectj/lang/JoinPoint";
+       private static final String ASPECTJ_SYNTHETIC_SIGNATURE_PREFIX = "Lorg/aspectj/runtime/internal/";
+       
+       private TypePatternList arguments;
+       private String stringRepresentation;
+       
+       public ArgsPointcut(TypePatternList arguments) {
+               this.arguments = arguments;
+               this.pointcutKind = ARGS;
+               this.stringRepresentation = "args" + arguments.toString() + "";
+       }
+
+    public TypePatternList getArguments() {
+        return arguments;
+    }
+
+    public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+       ArgsPointcut ret = new ArgsPointcut(this.arguments.parameterizeWith(typeVariableMap,w));
+       ret.copyLocationFrom(this);
+       return ret;
+    }
+    
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;  // empty args() matches jps with no args
+       }
+
+    public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               return FuzzyBoolean.MAYBE;
+       }
+       
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               ResolvedType[] argumentsToMatchAgainst = getArgumentsToMatchAgainst(shadow);
+               FuzzyBoolean ret =
+                       arguments.matches(argumentsToMatchAgainst, TypePattern.DYNAMIC);
+               return ret;
+       }
+       
+       private ResolvedType[] getArgumentsToMatchAgainst(Shadow shadow) {
+               
+               if (shadow.isShadowForArrayConstructionJoinpoint()) {
+                  return shadow.getArgumentTypesForArrayConstructionShadow();
+               }
+               
+               ResolvedType[] argumentsToMatchAgainst = shadow.getIWorld().resolve(shadow.getGenericArgTypes());
+               
+               // special treatment for adviceexecution which may have synthetic arguments we
+               // want to ignore.
+               if (shadow.getKind() == Shadow.AdviceExecution) {
+                       int numExtraArgs = 0;
+                       for (int i = 0; i < argumentsToMatchAgainst.length; i++) {
+                               String argumentSignature = argumentsToMatchAgainst[i].getSignature();
+                               if (argumentSignature.startsWith(ASPECTJ_JP_SIGNATURE_PREFIX) || argumentSignature.startsWith(ASPECTJ_SYNTHETIC_SIGNATURE_PREFIX)) {
+                                       numExtraArgs++;
+                               } else {
+                                       // normal arg after AJ type means earlier arg was NOT synthetic
+                                       numExtraArgs = 0;
+                               }
+                       }
+                       if (numExtraArgs > 0) {
+                               int newArgLength = argumentsToMatchAgainst.length - numExtraArgs;
+                               ResolvedType[] argsSubset = new ResolvedType[newArgLength];
+                               System.arraycopy(argumentsToMatchAgainst, 0, argsSubset, 0, newArgLength);
+                               argumentsToMatchAgainst = argsSubset;
+                       }
+               } else if (shadow.getKind() == Shadow.ConstructorExecution) {           
+                       if (shadow.getMatchingSignature().getParameterTypes().length < argumentsToMatchAgainst.length) {
+                               // there are one or more synthetic args on the end, caused by non-public itd constructor 
+                               int newArgLength = shadow.getMatchingSignature().getParameterTypes().length;
+                               ResolvedType[] argsSubset = new ResolvedType[newArgLength];
+                               System.arraycopy(argumentsToMatchAgainst, 0, argsSubset, 0, newArgLength);
+                               argumentsToMatchAgainst = argsSubset;                           
+                       }
+               }
+               
+               return argumentsToMatchAgainst;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
+        */
+       public List getBindingAnnotationTypePatterns() {
+               return Collections.EMPTY_LIST; 
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
+        */
+       public List getBindingTypePatterns() {
+               List l = new ArrayList();
+               TypePattern[] pats = arguments.getTypePatterns();
+               for (int i = 0; i < pats.length; i++) {
+                       if (pats[i] instanceof BindingTypePattern) {
+                               l.add(pats[i]);
+                       }
+               }
+               return l;
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.ARGS);
+               arguments.write(s);
+               writeLocation(s);
+       }
+       
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               ArgsPointcut ret = new ArgsPointcut(TypePatternList.read(s, context));
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       
+       public boolean equals(Object other) {
+               if (!(other instanceof ArgsPointcut)) return false;
+               ArgsPointcut o = (ArgsPointcut)other;
+               return o.arguments.equals(this.arguments);
+       }
+
+    public int hashCode() {
+        return arguments.hashCode();
+    }
+  
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               arguments.resolveBindings(scope, bindings, true, true);
+               if (arguments.ellipsisCount > 1) {
+                       scope.message(IMessage.ERROR, this,
+                                       "uses more than one .. in args (compiler limitation)");
+               }
+       }
+       
+       public void postRead(ResolvedType enclosingType) {
+               arguments.postRead(enclosingType);
+       }
+
+
+       public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               if (isDeclare(bindings.getEnclosingAdvice())) {
+                 // Enforce rule about which designators are supported in declare
+                 inAspect.getWorld().showMessage(IMessage.ERROR,
+                               WeaverMessages.format(WeaverMessages.ARGS_IN_DECLARE),
+                               bindings.getEnclosingAdvice().getSourceLocation(), null);
+                 return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+               }
+               TypePatternList args = arguments.resolveReferences(bindings);
+               if (inAspect.crosscuttingMembers != null) {
+                       inAspect.crosscuttingMembers.exposeTypes(args.getExactTypes());
+               }
+               Pointcut ret = new ArgsPointcut(args);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       private Test findResidueNoEllipsis(Shadow shadow, ExposedState state, TypePattern[] patterns) {
+               ResolvedType[] argumentsToMatchAgainst = getArgumentsToMatchAgainst(shadow);
+               int len = argumentsToMatchAgainst.length;
+               //System.err.println("boudn to : " + len + ", " + patterns.length);
+               if (patterns.length != len) {
+                       return Literal.FALSE;
+               }
+               
+               Test ret = Literal.TRUE;
+               
+               for (int i=0; i < len; i++) {
+                       UnresolvedType argType = shadow.getGenericArgTypes()[i];
+                       TypePattern type = patterns[i];
+            ResolvedType argRTX = shadow.getIWorld().resolve(argType,true);
+                       if (!(type instanceof BindingTypePattern)) {
+                if (argRTX.isMissing()) {
+                                       shadow.getIWorld().getLint().cantFindType.signal(
+                                                       new String[] {WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_ARG_TYPE,argType.getName())},
+                                                       shadow.getSourceLocation(),
+                                                       new ISourceLocation[]{getSourceLocation()}
+                                                       );
+//                  IMessage msg = new Message(
+//                    WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_ARG_TYPE,argType.getName()),
+//                    "",IMessage.ERROR,shadow.getSourceLocation(),null,new ISourceLocation[]{getSourceLocation()});
+//                  shadow.getIWorld().getMessageHandler().handleMessage(msg);
+                }
+                               if (type.matchesInstanceof(argRTX).alwaysTrue()) {
+                                       continue;
+                               }
+                       }
+
+                       World world = shadow.getIWorld();
+                       ResolvedType typeToExpose = type.getExactType().resolve(world);
+                       if (typeToExpose.isParameterizedType()) {
+                               boolean inDoubt = (type.matchesInstanceof(argRTX) == FuzzyBoolean.MAYBE);                               
+                               if (inDoubt && world.getLint().uncheckedArgument.isEnabled()) {
+                                       String uncheckedMatchWith = typeToExpose.getSimpleBaseName();
+                                       if (argRTX.isParameterizedType() && (argRTX.getRawType() == typeToExpose.getRawType())) {
+                                               uncheckedMatchWith = argRTX.getSimpleName();
+                                       }
+                                       if (!isUncheckedArgumentWarningSuppressed()) {
+                                               world.getLint().uncheckedArgument.signal(
+                                                               new String[] {
+                                                                               typeToExpose.getSimpleName(),
+                                                                               uncheckedMatchWith,
+                                                                               typeToExpose.getSimpleBaseName(),
+                                                                               shadow.toResolvedString(world)},
+                                                               getSourceLocation(),
+                                                               new ISourceLocation[] {shadow.getSourceLocation()});
+                                               }
+                               }
+                       }                       
+                       
+                       ret = Test.makeAnd(ret,
+                               exposeStateForVar(shadow.getArgVar(i), type, state,shadow.getIWorld()));
+               }
+               
+               return ret;             
+       }
+
+       /**
+        * We need to find out if someone has put the @SuppressAjWarnings{"uncheckedArgument"}
+        * annotation somewhere. That somewhere is going to be an a piece of advice that uses this
+        * pointcut. But how do we find it???
+        * @return
+        */
+       private boolean isUncheckedArgumentWarningSuppressed() {
+               return false;
+       }
+       
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               ResolvedType[] argsToMatch = getArgumentsToMatchAgainst(shadow);
+               if (arguments.matches(argsToMatch, TypePattern.DYNAMIC).alwaysFalse()) {
+                       return Literal.FALSE;
+               }
+               int ellipsisCount = arguments.ellipsisCount;
+               if (ellipsisCount == 0) {
+                       return findResidueNoEllipsis(shadow, state, arguments.getTypePatterns());               
+               } else if (ellipsisCount == 1) {
+                       TypePattern[] patternsWithEllipsis = arguments.getTypePatterns();
+                       TypePattern[] patternsWithoutEllipsis = new TypePattern[argsToMatch.length];
+                       int lenWithEllipsis = patternsWithEllipsis.length;
+                       int lenWithoutEllipsis = patternsWithoutEllipsis.length;
+                       // l1+1 >= l0
+                       int indexWithEllipsis = 0;
+                       int indexWithoutEllipsis = 0;
+                       while (indexWithoutEllipsis < lenWithoutEllipsis) {
+                               TypePattern p = patternsWithEllipsis[indexWithEllipsis++];
+                               if (p == TypePattern.ELLIPSIS) {
+                                       int newLenWithoutEllipsis =
+                                               lenWithoutEllipsis - (lenWithEllipsis-indexWithEllipsis);
+                                       while (indexWithoutEllipsis < newLenWithoutEllipsis) {
+                                               patternsWithoutEllipsis[indexWithoutEllipsis++] = TypePattern.ANY;
+                                       }
+                               } else {
+                                       patternsWithoutEllipsis[indexWithoutEllipsis++] = p;
+                               }
+                       }
+                       return findResidueNoEllipsis(shadow, state, patternsWithoutEllipsis);
+               } else {
+                       throw new BCException("unimplemented");
+               }
+       }
+       
+       public String toString() {
+               return this.stringRepresentation;
+       }
+       
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BasicToken.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BasicToken.java
new file mode 100644 (file)
index 0000000..e6e201d
--- /dev/null
@@ -0,0 +1,75 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+
+public final class BasicToken implements IToken {
+       private String value;
+       private boolean isIdentifier;
+       private String literalKind;
+
+       private int start;
+       private int end;
+       
+       public static BasicToken makeOperator(String value, int start, int end) {
+               return new BasicToken(value.intern(), false, null, start, end);
+       }
+       
+       public static BasicToken makeIdentifier(String value, int start, int end) {
+               return new BasicToken(value, true, null, start, end);
+       }
+       
+       public static BasicToken makeLiteral(String value, String kind, int start, int end) {
+               return new BasicToken(value, false, kind.intern(), start, end);
+       }
+       
+       
+       private BasicToken(String value, boolean isIdentifier, String literalKind, int start, int end) {
+               this.value = value;
+               this.isIdentifier = isIdentifier;
+               this.literalKind = literalKind;
+               this.start = start;
+               this.end = end;
+       }
+       
+       public int getStart() { return start; }
+       public int getEnd() { return end; }
+       public String getFileName() { return "unknown"; }
+       
+       public String getString() {
+               return value;
+       }
+
+       public boolean isIdentifier() {
+               return isIdentifier;
+       }
+       
+       public Pointcut maybeGetParsedPointcut() {
+               return null;
+       }
+
+       
+       
+       public String toString() {
+               String s;
+               if (isIdentifier) s = value;
+               else s = "'" + value + "'";
+               
+               return s + "@" + start + ":" + end;
+       }
+       public String getLiteralKind() {
+               return literalKind;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BasicTokenSource.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BasicTokenSource.java
new file mode 100644 (file)
index 0000000..37bc7ed
--- /dev/null
@@ -0,0 +1,183 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ISourceContext;
+
+
+public class BasicTokenSource implements ITokenSource {
+       private int index = 0;
+       private IToken[] tokens;
+       private ISourceContext sourceContext;
+
+       public BasicTokenSource(IToken[] tokens, ISourceContext sourceContext) {
+               this.tokens = tokens;
+               this.sourceContext = sourceContext;
+       }
+
+       public int getIndex() {
+               return index;
+       }
+
+       public void setIndex(int newIndex) {
+               this.index = newIndex;
+       }
+
+       public IToken next() {
+               try {
+                   return tokens[index++];
+               } catch (ArrayIndexOutOfBoundsException e) {
+                       return IToken.EOF;
+               }
+       }
+
+       public IToken peek() {
+               try {
+                   return tokens[index];
+               } catch (ArrayIndexOutOfBoundsException e) {
+                       return IToken.EOF;
+               }
+       }
+
+       public IToken peek(int offset) {
+               try {
+                   return tokens[index+offset];
+               } catch (ArrayIndexOutOfBoundsException e) {
+                       return IToken.EOF;
+               }
+       }
+
+       public String toString() {
+               StringBuffer buf = new StringBuffer();
+               buf.append("[");
+               for (int i = 0; i < tokens.length; i++) {
+                       IToken t = tokens[i];
+                       if (t == null)
+                               break;
+                       if (i > 0)
+                               buf.append(", ");
+                       buf.append(t.toString());
+               }
+               buf.append("]");
+               return buf.toString();
+       }
+       
+       
+       //////////////////////////////////////////////////////
+       // Convenience, maybe just for testing
+       static ITokenSource makeTokenSource(String input, ISourceContext context) {
+               char[] chars = input.toCharArray();
+               
+               int i = 0;
+               List tokens = new ArrayList();
+               
+               while (i < chars.length) {
+                       char ch = chars[i++];                   
+                       switch(ch) {
+                               case ' ':
+                               case '\t':
+                               case '\n':
+                               case '\r':
+                                       continue;
+                               case '*':
+                               case '(':
+                               case ')':
+                               case '+':
+                               case '[':
+                               case ']':
+                               case ',':
+                               case '!':
+                               case ':':
+                               case '@':
+                               case '<':
+                               case '>':
+                               case '=':
+                               case    '?':
+                                   tokens.add(BasicToken.makeOperator(makeString(ch), i-1, i-1));
+                                   continue;
+                               case '.':
+                                       if ((i+2)<=chars.length) {
+                                               // could be '...'
+                                               char nextChar1 = chars[i];
+                                               char nextChar2 = chars[i+1];
+                                               if (ch==nextChar1 && ch==nextChar2) {
+                                                       // '...'
+                                                       tokens.add(BasicToken.makeIdentifier("...",i-1,i+1));
+                                                       i=i+2;
+                                               } else {
+                                                       tokens.add(BasicToken.makeOperator(makeString(ch), i-1, i-1));
+                                               }
+                                       } else {
+                                               tokens.add(BasicToken.makeOperator(makeString(ch), i-1, i-1));
+                                       }
+                                       continue;
+                               case '&':
+                                       if ((i+1) <= chars.length && chars[i] != '&') {
+                                               tokens.add(BasicToken.makeOperator(makeString(ch),i-1,i-1));
+                                               continue;
+                                       }
+                                       // fall-through
+                               case '|':
+                                   if (i == chars.length) {
+                                       throw new BCException("bad " + ch);
+                                   }
+                                   char nextChar = chars[i++];
+                                   if (nextChar == ch) {
+                                       tokens.add(BasicToken.makeOperator(makeString(ch, 2), i-2, i-1));
+                                   } else {
+                                       throw new RuntimeException("bad " + ch);
+                                   }
+                                   continue;
+                                   
+                               case '\"':
+                                   int start0 = i-1;
+                                   while (i < chars.length && !(chars[i]=='\"')) i++;
+                                   i += 1;
+                                   tokens.add(BasicToken.makeLiteral(new String(chars, start0+1, i-start0-2), "string", start0, i-1));
+                                   continue;
+                               default:
+                                   int start = i-1;
+                                   while (i < chars.length && Character.isJavaIdentifierPart(chars[i])) { i++; }
+                                   tokens.add(BasicToken.makeIdentifier(new String(chars, start, i-start), start, i-1));
+                               
+                       }
+               }
+
+               //System.out.println(tokens);
+               
+               return new BasicTokenSource((IToken[])tokens.toArray(new IToken[tokens.size()]), context);
+       }
+
+       private static String makeString(char ch) {
+               return Character.toString(ch);
+       }
+
+       private static String makeString(char ch, int count) {
+               // slightly inefficient ;-)
+               char[] chars = new char[count];
+               for (int i=0; i<count; i++) { chars[i] = ch; }
+               return new String(chars);
+       }
+       public ISourceContext getSourceContext() {
+               return sourceContext;
+       }
+       public void setSourceContext(ISourceContext context) {
+               this.sourceContext = context;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingAnnotationFieldTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingAnnotationFieldTypePattern.java
new file mode 100644 (file)
index 0000000..96a651e
--- /dev/null
@@ -0,0 +1,171 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement     initial implementation 
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ReferenceType;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+
+/**
+ * Represents an attempt to bind the field of an annotation within a pointcut. For example:<br>
+ * <code><pre>
+ * before(Level lev): execution(* *(..)) &amp;&amp; @annotation(TraceAnnotation(lev))
+ * </pre></code><br>
+ * This binding annotation type pattern will be for 'lev'.
+ */
+public class BindingAnnotationFieldTypePattern extends ExactAnnotationTypePattern implements BindingPattern {
+
+    protected int formalIndex;
+    UnresolvedType formalType; // In this construct the formal type differs from the annotation type
+
+    public BindingAnnotationFieldTypePattern(UnresolvedType formalType, int formalIndex, UnresolvedType theAnnotationType) {
+        super(theAnnotationType, null);
+        this.formalIndex = formalIndex;
+        this.formalType = formalType;
+    }
+
+    public void resolveBinding(World world) {
+        if (resolved) return;
+        resolved = true;
+        formalType = world.resolve(formalType);
+        annotationType = world.resolve(annotationType);
+        ResolvedType annoType = (ResolvedType) annotationType;
+        if (!annoType.isAnnotation()) {
+            IMessage m = MessageUtil.error(WeaverMessages.format(WeaverMessages.REFERENCE_TO_NON_ANNOTATION_TYPE, annoType.getName()),
+                getSourceLocation());
+            world.getMessageHandler().handleMessage(m);
+            resolved = false;
+        }
+    }
+
+    public AnnotationTypePattern parameterizeWith(Map typeVariableMap, World w) {
+        throw new BCException("Parameterization not implemented for annotation field binding construct (compiler limitation)");
+        // UnresolvedType newAnnotationType = annotationType;
+        // if (annotationType.isTypeVariableReference()) {
+        // TypeVariableReference t = (TypeVariableReference) annotationType;
+        // String key = t.getTypeVariable().getName();
+        // if (typeVariableMap.containsKey(key)) {
+        // newAnnotationType = (UnresolvedType) typeVariableMap.get(key);
+        // }
+        // } else if (annotationType.isParameterizedType()) {
+        // newAnnotationType = annotationType.parameterize(typeVariableMap);
+        // }
+        // BindingAnnotationTypePattern ret = new BindingAnnotationTypePattern(newAnnotationType, this.formalIndex);
+        // if (newAnnotationType instanceof ResolvedType) {
+        // ResolvedType rat = (ResolvedType) newAnnotationType;
+        // verifyRuntimeRetention(rat.getWorld(), rat);
+        // }
+        // ret.copyLocationFrom(this);
+        // return ret;
+    }
+
+    public int getFormalIndex() {
+        return formalIndex;
+    }
+
+    public boolean equals(Object obj) {
+        if (!(obj instanceof BindingAnnotationFieldTypePattern)) return false;
+        BindingAnnotationFieldTypePattern btp = (BindingAnnotationFieldTypePattern) obj;
+        return (btp.formalIndex == formalIndex) && (annotationType.equals(btp.annotationType)) && (formalType.equals(btp.formalType));
+    }
+
+    public int hashCode() {
+        return (annotationType.hashCode() * 37 + formalIndex * 37) + formalType.hashCode();
+    }
+
+    public AnnotationTypePattern remapAdviceFormals(IntMap bindings) {
+        if (!bindings.hasKey(formalIndex)) {
+            throw new BCException("Annotation field binding reference must be bound (compiler limitation)");
+            // must be something like returning the unbound form: return new ExactAnnotationTypePattern(annotationType,
+            // null);
+        } else {
+            int newFormalIndex = bindings.get(formalIndex);
+            return new BindingAnnotationFieldTypePattern(formalType, newFormalIndex, annotationType);
+        }
+    }
+
+    public void write(DataOutputStream s) throws IOException {
+        s.writeByte(AnnotationTypePattern.BINDINGFIELD);
+        formalType.write(s); // the type of the field within the annotation
+        s.writeShort((short) formalIndex);
+        annotationType.write(s); // the annotation type
+        writeLocation(s);
+    }
+
+    public static AnnotationTypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+        AnnotationTypePattern ret = new BindingAnnotationFieldTypePattern(UnresolvedType.read(s), s.readShort(), UnresolvedType.read(s));
+        ret.readLocation(context, s);
+        return ret;
+    }
+    
+
+    public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations) {        
+        // Inheritance irrelevant because @annotation(Anno(x)) only supported at method execution join points (compiler limitation)
+//      boolean checkSupers = false;
+//        if (getResolvedAnnotationType().hasAnnotation(UnresolvedType.AT_INHERITED)) {
+//            if (annotated instanceof ResolvedType) {
+//                checkSupers = true;
+//            }
+//        }
+//
+        if (annotated.hasAnnotation(annotationType)) {
+            if (annotationType instanceof ReferenceType) {
+                ReferenceType rt = (ReferenceType) annotationType;
+                if (rt.getRetentionPolicy() != null && rt.getRetentionPolicy().equals("SOURCE")) {
+                    rt.getWorld().getMessageHandler().handleMessage(
+                        MessageUtil.warn(WeaverMessages.format(WeaverMessages.NO_MATCH_BECAUSE_SOURCE_RETENTION, annotationType, annotated),
+                            getSourceLocation()));
+                    return FuzzyBoolean.NO;
+                }
+                ResolvedMember[] methods = rt.getDeclaredMethods();
+                boolean found = false;
+                for (int i = 0; i < methods.length && !found; i++) {
+                    if (methods[i].getReturnType().equals(formalType)) {
+                        found = true;
+                    }
+                }
+                return (found ? FuzzyBoolean.YES : FuzzyBoolean.NO);
+            }
+        }
+//         else if (checkSupers) {
+//            ResolvedType toMatchAgainst = ((ResolvedType) annotated).getSuperclass();
+//            while (toMatchAgainst != null) {
+//                if (toMatchAgainst.hasAnnotation(annotationType)) {
+//                    return FuzzyBoolean.YES;
+//                }
+//                toMatchAgainst = toMatchAgainst.getSuperclass();
+//            }
+//        }
+//
+        return FuzzyBoolean.NO;
+    }
+
+    public UnresolvedType getFormalType() {
+        return formalType;
+    }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java
new file mode 100644 (file)
index 0000000..f0be890
--- /dev/null
@@ -0,0 +1,134 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.TypeVariableReference;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+
+public class BindingAnnotationTypePattern extends ExactAnnotationTypePattern implements BindingPattern {
+
+       protected int formalIndex;
+       
+       /**
+        * @param annotationType
+        */
+       public BindingAnnotationTypePattern(UnresolvedType annotationType, int index) {
+               super(annotationType,null);
+               this.formalIndex = index;
+       }
+               
+       public BindingAnnotationTypePattern(FormalBinding binding) {
+               this(binding.getType(),binding.getIndex());
+       }
+       
+       public void resolveBinding(World world) {
+               if (resolved) return;
+               resolved = true;
+               annotationType = annotationType.resolve(world);
+               ResolvedType resolvedAnnotationType = (ResolvedType) annotationType;
+               if (!resolvedAnnotationType.isAnnotation()) {
+                       IMessage m = MessageUtil.error(
+                                       WeaverMessages.format(WeaverMessages.REFERENCE_TO_NON_ANNOTATION_TYPE,annotationType.getName()),
+                                       getSourceLocation());
+                       world.getMessageHandler().handleMessage(m);
+                       resolved = false;
+               }
+               if (annotationType.isTypeVariableReference()) return;  // we'll deal with this next check when the type var is actually bound...
+        verifyRuntimeRetention(world, resolvedAnnotationType);
+       }
+
+       private void verifyRuntimeRetention(World world, ResolvedType resolvedAnnotationType) {
+               if (!resolvedAnnotationType.isAnnotationWithRuntimeRetention()) { // default is class visibility
+                   // default is class visibility
+                       IMessage m = MessageUtil.error(
+                                       WeaverMessages.format(WeaverMessages.BINDING_NON_RUNTIME_RETENTION_ANNOTATION,annotationType.getName()),
+                                       getSourceLocation());
+                       world.getMessageHandler().handleMessage(m);
+                       resolved = false;                   
+               }
+       }
+       
+       public AnnotationTypePattern parameterizeWith(Map typeVariableMap,World w) {
+               UnresolvedType newAnnotationType = annotationType;
+               if (annotationType.isTypeVariableReference()) {
+                       TypeVariableReference t = (TypeVariableReference) annotationType;
+                       String key = t.getTypeVariable().getName();
+                       if (typeVariableMap.containsKey(key)) {
+                               newAnnotationType = (UnresolvedType) typeVariableMap.get(key);
+                       }
+               } else if (annotationType.isParameterizedType()) {
+                       newAnnotationType = annotationType.parameterize(typeVariableMap);
+               }
+               BindingAnnotationTypePattern ret = new BindingAnnotationTypePattern(newAnnotationType,this.formalIndex);
+               if (newAnnotationType instanceof ResolvedType) {
+                       ResolvedType rat = (ResolvedType) newAnnotationType;
+                       verifyRuntimeRetention(rat.getWorld(),rat);                     
+               }
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public int getFormalIndex() {
+               return formalIndex;
+       }
+
+       public boolean equals(Object obj) {
+               if (!(obj instanceof BindingAnnotationTypePattern)) return false;
+               BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern) obj;
+               return (super.equals(btp) && (btp.formalIndex == formalIndex));
+       }
+       
+       public int hashCode() {
+               return super.hashCode()*37 + formalIndex;
+       }
+       
+       public AnnotationTypePattern remapAdviceFormals(IntMap bindings) {                      
+               if (!bindings.hasKey(formalIndex)) {
+                       return new ExactAnnotationTypePattern(annotationType,null);
+               } else {
+                       int newFormalIndex = bindings.get(formalIndex);
+                       return new BindingAnnotationTypePattern(annotationType, newFormalIndex);
+               }
+       }
+       private static final byte VERSION = 1; // rev if serialised form changed
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.ExactAnnotationTypePattern#write(java.io.DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(AnnotationTypePattern.BINDING);
+               s.writeByte(VERSION);
+               annotationType.write(s);
+               s.writeShort((short)formalIndex);
+               writeLocation(s);
+       }       
+       
+       public static AnnotationTypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               byte version = s.readByte();
+               if (version > VERSION) {
+                       throw new BCException("BindingAnnotationTypePattern was written by a more recent version of AspectJ");
+               }
+               AnnotationTypePattern ret = new BindingAnnotationTypePattern(UnresolvedType.read(s),s.readShort());
+               ret.readLocation(context,s);
+               return ret;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingPattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingPattern.java
new file mode 100644 (file)
index 0000000..4d909ed
--- /dev/null
@@ -0,0 +1,19 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.IHasPosition;
+
+/**
+ * Marker interface for BindingTypePattern and BindingAnnotationTypePattern
+ */
+public interface BindingPattern extends IHasPosition {
+       int getFormalIndex();
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingTypePattern.java
new file mode 100644 (file)
index 0000000..28c5739
--- /dev/null
@@ -0,0 +1,97 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+public class BindingTypePattern extends ExactTypePattern implements BindingPattern {
+       private int formalIndex;
+
+       public BindingTypePattern(UnresolvedType type, int index,boolean isVarArgs) {
+               super(type, false,isVarArgs);
+               this.formalIndex = index;
+       }
+
+       public BindingTypePattern(FormalBinding binding, boolean isVarArgs) {
+               this(binding.getType(), binding.getIndex(),isVarArgs);
+       }
+       
+       public int getFormalIndex() {
+               return formalIndex;
+       }
+
+    public boolean equals(Object other) {
+       if (!(other instanceof BindingTypePattern)) return false;
+       BindingTypePattern o = (BindingTypePattern)other;
+       if (includeSubtypes != o.includeSubtypes) return false;
+       if (isVarArgs != o.isVarArgs) return false;
+       return o.type.equals(this.type) && o.formalIndex == this.formalIndex;
+    }
+    public int hashCode() {
+        int result = 17;
+        result = 37*result + super.hashCode();
+        result = 37*result + formalIndex;
+        return result;
+    }
+       
+       public void write(DataOutputStream out) throws IOException {
+               out.writeByte(TypePattern.BINDING);
+               type.write(out);
+               out.writeShort((short)formalIndex);
+               out.writeBoolean(isVarArgs);
+               writeLocation(out);
+       }
+       
+       public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               UnresolvedType  type = UnresolvedType.read(s);
+               int            index = s.readShort();
+               boolean   isVarargs = false;
+               if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
+                       isVarargs = s.readBoolean();
+               }
+               TypePattern ret = new BindingTypePattern(type,index,isVarargs);
+               ret.readLocation(context, s);
+               return ret;
+       }
+       
+       public TypePattern remapAdviceFormals(IntMap bindings) {                        
+               if (!bindings.hasKey(formalIndex)) {
+                       return new ExactTypePattern(type, false, isVarArgs);
+               } else {
+                       int newFormalIndex = bindings.get(formalIndex);
+                       return new BindingTypePattern(type, newFormalIndex, isVarArgs);
+               }
+       }
+       
+       public TypePattern parameterizeWith(Map typeVariableMap,World w) {
+               ExactTypePattern superParameterized = (ExactTypePattern) super.parameterizeWith(typeVariableMap,w);
+               BindingTypePattern ret = new BindingTypePattern(superParameterized.getExactType(),this.formalIndex,this.isVarArgs);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+    public String toString() {
+       //Thread.currentThread().dumpStack();
+       return "BindingTypePattern(" + super.toString() + ", " + formalIndex + ")";
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/Bindings.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/Bindings.java
new file mode 100644 (file)
index 0000000..4853dd0
--- /dev/null
@@ -0,0 +1,136 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.UnresolvedType;
+
+public class Bindings {
+       public static final Bindings NONE = new Bindings(0);
+
+       private BindingPattern[] bindings;
+
+       public Bindings(BindingPattern[] bindings) {
+               this.bindings = bindings;
+       }
+
+       public Bindings(int count) {
+               this(new BindingPattern[count]);
+       }
+
+       public void register(BindingPattern binding, IScope scope) {
+               int index = binding.getFormalIndex();
+               BindingPattern existingBinding = bindings[index];
+               if (existingBinding != null) {
+                       scope.message(IMessage.ERROR, existingBinding, binding, "multiple bindings" + index + ", " + binding);
+               }
+               bindings[index] = binding;
+       }
+
+       public void mergeIn(Bindings other, IScope scope) {
+               for (int i = 0, len = other.bindings.length; i < len; i++) {
+                       if (other.bindings[i] != null) {
+                               register(other.bindings[i], scope);
+                       }
+               }
+       }
+
+       /**
+        * signals an error if one has a binding and other doesn't
+        */
+       public void checkEquals(Bindings other, IScope scope) {
+               BindingPattern[] b1 = this.bindings;
+               BindingPattern[] b2 = other.bindings;
+               int len = b1.length;
+               if (len != b2.length) {
+                       throw new BCException("INSANE");
+               }
+
+               for (int i = 0; i < len; i++) {
+                       if (b1[i] == null && b2[i] != null) {
+                               scope.message(IMessage.ERROR, b2[i], "inconsistent binding");
+                               b1[i] = b2[i]; // done just to produce fewer error messages
+                       } else if (b2[i] == null && b1[i] != null) {
+                               scope.message(IMessage.ERROR, b1[i], "inconsistent binding");
+                               b2[i] = b1[i]; // done just to produce fewer error messages
+                       }
+               }
+       }
+
+       public String toString() {
+               StringBuffer buf = new StringBuffer("Bindings(");
+               for (int i = 0, len = bindings.length; i < len; i++) {
+                       if (i > 0)
+                               buf.append(", ");
+                       buf.append(bindings[i]);
+               }
+               buf.append(")");
+               return buf.toString();
+       }
+
+       public int[] getUsedFormals() {
+               // System.out.println("used: " + this);
+               int[] ret = new int[bindings.length];
+               int index = 0;
+               for (int i = 0, len = bindings.length; i < len; i++) {
+                       if (bindings[i] != null) {
+                               ret[index++] = i;
+                       }
+               }
+               int[] newRet = new int[index];
+               System.arraycopy(ret, 0, newRet, 0, index);
+               // System.out.println("ret: " + index);
+               return newRet;
+       }
+
+       public UnresolvedType[] getUsedFormalTypes() {
+               UnresolvedType[] ret = new UnresolvedType[bindings.length];
+               int index = 0;
+               for (int i = 0, len = bindings.length; i < len; i++) {
+                       if (bindings[i] != null) {
+                               ret[index++] = ((BindingTypePattern) bindings[i]).getExactType();
+                       }
+               }
+               UnresolvedType[] newRet = new UnresolvedType[index];
+               System.arraycopy(ret, 0, newRet, 0, index);
+               // System.out.println("ret: " + index);
+               return newRet;
+       }
+
+       public Bindings copy() {
+               // int len = bindings.length;
+               // boolean[] a = new boolean[len];
+               // System.arraycopy(bindings, 0, a, 0, len);
+               return new Bindings((BindingPattern[]) bindings.clone());
+       }
+
+       public void checkAllBound(IScope scope) {
+               for (int i = 0, len = bindings.length; i < len; i++) {
+                       if (bindings[i] == null) {
+                               // ATAJ: avoid warnings for implicit bindings
+                               if (scope.getFormal(i) instanceof FormalBinding.ImplicitFormalBinding) {
+                                       bindings[i] = new BindingTypePattern(scope.getFormal(i), false);
+                               } else {
+                                       scope.message(IMessage.ERROR, scope.getFormal(i), "formal unbound in pointcut ");
+                               }
+                       }
+               }
+
+       }
+
+       public int size() {
+               return bindings.length;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/CflowPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/CflowPointcut.java
new file mode 100644 (file)
index 0000000..05ff2d8
--- /dev/null
@@ -0,0 +1,353 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.util.FileUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.Advice;
+import org.aspectj.weaver.CrosscuttingMembers;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedMemberImpl;
+import org.aspectj.weaver.ResolvedPointcutDefinition;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Test;
+
+public class CflowPointcut extends Pointcut {
+       private final Pointcut entry; // The pointcut inside the cflow() that
+       // represents the 'entry' point
+       boolean isBelow;// Is this cflowbelow?
+       private int[] freeVars;
+
+       /**
+        * Used to indicate that we're in the context of a cflow when concretizing if's
+        * 
+        * Will be removed or replaced with something better when we handle this as a non-error
+        */
+       public static final ResolvedPointcutDefinition CFLOW_MARKER = new ResolvedPointcutDefinition(null, 0, null,
+                       UnresolvedType.NONE, Pointcut.makeMatchesNothing(Pointcut.RESOLVED));
+
+       public CflowPointcut(Pointcut entry, boolean isBelow, int[] freeVars) {
+               // System.err.println("Building cflow pointcut "+entry.toString());
+               this.entry = entry;
+               this.isBelow = isBelow;
+               this.freeVars = freeVars;
+               pointcutKind = CFLOW;
+       }
+
+       /**
+        * @return Returns true is this is a cflowbelow pointcut
+        */
+       public boolean isCflowBelow() {
+               return isBelow;
+       }
+
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;
+       }
+
+       // enh 76055
+       public Pointcut getEntry() {
+               return entry;
+       }
+
+       public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               return FuzzyBoolean.MAYBE;
+       }
+
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               // ??? this is not maximally efficient
+               return FuzzyBoolean.MAYBE;
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.CFLOW);
+               entry.write(s);
+               s.writeBoolean(isBelow);
+               FileUtil.writeIntArray(freeVars, s);
+               writeLocation(s);
+       }
+
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+
+               CflowPointcut ret = new CflowPointcut(Pointcut.read(s, context), s.readBoolean(), FileUtil.readIntArray(s));
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public Pointcut parameterizeWith(Map typeVariableMap, World w) {
+               CflowPointcut ret = new CflowPointcut(entry.parameterizeWith(typeVariableMap, w), isBelow, freeVars);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               if (bindings == null) {
+                       entry.resolveBindings(scope, null);
+                       entry.state = RESOLVED;
+                       freeVars = new int[0];
+               } else {
+                       // ??? for if's sake we might need to be more careful here
+                       Bindings entryBindings = new Bindings(bindings.size());
+
+                       entry.resolveBindings(scope, entryBindings);
+                       entry.state = RESOLVED;
+
+                       freeVars = entryBindings.getUsedFormals();
+
+                       bindings.mergeIn(entryBindings, scope);
+               }
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof CflowPointcut))
+                       return false;
+               CflowPointcut o = (CflowPointcut) other;
+               return o.entry.equals(entry) && o.isBelow == isBelow;
+       }
+
+       public int hashCode() {
+               int result = 17;
+               result = 37 * result + entry.hashCode();
+               result = 37 * result + (isBelow ? 0 : 1);
+               return result;
+       }
+
+       public String toString() {
+               return "cflow" + (isBelow ? "below" : "") + "(" + entry + ")";
+       }
+
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               throw new RuntimeException("unimplemented - did concretization fail?");
+       }
+
+       public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+
+               // the pointcut is marked as CONCRETE after returning from this
+               // call - so we can't skip concretization
+               // if (this.entry.state == Pointcut.SYMBOLIC) {
+               // // too early to concretize, return unchanged
+               // return this;
+               // }
+
+               // Enforce rule about which designators are supported in declare
+               if (isDeclare(bindings.getEnclosingAdvice())) {
+                       inAspect.getWorld().showMessage(IMessage.ERROR,
+                                       WeaverMessages.format(WeaverMessages.CFLOW_IN_DECLARE, isBelow ? "below" : ""),
+                                       bindings.getEnclosingAdvice().getSourceLocation(), null);
+                       return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+               }
+
+               // make this remap from formal positions to arrayIndices
+               IntMap entryBindings = new IntMap();
+               if (freeVars != null) {
+                       for (int i = 0, len = freeVars.length; i < len; i++) {
+                               int freeVar = freeVars[i];
+                               // int formalIndex = bindings.get(freeVar);
+                               entryBindings.put(freeVar, i);
+                       }
+               }
+               entryBindings.copyContext(bindings);
+               // System.out.println(this + " bindings: " + entryBindings);
+
+               World world = inAspect.getWorld();
+
+               Pointcut concreteEntry;
+
+               ResolvedType concreteAspect = bindings.getConcreteAspect();
+
+               CrosscuttingMembers xcut = concreteAspect.crosscuttingMembers;
+               Collection 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 innerCflowEntries = new ArrayList(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);
+                       return ret;
+               }
+
+       }
+
+       private String getKey(Pointcut p, ResolvedType a, String stackOrCounter) {
+               StringBuffer sb = new StringBuffer();
+               sb.append(a.getName());
+               sb.append("::");
+               sb.append(p.toString());
+               sb.append("::");
+               sb.append(stackOrCounter);
+               return sb.toString();
+       }
+
+       private Object getCflowfield(CrosscuttingMembers xcut, Pointcut pcutkey, ResolvedType concreteAspect, String stackOrCounter) {
+               String key = getKey(pcutkey, concreteAspect, stackOrCounter);
+               Object o = null;
+               if (isBelow)
+                       o = xcut.getCflowBelowFields().get(key);
+               else
+                       o = xcut.getCflowFields().get(key);
+               // System.err.println("Retrieving for key "+key+" returning "+o);
+               return o;
+       }
+
+       private void putCflowfield(CrosscuttingMembers xcut, Pointcut pcutkey, ResolvedType concreteAspect, Object o,
+                       String stackOrCounter) {
+               String key = getKey(pcutkey, concreteAspect, stackOrCounter);
+               // System.err.println("Storing cflow field for key"+key);
+               if (isBelow) {
+                       xcut.getCflowBelowFields().put(key, o);
+               } else {
+                       xcut.getCflowFields().put(key, o);
+               }
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this, data);
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java
new file mode 100644 (file)
index 0000000..842384b
--- /dev/null
@@ -0,0 +1,184 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.Message;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.MemberImpl;
+import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Expr;
+import org.aspectj.weaver.ast.Test;
+
+public class ConcreteCflowPointcut extends Pointcut {
+       private final Member cflowField;
+       List/* Slot */slots; // exposed for testing
+       boolean usesCounter;
+       ResolvedType aspect;
+
+       // Can either use a counter or a stack to implement cflow.
+       public ConcreteCflowPointcut(ResolvedType aspect, Member cflowField, List slots, boolean usesCounter) {
+               this.aspect = aspect;
+               this.cflowField = cflowField;
+               this.slots = slots;
+               this.usesCounter = usesCounter;
+               this.pointcutKind = CFLOW;
+       }
+
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;
+       }
+
+       public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               return FuzzyBoolean.MAYBE;
+       }
+
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               // ??? this is not maximally efficient
+               // Check we'll be able to do the residue!
+
+               // this bit is for pr145693 - we cannot match at all if one of the types is missing, we will be unable
+               // to create the residue
+               if (slots != null) {
+                       for (Iterator i = slots.iterator(); i.hasNext();) {
+                               Slot slot = (Slot) i.next();
+                               ResolvedType rt = slot.formalType;
+                               if (rt.isMissing()) {
+                                       ISourceLocation[] locs = new ISourceLocation[] { getSourceLocation() };
+                                       Message m = new Message(WeaverMessages.format(WeaverMessages.MISSING_TYPE_PREVENTS_MATCH, rt.getName()), "",
+                                                       Message.WARNING, shadow.getSourceLocation(), null, locs);
+                                       rt.getWorld().getMessageHandler().handleMessage(m);
+                                       return FuzzyBoolean.NO;
+                               }
+                       }
+               }
+               return FuzzyBoolean.MAYBE;
+       }
+
+       // used by weaver when validating bindings
+       public int[] getUsedFormalSlots() {
+               if (slots == null)
+                       return new int[0];
+               int[] indices = new int[slots.size()];
+               for (int i = 0; i < indices.length; i++) {
+                       indices[i] = ((Slot) slots.get(i)).formalIndex;
+               }
+               return indices;
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               throw new RuntimeException("unimplemented");
+       }
+
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               throw new RuntimeException("unimplemented");
+       }
+
+       public Pointcut parameterizeWith(Map typeVariableMap, World w) {
+               throw new RuntimeException("unimplemented");
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof ConcreteCflowPointcut))
+                       return false;
+               ConcreteCflowPointcut o = (ConcreteCflowPointcut) other;
+               return o.cflowField.equals(this.cflowField);
+       }
+
+       public int hashCode() {
+               int result = 17;
+               result = 37 * result + cflowField.hashCode();
+               return result;
+       }
+
+       public String toString() {
+               return "concretecflow(" + cflowField + ")";
+       }
+
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               // System.out.println("find residue: " + this);
+               if (usesCounter) {
+                       return Test.makeFieldGetCall(cflowField, cflowCounterIsValidMethod, Expr.NONE);
+               } else {
+                       if (slots != null) { // null for cflows managed by counters
+                               for (Iterator i = slots.iterator(); i.hasNext();) {
+                                       Slot slot = (Slot) i.next();
+                                       // System.out.println("slot: " + slot.formalIndex);
+                                       state.set(slot.formalIndex, aspect.getWorld().getWeavingSupport().makeCflowAccessVar(slot.formalType,
+                                                       cflowField, slot.arrayIndex));
+                               }
+                       }
+                       return Test.makeFieldGetCall(cflowField, cflowStackIsValidMethod, Expr.NONE);
+               }
+       }
+
+       private static final Member cflowStackIsValidMethod = MemberImpl.method(NameMangler.CFLOW_STACK_UNRESOLVEDTYPE, 0,
+                       ResolvedType.BOOLEAN, "isValid", UnresolvedType.NONE);
+
+       private static final Member cflowCounterIsValidMethod = MemberImpl.method(NameMangler.CFLOW_COUNTER_UNRESOLVEDTYPE, 0,
+                       ResolvedType.BOOLEAN, "isValid", UnresolvedType.NONE);
+
+       public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               throw new RuntimeException("unimplemented");
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this, data);
+       }
+
+       public static class Slot {
+               int formalIndex;
+               ResolvedType formalType;
+               int arrayIndex;
+
+               public Slot(int formalIndex, ResolvedType formalType, int arrayIndex) {
+                       this.formalIndex = formalIndex;
+                       this.formalType = formalType;
+                       this.arrayIndex = arrayIndex;
+               }
+
+               public boolean equals(Object other) {
+                       if (!(other instanceof Slot))
+                               return false;
+
+                       Slot o = (Slot) other;
+                       return o.formalIndex == this.formalIndex && o.arrayIndex == this.arrayIndex && o.formalType.equals(this.formalType);
+               }
+
+               public int hashCode() {
+                       int result = 19;
+                       result = 37 * result + formalIndex;
+                       result = 37 * result + arrayIndex;
+                       result = 37 * result + formalType.hashCode();
+                       return result;
+               }
+
+               public String toString() {
+                       return "Slot(" + formalIndex + ", " + formalType + ", " + arrayIndex + ")";
+               }
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/Declare.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/Declare.java
new file mode 100644 (file)
index 0000000..1740010
--- /dev/null
@@ -0,0 +1,87 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+public abstract class Declare extends PatternNode {
+       public static final byte ERROR_OR_WARNING = 1;
+       public static final byte PARENTS = 2;
+       public static final byte SOFT = 3;
+       public static final byte DOMINATES = 4;
+       public static final byte ANNOTATION = 5;
+       
+       // set when reading declare from aspect 
+       private ResolvedType declaringType;
+
+       public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               byte kind = s.readByte();
+               switch (kind) {
+                       case ERROR_OR_WARNING:
+                               return DeclareErrorOrWarning.read(s, context);
+                       case DOMINATES:
+                               return DeclarePrecedence.read(s, context);
+                       case PARENTS:
+                               return DeclareParents.read(s, context);
+                       case SOFT:
+                               return DeclareSoft.read(s, context);
+                       case ANNOTATION:
+                               return DeclareAnnotation.read(s,context);
+                       default:
+                               throw new RuntimeException("unimplemented");
+               }
+       }
+       
+    /**
+     * Returns this declare mutated
+     */
+    public abstract void resolve(IScope scope);
+    
+    /**
+     * Returns a version of this declare element in which all references to type variables
+     * are replaced with their bindings given in the map.
+     */
+    public abstract Declare parameterizeWith(Map typeVariableBindingMap,World w);
+    
+    /**
+     * Indicates if this declare should be treated like advice.  If true, the
+     * declare will have no effect in an abstract aspect.  It will be inherited by
+     * any concrete aspects and will have an effect for each concrete aspect it
+     * is ultimately inherited by.
+     */
+    public abstract boolean isAdviceLike();
+
+       /**
+        * Declares have methods in the .class file against which info can be stored
+        * (for example, the annotation in the case of declare annotation).  The
+        * name is of the form ajc$declare_XXX_NNN where XXX can optionally be set in
+        * this 'getNameSuffix()' method - depending on whether, at weave time, we
+        * want to easily differentiate between the declare methods.
+        */
+       public abstract String getNameSuffix();
+       
+       public void setDeclaringType(ResolvedType aType) {
+               this.declaringType = aType;
+       }
+       
+       public ResolvedType getDeclaringType() {
+               return declaringType;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareAnnotation.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareAnnotation.java
new file mode 100644 (file)
index 0000000..3958566
--- /dev/null
@@ -0,0 +1,408 @@
+/* *******************************************************************
+ * Copyright (c) 2005 IBM Corporation
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Adrian Colyer     initial implementation 
+ *      Andy Clement     got it working
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.weaver.AnnotationAJ;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+
+public class DeclareAnnotation extends Declare {
+
+       public static final Kind AT_TYPE = new Kind(1, "type");
+       public static final Kind AT_FIELD = new Kind(2, "field");
+       public static final Kind AT_METHOD = new Kind(3, "method");
+       public static final Kind AT_CONSTRUCTOR = new Kind(4, "constructor");
+
+       private Kind kind;
+       private TypePattern typePattern; // for declare @type
+       private SignaturePattern sigPattern; // for declare
+       // @field,@method,@constructor
+       private String annotationMethod = "unknown";
+       private String annotationString = "@<annotation>";
+       private ResolvedType containingAspect;
+       private AnnotationAJ annotation;
+
+       /**
+        * Captures type of declare annotation (method/type/field/constructor)
+        */
+       public static class Kind {
+               private final int id;
+               private String s;
+
+               private Kind(int n, String name) {
+                       id = n;
+                       s = name;
+               }
+
+               public int hashCode() {
+                       return (19 + 37 * id);
+               }
+
+               public boolean equals(Object obj) {
+                       if (!(obj instanceof Kind))
+                               return false;
+                       Kind other = (Kind) obj;
+                       return other.id == id;
+               }
+
+               public String toString() {
+                       return "at_" + s;
+               }
+       }
+
+       public DeclareAnnotation(Kind kind, TypePattern typePattern) {
+               this.typePattern = typePattern;
+               this.kind = kind;
+       }
+
+       /**
+        * Returns the string, useful before the real annotation has been resolved
+        */
+       public String getAnnotationString() {
+               return annotationString;
+       }
+
+       public DeclareAnnotation(Kind kind, SignaturePattern sigPattern) {
+               this.sigPattern = sigPattern;
+               this.kind = kind;
+       }
+
+       public boolean isExactPattern() {
+               return typePattern instanceof ExactTypePattern;
+       }
+
+       public String getAnnotationMethod() {
+               return annotationMethod;
+       }
+
+       public String toString() {
+               StringBuffer ret = new StringBuffer();
+               ret.append("declare @");
+               ret.append(kind);
+               ret.append(" : ");
+               ret.append(typePattern != null ? typePattern.toString() : sigPattern
+                               .toString());
+               ret.append(" : ");
+               ret.append(annotationString);
+               return ret.toString();
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this, data);
+       }
+
+       public void resolve(IScope scope) {
+               if (!scope.getWorld().isInJava5Mode()) {
+                       String msg = null;
+                       if (kind == AT_TYPE) {
+                               msg = WeaverMessages.DECLARE_ATTYPE_ONLY_SUPPORTED_AT_JAVA5_LEVEL;
+                       } else if (kind == AT_METHOD) {
+                               msg = WeaverMessages.DECLARE_ATMETHOD_ONLY_SUPPORTED_AT_JAVA5_LEVEL;
+                       } else if (kind == AT_FIELD) {
+                               msg = WeaverMessages.DECLARE_ATFIELD_ONLY_SUPPORTED_AT_JAVA5_LEVEL;
+                       } else if (kind == AT_CONSTRUCTOR) {
+                               msg = WeaverMessages.DECLARE_ATCONS_ONLY_SUPPORTED_AT_JAVA5_LEVEL;
+                       }
+                       scope.message(MessageUtil.error(WeaverMessages.format(msg),
+                                       getSourceLocation()));
+                       return;
+               }
+               if (typePattern != null) {
+                       typePattern = typePattern.resolveBindings(scope, Bindings.NONE,
+                                       false, false);
+               }
+               if (sigPattern != null) {
+                       sigPattern = sigPattern.resolveBindings(scope, Bindings.NONE);
+               }
+               this.containingAspect = scope.getEnclosingType();
+       }
+
+       public Declare parameterizeWith(Map typeVariableBindingMap, World w) {
+               DeclareAnnotation ret;
+               if (this.kind == AT_TYPE) {
+                       ret = new DeclareAnnotation(kind, this.typePattern
+                                       .parameterizeWith(typeVariableBindingMap, w));
+               } else {
+                       ret = new DeclareAnnotation(kind, this.sigPattern.parameterizeWith(
+                                       typeVariableBindingMap, w));
+               }
+               ret.annotationMethod = this.annotationMethod;
+               ret.annotationString = this.annotationString;
+               ret.containingAspect = this.containingAspect;
+               ret.annotation = this.annotation;
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       public boolean isAdviceLike() {
+               return false;
+       }
+
+       public void setAnnotationString(String as) {
+               this.annotationString = as;
+       }
+
+       public void setAnnotationMethod(String methName) {
+               this.annotationMethod = methName;
+       }
+
+       public boolean equals(Object obj) {
+               if (!(obj instanceof DeclareAnnotation))
+                       return false;
+               DeclareAnnotation other = (DeclareAnnotation) obj;
+               if (!this.kind.equals(other.kind))
+                       return false;
+               if (!this.annotationString.equals(other.annotationString))
+                       return false;
+               if (!this.annotationMethod.equals(other.annotationMethod))
+                       return false;
+               if (this.typePattern != null) {
+                       if (!typePattern.equals(other.typePattern))
+                               return false;
+               }
+               if (this.sigPattern != null) {
+                       if (!sigPattern.equals(other.sigPattern))
+                               return false;
+               }
+               return true;
+       }
+
+       public int hashCode() {
+               int result = 19;
+               result = 37 * result + kind.hashCode();
+               result = 37 * result + annotationString.hashCode();
+               result = 37 * result + annotationMethod.hashCode();
+               if (typePattern != null)
+                       result = 37 * result + typePattern.hashCode();
+               if (sigPattern != null)
+                       result = 37 * result + sigPattern.hashCode();
+               return result;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Declare.ANNOTATION);
+               s.writeInt(kind.id);
+               s.writeUTF(annotationString);
+               s.writeUTF(annotationMethod);
+               if (typePattern != null)
+                       typePattern.write(s);
+               if (sigPattern != null)
+                       sigPattern.write(s);
+               writeLocation(s);
+       }
+
+       public static Declare read(VersionedDataInputStream s,
+                       ISourceContext context) throws IOException {
+               DeclareAnnotation ret = null;
+               int kind = s.readInt();
+               String annotationString = s.readUTF();
+               String annotationMethod = s.readUTF();
+               TypePattern tp = null;
+               SignaturePattern sp = null;
+               switch (kind) {
+               case 1:
+                       tp = TypePattern.read(s, context);
+                       ret = new DeclareAnnotation(AT_TYPE, tp);
+                       break;
+               case 2:
+                       sp = SignaturePattern.read(s, context);
+                       ret = new DeclareAnnotation(AT_FIELD, sp);
+                       break;
+               case 3:
+                       sp = SignaturePattern.read(s, context);
+                       ret = new DeclareAnnotation(AT_METHOD, sp);
+                       break;
+               case 4:
+                       sp = SignaturePattern.read(s, context);
+                       ret = new DeclareAnnotation(AT_CONSTRUCTOR, sp);
+                       break;
+
+               }
+               // if (kind==AT_TYPE.id) {
+               // tp = TypePattern.read(s,context);
+               // ret = new DeclareAnnotation(AT_TYPE,tp);
+               // } else {
+               // sp = SignaturePattern.read(s,context);
+               // ret = new DeclareAnnotation(kind,sp);
+               // }
+               ret.setAnnotationString(annotationString);
+               ret.setAnnotationMethod(annotationMethod);
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       // public boolean getAnnotationIfMatches(ResolvedType onType) {
+       // return (match(onType));
+       // }
+
+       /**
+        * For @constructor, @method, @field
+        */
+       public boolean matches(ResolvedMember rm, World world) {
+               return sigPattern.matches(rm, world, false);
+       }
+
+       /**
+        * For @type
+        */
+       public boolean matches(ResolvedType typeX) {
+               if (!typePattern.matchesStatically(typeX))
+                       return false;
+               if (typeX.getWorld().getLint().typeNotExposedToWeaver.isEnabled()
+                               && !typeX.isExposedToWeaver()) {
+                       typeX.getWorld().getLint().typeNotExposedToWeaver.signal(typeX
+                                       .getName(), getSourceLocation());
+               }
+               return true;
+       }
+
+       public void setAspect(ResolvedType typeX) {
+               containingAspect = typeX;
+       }
+
+       public UnresolvedType getAspect() {
+               return containingAspect;
+       }
+
+       public void copyAnnotationTo(ResolvedType onType) {
+               ensureAnnotationDiscovered();
+               if (!onType.hasAnnotation(annotation.getType())) {
+                       onType.addAnnotation(annotation);
+               }
+       }
+
+       public AnnotationAJ getAnnotationX() {
+               ensureAnnotationDiscovered();
+               return annotation;
+       }
+
+       /**
+        * The annotation specified in the declare @type is stored against a simple
+        * method of the form "ajc$declare_<NN>", this method finds that method and
+        * retrieves the annotation
+        */
+       private void ensureAnnotationDiscovered() {
+               if (annotation != null)
+                       return;
+               for (Iterator iter = containingAspect.getMethods(); iter.hasNext();) {
+                       ResolvedMember member = (ResolvedMember) iter.next();
+                       if (member.getName().equals(annotationMethod)) {
+                               annotation = member.getAnnotations()[0];
+                       }
+               }
+       }
+
+       public TypePattern getTypePattern() {
+               return typePattern;
+       }
+
+       public SignaturePattern getSignaturePattern() {
+               return sigPattern;
+       }
+
+       public boolean isStarredAnnotationPattern() {
+               if (typePattern != null)
+                       return typePattern.isStarAnnotation();
+               if (sigPattern != null)
+                       return sigPattern.isStarAnnotation();
+               throw new RuntimeException("Impossible! what kind of deca is this: "
+                               + this);
+       }
+
+       public Kind getKind() {
+               return kind;
+       }
+
+       public boolean isDeclareAtConstuctor() {
+               return kind.equals(AT_CONSTRUCTOR);
+       }
+
+       public boolean isDeclareAtMethod() {
+               return kind.equals(AT_METHOD);
+       }
+
+       public boolean isDeclareAtType() {
+               return kind.equals(AT_TYPE);
+       }
+
+       public boolean isDeclareAtField() {
+               return kind.equals(AT_FIELD);
+       }
+
+       /**
+        * @return UnresolvedType for the annotation
+        */
+       public UnresolvedType getAnnotationTypeX() {
+               ensureAnnotationDiscovered();
+               return this.annotation.getType();
+       }
+
+       /**
+        * @return true if the annotation specified is allowed on a field
+        */
+       public boolean isAnnotationAllowedOnField() {
+               ensureAnnotationDiscovered();
+               return annotation.allowedOnField();
+       }
+
+       public String getPatternAsString() {
+               if (sigPattern != null)
+                       return sigPattern.toString();
+               if (typePattern != null)
+                       return typePattern.toString();
+               return "DONT KNOW";
+       }
+
+       /**
+        * Return true if this declare annotation could ever match something in the
+        * specified type - only really able to make intelligent decision if a type
+        * was specified in the sig/type pattern signature.
+        */
+       public boolean couldEverMatch(ResolvedType type) {
+               // Haven't implemented variant for typePattern (doesn't seem worth it!)
+               // BUGWARNING This test might not be sufficient for funny cases relating
+               // to interfaces and the use of '+' - but it seems really important to
+               // do something here so we don't iterate over all fields and all methods
+               // in all types exposed to the weaver! So look out for bugs here and
+               // we can update the test as appropriate.
+               if (sigPattern != null)
+                       return sigPattern.getDeclaringType().matches(type,
+                                       TypePattern.STATIC).maybeTrue();
+               return true;
+       }
+
+       /**
+        * Provide a name suffix so that we can tell the different declare
+        * annotations forms apart in the AjProblemReporter
+        */
+       public String getNameSuffix() {
+               return getKind().toString();
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareErrorOrWarning.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareErrorOrWarning.java
new file mode 100644 (file)
index 0000000..c892293
--- /dev/null
@@ -0,0 +1,129 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+public class DeclareErrorOrWarning extends Declare {
+       private boolean isError;
+       private Pointcut pointcut;
+       private String message;
+
+       public DeclareErrorOrWarning(boolean isError, Pointcut pointcut, String message) {
+               this.isError = isError;
+               this.pointcut = pointcut;
+               this.message = message;
+       }
+       
+       /**
+        * returns "declare warning: <message>" or "declare error: <message>"
+        */
+       public String toString() {
+               StringBuffer buf = new StringBuffer();
+               buf.append("declare ");
+               if (isError) buf.append("error: ");
+               else buf.append("warning: ");
+               buf.append(pointcut);
+               buf.append(": ");
+               buf.append("\"");
+               buf.append(message);
+               buf.append("\";");
+               return buf.toString();
+       }
+       
+       public boolean equals(Object other) { 
+               if (!(other instanceof DeclareErrorOrWarning)) return false;
+               DeclareErrorOrWarning o = (DeclareErrorOrWarning)other;
+               return (o.isError == isError) &&
+                       o.pointcut.equals(pointcut) &&
+                       o.message.equals(message);
+       }
+    
+    public int hashCode() {
+        int result = isError ? 19 : 23;
+        result = 37*result + pointcut.hashCode();
+        result = 37*result + message.hashCode();
+        return result;
+    }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Declare.ERROR_OR_WARNING);
+               s.writeBoolean(isError);
+               pointcut.write(s);
+               s.writeUTF(message);
+               writeLocation(s);
+       }
+
+       public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               Declare ret = new DeclareErrorOrWarning(
+                       s.readBoolean(),
+                       Pointcut.read(s, context),
+                       s.readUTF()
+               );
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+
+       public boolean isError() {
+               return isError;
+       }
+
+       public String getMessage() {
+               return message;
+       }
+
+       public Pointcut getPointcut() {
+               return pointcut;
+       }
+       
+    public void resolve(IScope scope) {
+       pointcut = pointcut.resolve(scope);     
+    }
+    
+    public Declare parameterizeWith(Map typeVariableBindingMap,World w) {
+       Declare ret = new DeclareErrorOrWarning(isError,pointcut.parameterizeWith(typeVariableBindingMap,w),message);
+       ret.copyLocationFrom(this);
+       return ret;
+    }
+    
+       public boolean isAdviceLike() {
+               return true;
+       }
+
+       public String getNameSuffix() {
+               return "eow";
+       }
+       
+       /**
+        * returns "declare warning" or "declare error"
+        */
+       public String getName() {
+               StringBuffer buf = new StringBuffer();
+               buf.append("declare ");
+               if (isError) buf.append("error");
+               else buf.append("warning");     
+               return buf.toString();
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParents.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParents.java
new file mode 100644 (file)
index 0000000..3d97bca
--- /dev/null
@@ -0,0 +1,352 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.Message;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+
+public class DeclareParents extends Declare {
+       private TypePattern child;
+       private TypePatternList parents;
+       private boolean isWildChild = false;
+       private boolean isExtends = true;
+//     private String[] typeVariablesInScope = new String[0]; // AspectJ 5 extension for generic types
+       
+
+       public DeclareParents(TypePattern child, List parents, boolean isExtends) {
+               this(child, new TypePatternList(parents),isExtends);
+       }
+       
+       private DeclareParents(TypePattern child, TypePatternList parents, boolean isExtends) {
+               this.child = child;
+               this.parents = parents;
+               this.isExtends = isExtends;
+               if (child instanceof WildTypePattern) isWildChild = true;
+       }
+       
+//     public String[] getTypeParameterNames() {
+//             return this.typeVariablesInScope;
+//     }
+//     
+//     public void setTypeParametersInScope(String[] typeParameters) {
+//             this.typeVariablesInScope = typeParameters;
+//     }
+       
+       public boolean match(ResolvedType typeX) {
+               if (!child.matchesStatically(typeX)) return false;
+               if (typeX.getWorld().getLint().typeNotExposedToWeaver.isEnabled() &&
+                               !typeX.isExposedToWeaver())
+               {
+                       typeX.getWorld().getLint().typeNotExposedToWeaver.signal(typeX.getName(), getSourceLocation());
+               }
+               
+               return true;
+       }
+       
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
+       public Declare parameterizeWith(Map typeVariableBindingMap,World w) {
+               DeclareParents ret = 
+                       new DeclareParents(
+                                       child.parameterizeWith(typeVariableBindingMap,w),
+                                       parents.parameterizeWith(typeVariableBindingMap,w),
+                                       isExtends);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public String toString() {
+               StringBuffer buf = new StringBuffer();
+               buf.append("declare parents: ");
+               buf.append(child);
+               buf.append(isExtends ? " extends " : " implements ");  //extends and implements are treated equivalently
+               buf.append(parents);
+               buf.append(";");
+               return buf.toString();
+       }
+       
+       public boolean equals(Object other) { 
+               if (!(other instanceof DeclareParents)) return false;
+               DeclareParents o = (DeclareParents)other;
+               return o.child.equals(child) && o.parents.equals(parents);
+       }
+    
+    //??? cache this 
+    public int hashCode() {
+       int result = 23;
+        result = 37*result + child.hashCode();
+        result = 37*result + parents.hashCode();
+       return result;
+    }
+
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Declare.PARENTS);
+               child.write(s);
+               parents.write(s);
+//             s.writeInt(typeVariablesInScope.length);
+//             for (int i = 0; i < typeVariablesInScope.length; i++) {
+//                     s.writeUTF(typeVariablesInScope[i]);
+//             }
+               writeLocation(s);
+       }
+
+       public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               DeclareParents ret = new DeclareParents(TypePattern.read(s, context), TypePatternList.read(s, context),true);
+//             if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
+//                     int numTypeVariablesInScope = s.readInt();
+//                     ret.typeVariablesInScope = new String[numTypeVariablesInScope];
+//                     for (int i = 0; i < numTypeVariablesInScope; i++) {
+//                             ret.typeVariablesInScope[i] = s.readUTF();
+//                     }
+//             }
+               ret.readLocation(context, s);
+               return ret;
+       }
+       
+       public boolean parentsIncludeInterface(World w) {
+               for (int i = 0; i < parents.size(); i++) {
+                       if (parents.get(i).getExactType().resolve(w).isInterface()) return true;
+               }
+         return false; 
+       }
+       public boolean parentsIncludeClass(World w) {
+               for (int i = 0; i < parents.size(); i++) {
+                       if (parents.get(i).getExactType().resolve(w).isClass()) return true;
+               }
+         return false; 
+       }
+       
+    public void resolve(IScope scope) {
+//             ScopeWithTypeVariables resolutionScope = new ScopeWithTypeVariables(typeVariablesInScope,scope);
+       child = child.resolveBindings(scope, Bindings.NONE, false, false);
+       parents = parents.resolveBindings(scope, Bindings.NONE, false, true); 
+
+//      Could assert this ...
+//             for (int i=0; i < parents.size(); i++) {
+//                     parents.get(i).assertExactType(scope.getMessageHandler());
+//                     }
+    }
+
+       public TypePatternList getParents() {
+               return parents;
+       }
+
+       public TypePattern getChild() {
+               return child;
+       }
+       
+       // note - will always return true after deserialization, this doesn't affect weaver
+       public boolean isExtends() {
+               return this.isExtends;
+       }
+       
+       public boolean isAdviceLike() {
+               return false;
+       }
+       
+       private ResolvedType maybeGetNewParent(ResolvedType targetType, TypePattern typePattern, World world,boolean reportErrors) {
+               if (typePattern == TypePattern.NO) return null;  // already had an error here
+               UnresolvedType iType = typePattern.getExactType();
+               ResolvedType parentType = iType.resolve(world);
+               
+               if (targetType.equals(world.getCoreType(UnresolvedType.OBJECT))) {
+                       world.showMessage(IMessage.ERROR, 
+                                       WeaverMessages.format(WeaverMessages.DECP_OBJECT),
+                               this.getSourceLocation(), null);
+                       return null;
+               }
+               
+               // Ensure the target doesn't already have an 
+               // alternate parameterization of the generic type on it
+               if (parentType.isParameterizedType() || parentType.isRawType()) {
+                       // Let's take a look at the parents we already have
+                       boolean isOK = verifyNoInheritedAlternateParameterization(targetType,parentType,world);
+                       if (!isOK) return null;
+               }
+
+               if (parentType.isAssignableFrom(targetType)) return null;  // already a parent
+               
+               // Enum types that are targetted for decp through a wild type pattern get linted 
+               if (reportErrors && isWildChild && targetType.isEnum()) {
+                       world.getLint().enumAsTargetForDecpIgnored.signal(targetType.toString(),getSourceLocation());   
+               }
+               
+               // Annotation types that are targetted for decp through a wild type pattern get linted 
+               if (reportErrors && isWildChild && targetType.isAnnotation()) {
+                       world.getLint().annotationAsTargetForDecpIgnored.signal(targetType.toString(),getSourceLocation());     
+               }
+
+               // 1. Can't use decp to make an enum/annotation type implement an interface
+               if (targetType.isEnum() && parentType.isInterface()) {
+                       if (reportErrors && !isWildChild)  {
+                               world.showMessage(IMessage.ERROR,
+                                               WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ENUM_TO_IMPL_INTERFACE,targetType),getSourceLocation(),null);
+                       }
+                       return null;
+               }
+               if (targetType.isAnnotation() && parentType.isInterface()) {
+                       if (reportErrors && !isWildChild)  {
+                               world.showMessage(IMessage.ERROR,WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ANNOTATION_TO_IMPL_INTERFACE,targetType),getSourceLocation(),null);
+                       }
+                       return null;
+               }
+               
+               // 2. Can't use decp to change supertype of an enum/annotation
+               if (targetType.isEnum() && parentType.isClass()) {
+                       if (reportErrors && !isWildChild) {
+                               world.showMessage(IMessage.ERROR,WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ENUM_TO_EXTEND_CLASS,targetType),getSourceLocation(),null);
+                       }
+                       return null;
+               }
+               if (targetType.isAnnotation() && parentType.isClass()) {
+                       if (reportErrors && !isWildChild) {
+                               world.showMessage(IMessage.ERROR,WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ANNOTATION_TO_EXTEND_CLASS,targetType),getSourceLocation(),null);
+                       }
+                       return null;
+               }
+               
+               // 3. Can't use decp to declare java.lang.Enum/java.lang.annotation.Annotation as the parent of a type
+               if (parentType.getSignature().equals(UnresolvedType.ENUM.getSignature())) {
+                       if (reportErrors && !isWildChild) {
+                           world.showMessage(IMessage.ERROR,
+                                       WeaverMessages.format(WeaverMessages.CANT_DECP_TO_MAKE_ENUM_SUPERTYPE,targetType),getSourceLocation(),null);
+                       }
+                       return null;
+               }       
+               if (parentType.getSignature().equals(UnresolvedType.ANNOTATION.getSignature())) {
+                       if (reportErrors && !isWildChild) {
+                           world.showMessage(IMessage.ERROR,
+                                       WeaverMessages.format(WeaverMessages.CANT_DECP_TO_MAKE_ANNOTATION_SUPERTYPE,targetType),getSourceLocation(),null);
+                       }
+                       return null;
+               }       
+                       
+               if (parentType.isAssignableFrom(targetType)) return null;  // already a parent
+
+               if (targetType.isAssignableFrom(parentType)) {
+                       world.showMessage(IMessage.ERROR,
+                                       WeaverMessages.format(WeaverMessages.CANT_EXTEND_SELF,targetType.getName()),
+                                       this.getSourceLocation(), null
+                       );
+                       return null;
+               }
+                                       
+               if (parentType.isClass()) {
+                       if (targetType.isInterface()) {
+                               world.showMessage(IMessage.ERROR, 
+                                               WeaverMessages.format(WeaverMessages.INTERFACE_CANT_EXTEND_CLASS),
+                                               this.getSourceLocation(), null
+                               );
+                               return null;
+                               // how to handle xcutting errors???
+                       }
+                       
+                       if (!targetType.getSuperclass().isAssignableFrom(parentType)) {
+                               world.showMessage(IMessage.ERROR,
+                                               WeaverMessages.format(WeaverMessages.DECP_HIERARCHY_ERROR,
+                                                               iType.getName(),
+                                                               targetType.getSuperclass().getName()), 
+                                               this.getSourceLocation(), null
+                               );
+                               return null;
+                       } else {
+                               return parentType;
+                       }                               
+               } else {
+                       return parentType;
+               }
+       }
+       
+       /**
+        * This method looks through the type hierarchy for some target type - it is attempting to
+        * find an existing parameterization that clashes with the new parent that the user
+        * wants to apply to the type.  If it finds an existing parameterization that matches the
+        * new one, it silently completes, if it finds one that clashes (e.g. a type already has
+        * A<String> when the user wants to add A<Number>) then it will produce an error.
+        * 
+        * It uses recursion and exits recursion on hitting 'jlObject'
+     *
+        * Related bugzilla entries: pr110788
+        */
+       private boolean verifyNoInheritedAlternateParameterization(ResolvedType typeToVerify,ResolvedType newParent,World world) {
+               
+
+               if (typeToVerify.equals(ResolvedType.OBJECT)) return true;
+
+               ResolvedType newParentGenericType = newParent.getGenericType();
+               Iterator iter = typeToVerify.getDirectSupertypes();
+               while (iter.hasNext()) {
+                       ResolvedType supertype = (ResolvedType)iter.next();
+                       if ( ((supertype.isRawType() && newParent.isParameterizedType()) || 
+                             (supertype.isParameterizedType() && newParent.isRawType())) && newParentGenericType.equals(supertype.getGenericType())) {
+                               // new parent is a parameterized type, but this is a raw type
+                               world.getMessageHandler().handleMessage(new Message(
+                                       WeaverMessages.format(WeaverMessages.CANT_DECP_MULTIPLE_PARAMETERIZATIONS,newParent.getName(),typeToVerify.getName(),supertype.getName()),
+                                       getSourceLocation(), true, new ISourceLocation[]{typeToVerify.getSourceLocation()}));
+                               return false;
+                       }
+                       if (supertype.isParameterizedType()) {
+                               ResolvedType generictype = supertype.getGenericType();
+                               
+                               // If the generic types are compatible but the parameterizations aren't then we have a problem
+                               if (generictype.isAssignableFrom(newParentGenericType) && 
+                                               !supertype.isAssignableFrom(newParent)) {
+                                       world.getMessageHandler().handleMessage(new Message(
+                                                       WeaverMessages.format(WeaverMessages.CANT_DECP_MULTIPLE_PARAMETERIZATIONS,newParent.getName(),typeToVerify.getName(),supertype.getName()),
+                                                       getSourceLocation(), true, new ISourceLocation[]{typeToVerify.getSourceLocation()}));
+                                       return false;
+                               }
+                       }
+                       if (!verifyNoInheritedAlternateParameterization(supertype,newParent,world)) {
+                               return false;
+                       }
+               }
+               return true;
+       }
+
+       public List/*<ResolvedType>*/ findMatchingNewParents(ResolvedType onType,boolean reportErrors) {
+               if (onType.isRawType()) onType = onType.getGenericType();
+               if (!match(onType)) return Collections.EMPTY_LIST;
+               
+               List ret = new ArrayList();
+               for (int i=0; i < parents.size(); i++) {
+                       ResolvedType t = maybeGetNewParent(onType, parents.get(i), onType.getWorld(),reportErrors);
+                       if (t != null) ret.add(t);
+               }
+               
+               return ret;
+       }
+
+       public String getNameSuffix() {
+               return "parents";
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclarePrecedence.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclarePrecedence.java
new file mode 100644 (file)
index 0000000..810f5ed
--- /dev/null
@@ -0,0 +1,166 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+
+public class DeclarePrecedence extends Declare {
+       private TypePatternList patterns;
+       
+
+       public DeclarePrecedence(List patterns) {
+               this(new TypePatternList(patterns));
+       }
+       
+       private DeclarePrecedence(TypePatternList patterns) {
+               this.patterns = patterns;
+       }
+       
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
+       public Declare parameterizeWith(Map typeVariableBindingMap,World w) {
+               DeclarePrecedence ret = new DeclarePrecedence(this.patterns.parameterizeWith(typeVariableBindingMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public String toString() {
+               StringBuffer buf = new StringBuffer();
+               buf.append("declare precedence: ");
+               buf.append(patterns);
+               buf.append(";");
+               return buf.toString();
+       }
+       
+       public boolean equals(Object other) { 
+               if (!(other instanceof DeclarePrecedence)) return false;
+               DeclarePrecedence o = (DeclarePrecedence)other;
+               return o.patterns.equals(patterns);
+       }
+    
+    public int hashCode() {
+       return patterns.hashCode();
+    }
+
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Declare.DOMINATES);
+               patterns.write(s);
+               writeLocation(s);
+       }
+       
+       public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               Declare ret = new DeclarePrecedence(TypePatternList.read(s, context));
+               ret.readLocation(context, s);
+               return ret;
+       }
+       
+    public void resolve(IScope scope) {
+       patterns = patterns.resolveBindings(scope, Bindings.NONE, false, false); 
+       boolean seenStar = false;
+       
+       for (int i=0; i < patterns.size(); i++) {
+               TypePattern pi = patterns.get(i);
+               if (pi.isStar()) {
+                       if (seenStar) {
+                               scope.getWorld().showMessage(IMessage.ERROR,
+                                               WeaverMessages.format(WeaverMessages.TWO_STARS_IN_PRECEDENCE),
+                                                       pi.getSourceLocation(), null);                                  
+                       }
+                       seenStar = true;
+                       continue;
+               }
+               ResolvedType exactType = pi.getExactType().resolve(scope.getWorld());
+               if (exactType.isMissing()) continue;
+               
+               // Cannot do a dec prec specifying a non-aspect types unless suffixed with a '+'
+               if (!exactType.isAspect() && !pi.isIncludeSubtypes() && !exactType.isTypeVariableReference()) {
+                       scope.getWorld().showMessage(IMessage.ERROR,
+                                       WeaverMessages.format(WeaverMessages.CLASSES_IN_PRECEDENCE,exactType.getName()),
+                                               pi.getSourceLocation(),null);
+               }
+               
+               for (int j=0; j < patterns.size(); j++) {
+                       if (j == i) continue;
+                       TypePattern pj = patterns.get(j);
+                       if (pj.isStar()) continue;
+                       if (pj.matchesStatically(exactType)) {
+                               scope.getWorld().showMessage(IMessage.ERROR,
+                                               WeaverMessages.format(WeaverMessages.TWO_PATTERN_MATCHES_IN_PRECEDENCE,exactType.getName()), 
+                                                       pi.getSourceLocation(), pj.getSourceLocation());
+                       }
+               }
+       }       
+    }
+
+       public TypePatternList getPatterns() {
+               return patterns;
+       }
+
+       private int matchingIndex(ResolvedType a) {
+               int knownMatch = -1;
+               int starMatch = -1;
+               for (int i=0, len=patterns.size(); i < len; i++) {
+                       TypePattern p = patterns.get(i);
+                       if (p.isStar()) {
+                               starMatch = i;
+                       } else if (p.matchesStatically(a)) {
+                               if (knownMatch != -1) {
+                                       a.getWorld().showMessage(IMessage.ERROR,
+                                                       WeaverMessages.format(WeaverMessages.MULTIPLE_MATCHES_IN_PRECEDENCE,a,patterns.get(knownMatch),p),
+                                                       patterns.get(knownMatch).getSourceLocation(), p.getSourceLocation());
+                                       return -1;
+                               } else {
+                                       knownMatch = i;
+                               }
+                       }
+               }
+               if (knownMatch == -1) return starMatch;
+               else return knownMatch;
+       }
+       
+
+       public int compare(ResolvedType aspect1, ResolvedType aspect2) {
+               int index1 = matchingIndex(aspect1);
+               int index2 = matchingIndex(aspect2);
+               
+               //System.out.println("a1: " + aspect1 + ", " + aspect2 + " = " + index1 + ", " + index2);
+               
+               if (index1 == -1 || index2 == -1) return 0;
+               
+               if (index1 == index2) return 0;
+               else if (index1 > index2) return -1;
+               else return +1;
+       }
+       
+       public boolean isAdviceLike() {
+               return false;
+       }
+
+       public String getNameSuffix() {
+               return "precedence";
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareSoft.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareSoft.java
new file mode 100644 (file)
index 0000000..c8a3bfa
--- /dev/null
@@ -0,0 +1,137 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.TypeVariableReferenceType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+
+public class DeclareSoft extends Declare {
+       private TypePattern exception;
+       private Pointcut pointcut;
+
+       public DeclareSoft(TypePattern exception, Pointcut pointcut) {
+               this.exception = exception;
+               this.pointcut = pointcut;
+       }
+       
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
+       public Declare parameterizeWith(Map typeVariableBindingMap,World w) {
+               DeclareSoft ret = 
+                       new DeclareSoft(
+                                       exception.parameterizeWith(typeVariableBindingMap,w),
+                                       pointcut.parameterizeWith(typeVariableBindingMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public String toString() {
+               StringBuffer buf = new StringBuffer();
+               buf.append("declare soft: ");
+               buf.append(exception);
+               buf.append(": ");
+               buf.append(pointcut);
+               buf.append(";");
+               return buf.toString();
+       }
+       
+       public boolean equals(Object other) { 
+               if (!(other instanceof DeclareSoft)) return false;
+               DeclareSoft o = (DeclareSoft)other;
+               return
+                       o.pointcut.equals(pointcut) &&
+                       o.exception.equals(exception);
+       }
+    
+    public int hashCode() {
+        int result = 19;
+        result = 37*result + pointcut.hashCode();
+        result = 37*result + exception.hashCode();
+        return result;
+    }
+
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Declare.SOFT);
+               exception.write(s);
+               pointcut.write(s);
+               writeLocation(s);
+       }
+
+       public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               Declare ret = new DeclareSoft(
+                       TypePattern.read(s, context),
+                       Pointcut.read(s, context)
+               );
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public Pointcut getPointcut() {
+               return pointcut;
+       }
+       
+       public TypePattern getException() {
+               return exception;
+       }
+
+    public void resolve(IScope scope) {
+       exception = exception.resolveBindings(scope, null, false, true);
+       ResolvedType excType = exception.getExactType().resolve(scope.getWorld());
+       if (!excType.isMissing()) {
+               if (excType.isTypeVariableReference()) {
+                   TypeVariableReferenceType typeVariableRT = (TypeVariableReferenceType) excType;
+                       // a declare soft in a generic abstract aspect, we need to check the upper bound
+                       excType = typeVariableRT.getUpperBound().resolve(scope.getWorld());
+               }
+               if (!scope.getWorld().getCoreType(UnresolvedType.THROWABLE).isAssignableFrom(excType)) {
+                       scope.getWorld().showMessage(IMessage.ERROR,
+                                       WeaverMessages.format(WeaverMessages.NOT_THROWABLE,excType.getName()),
+                                       exception.getSourceLocation(), null);
+                       pointcut = Pointcut.makeMatchesNothing(Pointcut.RESOLVED);
+                       return;
+               }
+               // ENH 42743 suggests that we don't soften runtime exceptions.
+                       if (scope.getWorld().getCoreType(UnresolvedType.RUNTIME_EXCEPTION).isAssignableFrom(excType)) {
+                           scope.getWorld().getLint().runtimeExceptionNotSoftened.signal(
+                                       new String[]{excType.getName()},
+                                       exception.getSourceLocation(),null);
+                               pointcut = Pointcut.makeMatchesNothing(Pointcut.RESOLVED);
+                               return;
+                       }                       
+       }
+       
+       pointcut = pointcut.resolve(scope);     
+    }
+    
+    public boolean isAdviceLike() {
+               return true;
+       }
+       
+       public String getNameSuffix() {
+               return "soft";
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationFieldTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationFieldTypePattern.java
new file mode 100644 (file)
index 0000000..0263035
--- /dev/null
@@ -0,0 +1,206 @@
+/* *******************************************************************
+ * Copyright (c) 2008 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement     initial implementation 
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ReferenceType;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+/**
+ * Represents an attempt to bind the field of an annotation within a pointcut. For example:<br>
+ * <code><pre>
+ * before(Level lev): execution(* *(..)) &amp;&amp; @annotation(TraceAnnotation(lev))
+ * </pre></code><br>
+ * This binding annotation type pattern will be for 'lev'.
+ */
+public class ExactAnnotationFieldTypePattern extends ExactAnnotationTypePattern {
+
+    UnresolvedType annotationType;
+    private ResolvedMember field;
+    
+    public ExactAnnotationFieldTypePattern(ExactAnnotationTypePattern p, String formalName) {
+        super(formalName);
+        this.annotationType = p.annotationType;
+        this.copyLocationFrom(p);
+    }
+
+    public ExactAnnotationFieldTypePattern(UnresolvedType annotationType, String formalName) {
+        super(formalName);
+        this.annotationType = annotationType;
+    }
+
+    /**
+     * resolve one of these funky things. Need to: <br>
+     * (a) Check the formal is bound <br>
+     * (b) Check the annotation type is valid
+     */
+    public AnnotationTypePattern resolveBindings(IScope scope, Bindings bindings, boolean allowBinding) {
+        if (resolved) return this;
+        resolved = true;
+        FormalBinding formalBinding = scope.lookupFormal(formalName);
+        if (formalBinding == null) {
+            scope.message(IMessage.ERROR, this, "When using @annotation(<annotationType>(<annotationField>)), <annotationField> must be bound");
+            return this;
+        }
+
+        annotationType = scope.getWorld().resolve(annotationType, true);
+
+        // May not be directly found if in a package, so go looking if that is the case:
+        if (ResolvedType.isMissing(annotationType)) {
+            String cleanname = annotationType.getName();
+            UnresolvedType type = null;
+            while (ResolvedType.isMissing(type = scope.lookupType(cleanname, this))) {
+                int lastDot = cleanname.lastIndexOf('.');
+                if (lastDot == -1) break;
+                cleanname = cleanname.substring(0, lastDot) + "$" + cleanname.substring(lastDot + 1);
+            }
+            annotationType = scope.getWorld().resolve(type, true);
+            if (ResolvedType.isMissing(annotationType)) {
+               // there are likely to be other errors around that have led to us being unable to 
+               // resolve the annotation type, let's quit now
+                return this;
+            }
+        }
+
+        verifyIsAnnotationType((ResolvedType) annotationType, scope);
+
+        if (!formalBinding.getType().resolve(scope.getWorld()).isEnum()) {
+            scope.message(IMessage.ERROR, this, "The field within the annotation must be an Enum. '" + formalBinding.getType()
+                + "' is not an Enum (compiler limitation)");
+        }
+        bindingPattern = true;
+
+        // Check that the formal is bound to a type that is represented by one field in the annotation type
+        ReferenceType theAnnotationType = (ReferenceType) annotationType;
+        ResolvedMember[] annotationFields = theAnnotationType.getDeclaredMethods();
+        field = null;
+        for (int i = 0; i < annotationFields.length; i++) {
+            ResolvedMember resolvedMember = annotationFields[i];
+            if (resolvedMember.getReturnType().equals(formalBinding.getType())) {
+                if (field != null) {
+                    scope.message(IMessage.ERROR, this, "The field type '" + formalBinding.getType() + "' is ambiguous for annotation type '"
+                        + theAnnotationType.getName() + "'");
+                }
+                field = resolvedMember;
+            }
+        }
+        if (field == null) {
+            scope.message(IMessage.ERROR, this, "No field of type '" + formalBinding.getType() + "' exists on annotation type '"
+                + theAnnotationType.getName() + "'");
+        }
+                
+        BindingAnnotationFieldTypePattern binding = new BindingAnnotationFieldTypePattern(formalBinding.getType(), formalBinding.getIndex(),
+            theAnnotationType);
+        binding.copyLocationFrom(this);
+        bindings.register(binding, scope);
+        binding.resolveBinding(scope.getWorld());
+        return binding;
+    }
+    
+    public void write(DataOutputStream s) throws IOException {
+        s.writeByte(AnnotationTypePattern.EXACTFIELD);
+        s.writeUTF(formalName);
+        annotationType.write(s);
+        writeLocation(s);
+    }
+
+    public static AnnotationTypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+        ExactAnnotationFieldTypePattern ret;
+        String formalName = s.readUTF();
+        UnresolvedType annotationType = UnresolvedType.read(s);
+        ret = new ExactAnnotationFieldTypePattern(annotationType, formalName);
+        ret.readLocation(context, s);
+        return ret;
+    }
+
+    // ---
+    
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+
+    public boolean equals(Object obj) {
+        if (!(obj instanceof ExactAnnotationFieldTypePattern)) return false;
+        ExactAnnotationFieldTypePattern other = (ExactAnnotationFieldTypePattern) obj;
+        return 
+            (other.annotationType.equals(annotationType)) && 
+            (other.field.equals(field)) && (other.formalName.equals(this.formalName));
+    }
+
+    public int hashCode() {
+        int hashcode = annotationType.hashCode();
+        hashcode = hashcode * 37 + field.hashCode();
+        hashcode = hashcode * 37 + formalName.hashCode();
+        return hashcode;
+    }
+
+    // TODO these are currently unimplemented as I believe it resolves to a Binding form *always* and so they don't get
+    // called
+    
+    public FuzzyBoolean fastMatches(AnnotatedElement annotated) {
+        throw new BCException("unimplemented");
+    }
+
+    public UnresolvedType getAnnotationType() {
+        throw new BCException("unimplemented");
+    }
+
+    public Map getAnnotationValues() {
+        throw new BCException("unimplemented");
+    }
+
+    public ResolvedType getResolvedAnnotationType() {
+        throw new BCException("unimplemented");
+    }
+
+
+    public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations) {
+        throw new BCException("unimplemented");
+    }
+
+    public FuzzyBoolean matches(AnnotatedElement annotated) {
+        throw new BCException("unimplemented");
+    }
+
+    public FuzzyBoolean matchesRuntimeType(AnnotatedElement annotated) {
+        throw new BCException("unimplemented");
+    }
+
+    public AnnotationTypePattern parameterizeWith(Map typeVariableMap, World w) {
+        throw new BCException("unimplemented");
+    }
+
+    public void resolve(World world) {
+        throw new BCException("unimplemented");
+    }
+
+    public String toString() {
+        if (!resolved && formalName != null) return formalName;
+        StringBuffer ret = new StringBuffer();
+        ret.append("@").append(annotationType.toString());
+        ret.append("(").append(formalName).append(")");
+        return ret.toString();
+    }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java
new file mode 100644 (file)
index 0000000..539dc6b
--- /dev/null
@@ -0,0 +1,469 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.AnnotationAJ;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ReferenceType;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.TypeVariableReference;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
+
+/**
+ * Matches an annotation of a given type
+ */
+public class ExactAnnotationTypePattern extends AnnotationTypePattern {
+
+       protected UnresolvedType annotationType;
+       protected String formalName;
+       protected boolean resolved = false;
+       protected boolean bindingPattern = false;
+       private Map annotationValues;
+
+       // OPTIMIZE is annotationtype really unresolved???? surely it is resolved by
+       // now...
+       public ExactAnnotationTypePattern(UnresolvedType annotationType,
+                       Map annotationValues) {
+               this.annotationType = annotationType;
+               this.annotationValues = annotationValues;
+               this.resolved = (annotationType instanceof ResolvedType);
+       }
+
+       // Used when deserializing, values will be added
+       private ExactAnnotationTypePattern(UnresolvedType annotationType) {
+               this.annotationType = annotationType;
+               this.resolved = (annotationType instanceof ResolvedType);
+       }
+
+       protected ExactAnnotationTypePattern(String formalName) {
+               this.formalName = formalName;
+               this.resolved = false;
+               this.bindingPattern = true;
+               // will be turned into BindingAnnotationTypePattern during resolution
+       }
+
+       public ResolvedType getResolvedAnnotationType() {
+               if (!resolved)
+                       throw new IllegalStateException("I need to be resolved first!");
+               return (ResolvedType) annotationType;
+       }
+
+       public UnresolvedType getAnnotationType() {
+               return annotationType;
+       }
+
+       public Map getAnnotationValues() {
+               return annotationValues;
+       }
+
+       public FuzzyBoolean fastMatches(AnnotatedElement annotated) {
+               if (annotated.hasAnnotation(annotationType) && annotationValues == null) {
+                       return FuzzyBoolean.YES;
+               } else {
+                       // could be inherited, but we don't know that until we are
+                       // resolved, and we're not yet...
+                       return FuzzyBoolean.MAYBE;
+               }
+       }
+
+       public FuzzyBoolean matches(AnnotatedElement annotated) {
+               return matches(annotated, null);
+       }
+
+       public FuzzyBoolean matches(AnnotatedElement annotated,
+                       ResolvedType[] parameterAnnotations) {
+               if (!isForParameterAnnotationMatch()) {
+                       boolean checkSupers = false;
+                       if (getResolvedAnnotationType().hasAnnotation(
+                                       UnresolvedType.AT_INHERITED)) {
+                               if (annotated instanceof ResolvedType) {
+                                       checkSupers = true;
+                               }
+                       }
+
+                       if (annotated.hasAnnotation(annotationType)) {
+                               if (annotationType instanceof ReferenceType) {
+                                       ReferenceType rt = (ReferenceType) annotationType;
+                                       if (rt.getRetentionPolicy() != null
+                                                       && rt.getRetentionPolicy().equals("SOURCE")) {
+                                               rt
+                                                               .getWorld()
+                                                               .getMessageHandler()
+                                                               .handleMessage(
+                                                                               MessageUtil
+                                                                                               .warn(
+                                                                                                               WeaverMessages
+                                                                                                                               .format(
+                                                                                                                                               WeaverMessages.NO_MATCH_BECAUSE_SOURCE_RETENTION,
+                                                                                                                                               annotationType,
+                                                                                                                                               annotated),
+                                                                                                               getSourceLocation()));
+                                               return FuzzyBoolean.NO;
+                                       }
+                               }
+
+                               // Are we also matching annotation values?
+                               if (annotationValues != null) {
+                                       AnnotationAJ theAnnotation = annotated
+                                                       .getAnnotationOfType(annotationType);
+
+                                       // Check each one
+                                       Set keys = annotationValues.keySet();
+                                       for (Iterator keyIter = keys.iterator(); keyIter.hasNext();) {
+                                               String k = (String) keyIter.next();
+                                               String v = (String) annotationValues.get(k);
+                                               if (theAnnotation.hasNamedValue(k)) {
+                                                       // Simple case, value is 'name=value' and the
+                                                       // annotation specified the same thing
+                                                       if (!theAnnotation.hasNameValuePair(k, v)) {
+                                                               return FuzzyBoolean.NO;
+                                                       }
+                                               } else {
+                                                       // Complex case, look at the default value
+                                                       ResolvedMember[] ms = ((ResolvedType) annotationType)
+                                                                       .getDeclaredMethods();
+                                                       boolean foundMatch = false;
+                                                       for (int i = 0; i < ms.length && !foundMatch; i++) {
+                                                               if (ms[i].isAbstract()
+                                                                               && ms[i].getParameterTypes().length == 0
+                                                                               && ms[i].getName().equals(k)) {
+                                                                       // we might be onto something
+                                                                       String s = ms[i]
+                                                                                       .getAnnotationDefaultValue();
+                                                                       if (s != null && s.equals(v))
+                                                                               foundMatch = true;
+                                                               }
+                                                       }
+                                                       if (!foundMatch)
+                                                               return FuzzyBoolean.NO;
+                                               }
+                                       }
+                               }
+                               return FuzzyBoolean.YES;
+                       } else if (checkSupers) {
+                               ResolvedType toMatchAgainst = ((ResolvedType) annotated)
+                                               .getSuperclass();
+                               while (toMatchAgainst != null) {
+                                       if (toMatchAgainst.hasAnnotation(annotationType)) {
+                                               // Are we also matching annotation values?
+                                               if (annotationValues != null) {
+                                                       AnnotationAJ theAnnotation = toMatchAgainst
+                                                                       .getAnnotationOfType(annotationType);
+
+                                                       // Check each one
+                                                       Set keys = annotationValues.keySet();
+                                                       for (Iterator keyIter = keys.iterator(); keyIter
+                                                                       .hasNext();) {
+                                                               String k = (String) keyIter.next();
+                                                               String v = (String) annotationValues.get(k);
+                                                               if (theAnnotation.hasNamedValue(k)) {
+                                                                       // Simple case, value is 'name=value' and
+                                                                       // the annotation specified the same thing
+                                                                       if (!theAnnotation.hasNameValuePair(k, v)) {
+                                                                               return FuzzyBoolean.NO;
+                                                                       }
+                                                               } else {
+                                                                       // Complex case, look at the default value
+                                                                       ResolvedMember[] ms = ((ResolvedType) annotationType)
+                                                                                       .getDeclaredMethods();
+                                                                       boolean foundMatch = false;
+                                                                       for (int i = 0; i < ms.length
+                                                                                       && !foundMatch; i++) {
+                                                                               if (ms[i].isAbstract()
+                                                                                               && ms[i].getParameterTypes().length == 0
+                                                                                               && ms[i].getName().equals(k)) {
+                                                                                       // we might be onto something
+                                                                                       String s = ms[i]
+                                                                                                       .getAnnotationDefaultValue();
+                                                                                       if (s != null && s.equals(v))
+                                                                                               foundMatch = true;
+                                                                               }
+                                                                       }
+                                                                       if (!foundMatch)
+                                                                               return FuzzyBoolean.NO;
+                                                               }
+                                                       }
+                                               }
+                                               return FuzzyBoolean.YES;
+                                       }
+                                       toMatchAgainst = toMatchAgainst.getSuperclass();
+                               }
+                       }
+               } else {
+                       // check parameter annotations
+                       if (parameterAnnotations == null)
+                               return FuzzyBoolean.NO;
+                       for (int i = 0; i < parameterAnnotations.length; i++) {
+                               if (annotationType.equals(parameterAnnotations[i])) {
+                                       // Are we also matching annotation values?
+                                       if (annotationValues != null) {
+                                               parameterAnnotations[i]
+                                                               .getWorld()
+                                                               .getMessageHandler()
+                                                               .handleMessage(
+                                                                               MessageUtil
+                                                                                               .error("Compiler limitation: annotation value matching for parameter annotations not yet supported"));
+                                               return FuzzyBoolean.NO;
+                                       }
+                                       return FuzzyBoolean.YES;
+                               }
+                       }
+               }
+
+               return FuzzyBoolean.NO;
+       }
+
+       // this version should be called for @this, @target, @args
+       public FuzzyBoolean matchesRuntimeType(AnnotatedElement annotated) {
+               if (getResolvedAnnotationType().hasAnnotation(
+                               UnresolvedType.AT_INHERITED)) {
+                       // a static match is good enough
+                       if (matches(annotated).alwaysTrue()) {
+                               return FuzzyBoolean.YES;
+                       }
+               }
+               // a subtype could match at runtime
+               return FuzzyBoolean.MAYBE;
+       }
+
+       public void resolve(World world) {
+               if (!resolved) {
+                       annotationType = annotationType.resolve(world);
+               }
+               resolved = true;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.aspectj.weaver.patterns.AnnotationTypePattern#resolveBindings(org
+        * .aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings,
+        * boolean)
+        */
+       public AnnotationTypePattern resolveBindings(IScope scope,
+                       Bindings bindings, boolean allowBinding) {
+               if (resolved)
+                       return this;
+               resolved = true;
+               String simpleName = maybeGetSimpleName();
+               if (simpleName != null) {
+                       FormalBinding formalBinding = scope.lookupFormal(simpleName);
+                       if (formalBinding != null) {
+                               if (bindings == null) {
+                                       scope.message(IMessage.ERROR, this,
+                                                       "negation doesn't allow binding");
+                                       return this;
+                               }
+                               if (!allowBinding) {
+                                       scope
+                                                       .message(IMessage.ERROR, this,
+                                                                       "name binding only allowed in @pcds, args, this, and target");
+                                       return this;
+                               }
+                               formalName = simpleName;
+                               bindingPattern = true;
+                               verifyIsAnnotationType(formalBinding.getType().resolve(
+                                               scope.getWorld()), scope);
+                               BindingAnnotationTypePattern binding = new BindingAnnotationTypePattern(
+                                               formalBinding);
+                               binding.copyLocationFrom(this);
+                               bindings.register(binding, scope);
+                               binding.resolveBinding(scope.getWorld());
+                               if (isForParameterAnnotationMatch())
+                                       binding.setForParameterAnnotationMatch();
+
+                               return binding;
+                       }
+               }
+
+               // Non binding case
+               String cleanname = annotationType.getName();
+               annotationType = scope.getWorld().resolve(annotationType, true);
+
+               // We may not have found it if it is in a package, lets look it up...
+               if (ResolvedType.isMissing(annotationType)) {
+                       UnresolvedType type = null;
+                       while (ResolvedType.isMissing(type = scope.lookupType(cleanname,
+                                       this))) {
+                               int lastDot = cleanname.lastIndexOf('.');
+                               if (lastDot == -1)
+                                       break;
+                               cleanname = cleanname.substring(0, lastDot) + "$"
+                                               + cleanname.substring(lastDot + 1);
+                       }
+                       annotationType = scope.getWorld().resolve(type, true);
+               }
+
+               verifyIsAnnotationType((ResolvedType) annotationType, scope);
+               return this;
+       }
+
+       public AnnotationTypePattern parameterizeWith(Map typeVariableMap, World w) {
+               UnresolvedType newAnnotationType = annotationType;
+               if (annotationType.isTypeVariableReference()) {
+                       TypeVariableReference t = (TypeVariableReference) annotationType;
+                       String key = t.getTypeVariable().getName();
+                       if (typeVariableMap.containsKey(key)) {
+                               newAnnotationType = (UnresolvedType) typeVariableMap.get(key);
+                       }
+               } else if (annotationType.isParameterizedType()) {
+                       newAnnotationType = annotationType.parameterize(typeVariableMap);
+               }
+               ExactAnnotationTypePattern ret = new ExactAnnotationTypePattern(
+                               newAnnotationType, annotationValues);
+               ret.formalName = formalName;
+               ret.bindingPattern = bindingPattern;
+               ret.copyLocationFrom(this);
+               if (isForParameterAnnotationMatch())
+                       ret.setForParameterAnnotationMatch();
+               return ret;
+       }
+
+       protected String maybeGetSimpleName() {
+               if (formalName != null)
+                       return formalName;
+               String ret = annotationType.getName();
+               return (ret.indexOf('.') == -1) ? ret : null;
+       }
+
+       protected void verifyIsAnnotationType(ResolvedType type, IScope scope) {
+               if (!type.isAnnotation()) {
+                       IMessage m = MessageUtil.error(WeaverMessages.format(
+                                       WeaverMessages.REFERENCE_TO_NON_ANNOTATION_TYPE, type
+                                                       .getName()), getSourceLocation());
+                       scope.getWorld().getMessageHandler().handleMessage(m);
+                       resolved = false;
+               }
+       }
+
+       private static byte VERSION = 1; // rev if serialisation form changes
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(AnnotationTypePattern.EXACT);
+               s.writeByte(VERSION);
+               s.writeBoolean(bindingPattern);
+               if (bindingPattern) {
+                       s.writeUTF(formalName);
+               } else {
+                       annotationType.write(s);
+               }
+               writeLocation(s);
+               s.writeBoolean(isForParameterAnnotationMatch());
+               if (annotationValues == null) {
+                       s.writeInt(0);
+               } else {
+                       s.writeInt(annotationValues.size());
+                       Set key = annotationValues.keySet();
+                       for (Iterator keys = key.iterator(); keys.hasNext();) {
+                               String k = (String) keys.next();
+                               s.writeUTF(k);
+                               s.writeUTF((String) annotationValues.get(k));
+                       }
+               }
+       }
+
+       public static AnnotationTypePattern read(VersionedDataInputStream s,
+                       ISourceContext context) throws IOException {
+               ExactAnnotationTypePattern ret;
+               byte version = s.readByte();
+               if (version > VERSION) {
+                       throw new BCException(
+                                       "ExactAnnotationTypePattern was written by a newer version of AspectJ");
+               }
+               boolean isBindingPattern = s.readBoolean();
+               if (isBindingPattern) {
+                       ret = new ExactAnnotationTypePattern(s.readUTF());
+               } else {
+                       ret = new ExactAnnotationTypePattern(UnresolvedType.read(s));
+               }
+               ret.readLocation(context, s);
+               if (s.getMajorVersion() >= WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160) {
+                       if (s.readBoolean())
+                               ret.setForParameterAnnotationMatch();
+               }
+               if (s.getMajorVersion() >= WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160M2) {
+                       int annotationValueCount = s.readInt();
+                       if (annotationValueCount > 0) {
+                               Map aValues = new HashMap();
+                               for (int i = 0; i < annotationValueCount; i++) {
+                                       String key = s.readUTF();
+                                       String val = s.readUTF();
+                                       aValues.put(key, val);
+                               }
+                               ret.annotationValues = aValues;
+                       }
+               }
+               return ret;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       public boolean equals(Object obj) {
+               if (!(obj instanceof ExactAnnotationTypePattern))
+                       return false;
+               ExactAnnotationTypePattern other = (ExactAnnotationTypePattern) obj;
+               return (other.annotationType.equals(annotationType))
+                               && isForParameterAnnotationMatch() == other
+                                               .isForParameterAnnotationMatch()
+                               && (annotationValues == null ? other.annotationValues == null
+                                               : annotationValues.equals(other.annotationValues));
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see java.lang.Object#hashCode()
+        */
+       public int hashCode() {
+               return (((annotationType.hashCode()) * 37 + (isForParameterAnnotationMatch() ? 0
+                               : 1)) * 37)
+                               + (annotationValues == null ? 0 : annotationValues.hashCode());
+       }
+
+       public String toString() {
+               if (!resolved && formalName != null)
+                       return formalName;
+               String ret = "@" + annotationType.toString();
+               if (formalName != null)
+                       ret = ret + " " + formalName;
+               return ret;
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this, data);
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactTypePattern.java
new file mode 100644 (file)
index 0000000..859e831
--- /dev/null
@@ -0,0 +1,268 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.TypeVariableReference;
+import org.aspectj.weaver.TypeVariableReferenceType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+public class ExactTypePattern extends TypePattern {
+       protected UnresolvedType type;
+
+       public static final Map primitiveTypesMap;
+       public static final Map boxedPrimitivesMap;
+       private static final Map boxedTypesMap;
+       
+       static {
+               primitiveTypesMap = new HashMap();
+               primitiveTypesMap.put("int",int.class);
+               primitiveTypesMap.put("short",short.class);
+               primitiveTypesMap.put("long",long.class);
+               primitiveTypesMap.put("byte",byte.class);
+               primitiveTypesMap.put("char",char.class);
+               primitiveTypesMap.put("float",float.class);
+               primitiveTypesMap.put("double",double.class);
+
+               boxedPrimitivesMap = new HashMap();
+               boxedPrimitivesMap.put("java.lang.Integer",Integer.class);
+               boxedPrimitivesMap.put("java.lang.Short",Short.class);
+               boxedPrimitivesMap.put("java.lang.Long",Long.class);
+               boxedPrimitivesMap.put("java.lang.Byte",Byte.class);
+               boxedPrimitivesMap.put("java.lang.Character",Character.class);
+               boxedPrimitivesMap.put("java.lang.Float",Float.class);
+               boxedPrimitivesMap.put("java.lang.Double",Double.class);
+
+               
+               boxedTypesMap = new HashMap();
+               boxedTypesMap.put("int",Integer.class);
+               boxedTypesMap.put("short",Short.class);
+               boxedTypesMap.put("long",Long.class);
+               boxedTypesMap.put("byte",Byte.class);
+               boxedTypesMap.put("char",Character.class);
+               boxedTypesMap.put("float",Float.class);
+               boxedTypesMap.put("double",Double.class);
+
+       }
+       
+       public ExactTypePattern(UnresolvedType type, boolean includeSubtypes,boolean isVarArgs) {
+               super(includeSubtypes,isVarArgs);
+               this.type = type;
+       }
+       
+       public boolean isArray() { 
+               return type.isArray();
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
+        */
+       protected boolean couldEverMatchSameTypesAs(TypePattern other) {
+               if (super.couldEverMatchSameTypesAs(other)) return true;
+               // false is necessary but not sufficient
+               UnresolvedType otherType = other.getExactType();
+               if (!ResolvedType.isMissing(otherType)) {
+                       return type.equals(otherType);
+               } 
+               if (other instanceof WildTypePattern) {
+                       WildTypePattern owtp = (WildTypePattern) other;
+                       String yourSimpleNamePrefix = owtp.getNamePatterns()[0].maybeGetSimpleName();
+                       if (yourSimpleNamePrefix != null) {
+                               return (type.getName().startsWith(yourSimpleNamePrefix));
+                       }
+               }
+               return true;
+       }
+       
+       protected boolean matchesExactly(ResolvedType matchType) {
+               boolean typeMatch = this.type.equals(matchType);
+               if (!typeMatch && (matchType.isParameterizedType() || matchType.isGenericType())) {
+                       typeMatch = this.type.equals(matchType.getRawType());
+               }
+               if (!typeMatch && matchType.isTypeVariableReference()) {
+                       typeMatch = matchesTypeVariable((TypeVariableReferenceType)matchType);
+               }
+               annotationPattern.resolve(matchType.getWorld());
+               boolean annMatch = false;
+        if (matchType.temporaryAnnotationTypes!=null) {
+            annMatch = annotationPattern.matches(matchType,matchType.temporaryAnnotationTypes).alwaysTrue();
+        } else {
+            annMatch = annotationPattern.matches(matchType).alwaysTrue();
+        }
+               return (typeMatch && annMatch);
+       }
+       
+       private boolean matchesTypeVariable(TypeVariableReferenceType matchType) {
+           // was this method previously coded to return false *on purpose* ??  pr124808
+               return this.type.equals(((TypeVariableReference)matchType).getTypeVariable().getFirstBound());
+               //return false;
+       }
+       
+       protected boolean matchesExactly(ResolvedType matchType, ResolvedType annotatedType) {
+               boolean typeMatch = this.type.equals(matchType);
+               if (!typeMatch && (matchType.isParameterizedType() || matchType.isGenericType())) {
+                       typeMatch = this.type.equals(matchType.getRawType());
+               }
+               if (!typeMatch && matchType.isTypeVariableReference()) {
+                       typeMatch = matchesTypeVariable((TypeVariableReferenceType)matchType);
+               }
+               annotationPattern.resolve(matchType.getWorld());
+        boolean annMatch = false;
+        if (annotatedType.temporaryAnnotationTypes!=null) {
+            annMatch = annotationPattern.matches(annotatedType,annotatedType.temporaryAnnotationTypes).alwaysTrue();
+        } else {
+            annMatch = annotationPattern.matches(annotatedType).alwaysTrue();
+        }
+               return (typeMatch && annMatch);         
+       }
+       
+       public UnresolvedType getType() { return type; }
+
+       // true if (matchType instanceof this.type)
+       public FuzzyBoolean matchesInstanceof(ResolvedType matchType) {
+               // in our world, Object is assignable from anything
+               annotationPattern.resolve(matchType.getWorld());
+               if (type.equals(ResolvedType.OBJECT)) 
+                   return FuzzyBoolean.YES.and(annotationPattern.matches(matchType));
+               
+               if (type.resolve(matchType.getWorld()).isAssignableFrom(matchType)) {
+                       return FuzzyBoolean.YES.and(annotationPattern.matches(matchType));
+               }
+               
+               // fix for PR 64262 - shouldn't try to coerce primitives
+               if (type.isPrimitiveType()) {
+                       return FuzzyBoolean.NO;
+               } else {
+                   return matchType.isCoerceableFrom(type.resolve(matchType.getWorld())) ? FuzzyBoolean.MAYBE : FuzzyBoolean.NO;
+               }
+       }
+               
+    public boolean equals(Object other) {
+       if (!(other instanceof ExactTypePattern)) return false;
+       if (other instanceof BindingTypePattern) return false;
+       ExactTypePattern o = (ExactTypePattern)other;
+       if (includeSubtypes != o.includeSubtypes) return false;
+       if (isVarArgs != o.isVarArgs) return false;     
+       if (!typeParameters.equals(o.typeParameters)) return false;
+       return (o.type.equals(this.type) && o.annotationPattern.equals(this.annotationPattern));
+    }
+    
+    public int hashCode() {
+        int result = 17;
+        result = 37*result + type.hashCode();
+        result = 37*result + new Boolean(includeSubtypes).hashCode();
+        result = 37*result + new Boolean(isVarArgs).hashCode();
+        result = 37*result + typeParameters.hashCode();
+        result = 37*result + annotationPattern.hashCode();
+        return result;
+    }
+
+    private static final byte EXACT_VERSION = 1; // rev if changed
+       public void write(DataOutputStream out) throws IOException {
+               out.writeByte(TypePattern.EXACT);
+               out.writeByte(EXACT_VERSION);
+               type.write(out);
+               out.writeBoolean(includeSubtypes);
+               out.writeBoolean(isVarArgs);
+               annotationPattern.write(out);
+               typeParameters.write(out);
+               writeLocation(out);
+       }
+       
+       public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
+                       return readTypePattern150(s,context);
+               } else {
+                       return readTypePatternOldStyle(s,context);
+           }
+    }
+       
+       public static TypePattern readTypePattern150(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               byte version = s.readByte();
+               if (version > EXACT_VERSION) throw new BCException("ExactTypePattern was written by a more recent version of AspectJ");
+               TypePattern ret = new ExactTypePattern(UnresolvedType.read(s), s.readBoolean(), s.readBoolean());
+               ret.setAnnotationTypePattern(AnnotationTypePattern.read(s,context));
+               ret.setTypeParameters(TypePatternList.read(s,context));
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public static TypePattern readTypePatternOldStyle(DataInputStream s, ISourceContext context) throws IOException {
+               TypePattern ret = new ExactTypePattern(UnresolvedType.read(s), s.readBoolean(),false);
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public String toString() {
+               StringBuffer buff = new StringBuffer();
+               if (annotationPattern != AnnotationTypePattern.ANY) {
+                       buff.append('(');
+                       buff.append(annotationPattern.toString());
+                       buff.append(' ');
+               }
+               String typeString = type.toString();
+               if (isVarArgs) typeString = typeString.substring(0,typeString.lastIndexOf('['));
+               buff.append(typeString);
+       if (includeSubtypes) buff.append('+');
+       if (isVarArgs) buff.append("...");
+               if (annotationPattern != AnnotationTypePattern.ANY) {
+                       buff.append(')');
+               }
+               return buff.toString();
+    }
+       public TypePattern resolveBindings(IScope scope, Bindings bindings, 
+                                                               boolean allowBinding, boolean requireExactType)
+    { 
+               throw new BCException("trying to re-resolve");
+               
+       }
+       
+       /**
+        * return a version of this type pattern with all type variables references replaced
+        * by the corresponding entry in the map.
+        */
+       public TypePattern parameterizeWith(Map typeVariableMap,World w) {
+               UnresolvedType newType = type;
+               if (type.isTypeVariableReference()) {
+                       TypeVariableReference t = (TypeVariableReference) type;
+                       String key = t.getTypeVariable().getName();
+                       if (typeVariableMap.containsKey(key)) {
+                               newType = (UnresolvedType) typeVariableMap.get(key);
+                       }
+               } else if (type.isParameterizedType()) {
+                       newType = w.resolve(type).parameterize(typeVariableMap);
+               }
+               ExactTypePattern ret = new ExactTypePattern(newType,includeSubtypes,isVarArgs);
+               ret.annotationPattern = annotationPattern.parameterizeWith(typeVariableMap,w);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExposedState.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExposedState.java
new file mode 100644 (file)
index 0000000..fb34da9
--- /dev/null
@@ -0,0 +1,98 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.util.Arrays;
+
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.ast.Expr;
+import org.aspectj.weaver.ast.Var;
+
+public class ExposedState {
+       public Var[] vars;
+       private boolean[] erroneousVars;
+       private Expr aspectInstance;
+       private UnresolvedType[] expectedVarTypes; // enables us to check that binding is occurring with the *right* types
+
+       public ExposedState(int size) {
+               super();
+               vars = new Var[size];
+               erroneousVars = new boolean[size];
+       }
+
+       public ExposedState(Member signature) {
+               // XXX there maybe something about target for non-static sigs
+               this(signature.getParameterTypes().length);
+               expectedVarTypes = new UnresolvedType[signature.getParameterTypes().length];
+               if (expectedVarTypes.length>0) {
+                       for (int i = 0; i < signature.getParameterTypes().length; i++) {
+                               expectedVarTypes[i] = signature.getParameterTypes()[i];
+                       }
+               }
+               
+       }
+       
+       public boolean isFullySetUp() {
+               for (int i = 0; i < vars.length; i++) {
+                       if (vars[i]==null) return false;
+               }
+               return true;
+       }
+
+       public void set(int i, Var var) {
+               // check the type is OK if we can... these are the same rules as in matchesInstanceOf() processing
+               if (expectedVarTypes!=null) {
+                       ResolvedType expected = expectedVarTypes[i].resolve(var.getType().getWorld());
+                       if (!expected.equals(ResolvedType.OBJECT)) {
+                               if (!expected.isAssignableFrom(var.getType())) {
+                                       if (!var.getType().isCoerceableFrom(expected)) {
+//                                             throw new BCException("Expected type "+expectedVarTypes[i]+" in slot "+i+" but attempt to put "+var.getType()+" into it");
+                                               return;
+                                       }
+                               }
+                       }
+               }
+               vars[i] = var;
+       }
+    public Var get(int i) {
+        return vars[i];
+    }
+    public int size() {
+        return vars.length;
+    }
+
+    public Expr getAspectInstance() {
+        return aspectInstance;
+    }
+
+    public void setAspectInstance(Expr aspectInstance) {
+        this.aspectInstance = aspectInstance;
+    }
+
+       public String toString() {
+               return "ExposedState(#Vars="+vars.length+",Vars=" + Arrays.asList(vars) + ",AspectInstance=" + aspectInstance + ")";
+       }
+
+       // Set to true if we have reported an error message against it,
+       // prevents us blowing up in later code gen.
+       public void setErroneousVar(int formalIndex) {
+               erroneousVars[formalIndex]=true;
+       }
+       
+       public boolean isErroneousVar(int formalIndex) {
+               return erroneousVars[formalIndex];
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/FastMatchInfo.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/FastMatchInfo.java
new file mode 100644 (file)
index 0000000..132b865
--- /dev/null
@@ -0,0 +1,47 @@
+/* *******************************************************************
+ * Copyright (c) 2004 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Jim Hugunin     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.Shadow.Kind;
+
+
+public class FastMatchInfo {
+       private Kind kind;
+       private ResolvedType type;
+
+       public FastMatchInfo(ResolvedType type, Shadow.Kind kind) {
+               this.type = type;
+               this.kind = kind;
+       }
+       
+       /**
+        * kind can be null to indicate that all kinds should be considered.
+        * This is usually done as a first pass
+        * @return
+        */
+       public Kind getKind() {
+               return kind;
+       }
+
+       public ResolvedType getType() {
+               return type;
+       }
+       
+       public String toString() {
+               return "FastMatchInfo [type="+type.getName()+"] ["+(kind==null?"AllKinds":"Kind="+kind)+"]";
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/FormalBinding.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/FormalBinding.java
new file mode 100644 (file)
index 0000000..73693f0
--- /dev/null
@@ -0,0 +1,82 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.IHasPosition;
+import org.aspectj.weaver.UnresolvedType;
+
+public class FormalBinding implements IHasPosition {
+       private final UnresolvedType type;
+       private final String name;
+       private final int index;
+       private final int start, end;
+
+       public FormalBinding(UnresolvedType type, String name, int index, int start, int end) {
+               this.type = type;
+               this.name = name;
+               this.index = index;
+               this.start = start;
+               this.end = end;
+       }
+
+       public FormalBinding(UnresolvedType type, int index) {
+               this(type, "unknown", index, 0, 0);
+       }
+
+       public FormalBinding(UnresolvedType type, String name, int index) {
+               this(type, name, index, 0, 0);
+       }
+
+       // ----
+
+       public String toString() {
+               return type.toString() + ":" + index;
+       }
+
+       public int getEnd() {
+               return end;
+       }
+
+       public int getStart() {
+               return start;
+       }
+
+       public int getIndex() {
+               return index;
+       }
+
+       public String getName() {
+               return name;
+       }
+
+       public UnresolvedType getType() {
+               return type;
+       }
+
+       // ----
+
+       public static final FormalBinding[] NONE = new FormalBinding[0];
+
+       /**
+        * A marker class for bindings for which we want to ignore unbound issue and consider them as implicit binding - f.e. to handle
+        * JoinPoint in @AJ advices
+        * 
+        * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+        */
+       public static class ImplicitFormalBinding extends FormalBinding {
+               public ImplicitFormalBinding(UnresolvedType type, String name, int index) {
+                       super(type, name, index);
+               }
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HandlerPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HandlerPointcut.java
new file mode 100644 (file)
index 0000000..b26dc9b
--- /dev/null
@@ -0,0 +1,139 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+
+/**
+ * This is a kind of KindedPointcut.  This belongs either in 
+ * a hierarchy with it or in a new place to share code
+ * with other potential future statement-level pointcuts like
+ * synchronized and throws
+ */
+public class HandlerPointcut extends Pointcut {
+       TypePattern exceptionType;
+
+       private static final int MATCH_KINDS = Shadow.ExceptionHandler.bit;
+       
+       public HandlerPointcut(TypePattern exceptionType) {
+               this.exceptionType = exceptionType;
+               this.pointcutKind = HANDLER;
+       }
+
+       public int couldMatchKinds() {
+               return MATCH_KINDS;
+       }
+       
+    public FuzzyBoolean fastMatch(FastMatchInfo type) {
+       //??? should be able to do better by finding all referenced types in type
+               return FuzzyBoolean.MAYBE;
+       }
+       
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               if (shadow.getKind() != Shadow.ExceptionHandler) return FuzzyBoolean.NO;
+               
+               exceptionType.resolve(shadow.getIWorld());
+               
+               // we know we have exactly one parameter since we're checking an exception handler
+               return exceptionType.matches(
+                               shadow.getSignature().getParameterTypes()[0].resolve(shadow.getIWorld()), 
+                               TypePattern.STATIC);
+       }
+       
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               HandlerPointcut ret = new HandlerPointcut(exceptionType.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public boolean equals(Object other) {
+               if (!(other instanceof HandlerPointcut)) return false;
+               HandlerPointcut o = (HandlerPointcut)other;
+               return o.exceptionType.equals(this.exceptionType);      }
+    
+    public int hashCode() {
+        int result = 17;
+        result = 37*result + exceptionType.hashCode();
+        return result;
+    }
+       
+       public String toString() {
+               StringBuffer buf = new StringBuffer();
+               buf.append("handler(");
+               buf.append(exceptionType.toString());
+               buf.append(")");
+               return buf.toString();
+       }
+       
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.HANDLER);
+               exceptionType.write(s);
+               writeLocation(s);
+       }
+       
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               HandlerPointcut ret = new HandlerPointcut(TypePattern.read(s, context));
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       // XXX note: there is no namebinding in any kinded pointcut.
+       // still might want to do something for better error messages
+       // We want to do something here to make sure we don't sidestep the parameter
+       // list in capturing type identifiers.
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               exceptionType = exceptionType.resolveBindings(scope, bindings, false, false);
+               boolean invalidParameterization = false;
+               if (exceptionType.getTypeParameters().size() > 0) invalidParameterization = true ;
+               UnresolvedType exactType = exceptionType.getExactType();
+               if (exactType != null && exactType.isParameterizedType()) invalidParameterization = true;
+               if (invalidParameterization) {
+                       // no parameterized or generic types for handler
+                       scope.message(
+                                       MessageUtil.error(WeaverMessages.format(WeaverMessages.HANDLER_PCD_DOESNT_SUPPORT_PARAMETERS),
+                                                                       getSourceLocation()));
+               }
+               //XXX add error if exact binding and not an exception
+       }
+       
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
+       }
+       
+       public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               Pointcut ret = new HandlerPointcut(exceptionType);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasMemberTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasMemberTypePattern.java
new file mode 100644 (file)
index 0000000..263b788
--- /dev/null
@@ -0,0 +1,160 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ConcreteTypeMunger;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+
+/**
+ * @author colyer
+ * Matches types that have a certain method / constructor / field
+ * Currently only allowed within declare parents and declare @type
+ */
+public class HasMemberTypePattern extends TypePattern {
+
+       private SignaturePattern signaturePattern;
+       
+       public HasMemberTypePattern(SignaturePattern aSignaturePattern) {
+               super(false,false);
+               this.signaturePattern = aSignaturePattern;
+       }
+
+       protected boolean matchesExactly(ResolvedType type) {
+               if (signaturePattern.getKind() == Member.FIELD) {
+                       return hasField(type);
+               } else {
+                       return hasMethod(type);
+               }
+       }
+       
+       private final static String declareAtPrefix = "ajc$declare_at";
+
+       private boolean hasField(ResolvedType type) {
+               // TODO what about ITDs
+               World world = type.getWorld();
+               for (Iterator iter = type.getFields(); iter.hasNext();) {
+                       Member field = (Member) iter.next();
+                       if (field.getName().startsWith(declareAtPrefix)) continue;
+                       if (signaturePattern.matches(field, type.getWorld(), false)) {
+                               if (field.getDeclaringType().resolve(world) != type) {
+                                       if (Modifier.isPrivate(field.getModifiers())) continue;
+                               }
+                               return true;
+                       }
+               }
+               return false;
+       }
+       
+       private boolean hasMethod(ResolvedType type) {
+               // TODO what about ITDs
+               World world = type.getWorld();
+               for (Iterator iter = type.getMethods(); iter.hasNext();) {
+                       Member method = (Member) iter.next();
+                       if (method.getName().startsWith(declareAtPrefix)) continue;
+                       if (signaturePattern.matches(method, type.getWorld(), false)) {
+                               if (method.getDeclaringType().resolve(world) != type) {
+                                       if (Modifier.isPrivate(method.getModifiers())) continue;
+                               }
+                               return true;
+                       }
+               }
+               // try itds before we give up
+               List mungers = type.getInterTypeMungersIncludingSupers();
+               for (Iterator iter = mungers.iterator(); iter.hasNext();) {
+                       ConcreteTypeMunger munger = (ConcreteTypeMunger) iter.next();
+                       Member member = munger.getSignature();
+                       if (signaturePattern.matches(member, type.getWorld(), false)) {
+                               if (!Modifier.isPublic(member.getModifiers())) continue;
+                               return true;
+                       }
+               }
+               return false;
+       }
+       
+       protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
+               return matchesExactly(type);
+       }
+
+       public FuzzyBoolean matchesInstanceof(ResolvedType type) {
+               throw new UnsupportedOperationException("hasmethod/field do not support instanceof matching");
+       }
+
+       public TypePattern parameterizeWith(Map typeVariableMap,World w) {
+               HasMemberTypePattern ret = new HasMemberTypePattern(signaturePattern.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       public TypePattern resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
+               // check that hasmember type patterns are allowed!
+               if (!scope.getWorld().isHasMemberSupportEnabled()) {
+                       String msg = WeaverMessages.format(WeaverMessages.HAS_MEMBER_NOT_ENABLED,this.toString());
+                       scope.message(IMessage.ERROR, this, msg);
+               }
+               signaturePattern.resolveBindings(scope,bindings);
+               return this;
+       }
+
+       public boolean equals(Object obj) {
+               if (!(obj instanceof HasMemberTypePattern)) return false;
+               if (this == obj) return true;
+               return signaturePattern.equals(((HasMemberTypePattern)obj).signaturePattern);
+       }
+       
+       public int hashCode() {
+               return signaturePattern.hashCode();
+       }
+       
+       public String toString() {
+               StringBuffer buff = new StringBuffer();
+               if (signaturePattern.getKind() == Member.FIELD) {
+                       buff.append("hasfield(");
+               } else {
+                       buff.append("hasmethod(");
+               }
+               buff.append(signaturePattern.toString());
+               buff.append(")");
+               return buff.toString();
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(TypePattern.HAS_MEMBER);
+               signaturePattern.write(s);
+               writeLocation(s);
+       }
+
+       public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               SignaturePattern sp = SignaturePattern.read(s, context);
+               HasMemberTypePattern ret = new HasMemberTypePattern(sp);
+               ret.readLocation(context,s);
+               return ret;
+       }
+       
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this, data);
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasMemberTypePatternFinder.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasMemberTypePatternFinder.java
new file mode 100644 (file)
index 0000000..5fb5950
--- /dev/null
@@ -0,0 +1,33 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+/**
+ * @author colyer
+ * usage : new HasMemberTypePatternFinder(pattern).hasMemberTypePattern()
+ */
+public class HasMemberTypePatternFinder extends AbstractPatternNodeVisitor {
+       
+       private boolean hasMemberTypePattern = false;
+       
+       public HasMemberTypePatternFinder(TypePattern aPattern) {
+               aPattern.traverse(this, null);
+       }
+       
+       public Object visit(HasMemberTypePattern node, Object data) {
+               hasMemberTypePattern = true;
+               return null;
+       }
+       
+       public boolean hasMemberTypePattern() { return hasMemberTypePattern; }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor.java
new file mode 100644 (file)
index 0000000..0b2b9b5
--- /dev/null
@@ -0,0 +1,50 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.UnresolvedType;
+
+/**
+ * @author colyer
+ *
+ */
+public class HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor
+               extends AbstractPatternNodeVisitor {
+
+       boolean ohYesItHas = false;
+       
+       /**
+        * Is the Exact type parameterized?
+        * Generic is ok as that just means we resolved a simple type pattern to a generic type
+        */
+       public Object visit(ExactTypePattern node, Object data) {
+               UnresolvedType theExactType = node.getExactType();
+               if (theExactType.isParameterizedType()) ohYesItHas = true;
+               //if (theExactType.isGenericType()) ohYesItHas = true;
+               return data;
+       }
+
+       /**
+        * Any type bounds are bad.
+        * Type parameters are right out.
+        */
+       public Object visit(WildTypePattern node, Object data) {
+               if (node.getUpperBound() != null) ohYesItHas = true;
+               if (node.getLowerBound() != null) ohYesItHas = true;
+               if (node.getTypeParameters().size() != 0) ohYesItHas = true;
+               return data;
+       }
+       
+       public boolean wellHasItThen/*?*/() {
+               return ohYesItHas;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/IScope.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/IScope.java
new file mode 100644 (file)
index 0000000..e96cb25
--- /dev/null
@@ -0,0 +1,51 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.weaver.IHasPosition;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.World;
+
+public interface IScope {
+
+    /** returns the type corresponding to the name in this scope
+     *  returns ResolvedType.MISSING if no such type exists and reports a problem
+     */
+    UnresolvedType lookupType(String name, IHasPosition location);
+
+       World getWorld();
+
+       ResolvedType getEnclosingType();
+
+    // these next three are used to create {@link BindingTypePattern} objects.
+       IMessageHandler getMessageHandler();
+    /** returns the formal associated with the name, or null if no such formal exists */
+    FormalBinding lookupFormal(String name);
+    /** returns the formal with the index.  Throws ArrayOutOfBounds exception if out of bounds */
+       FormalBinding getFormal(int i);
+       
+       int getFormalCount();
+
+       String[] getImportedPrefixes();
+       String[] getImportedNames();
+       
+       void message(IMessage.Kind kind, IHasPosition location, String message);
+       void message(IMessage.Kind kind, IHasPosition location1, IHasPosition location2, String message);
+       void message(IMessage  aMessage);
+       
+       //ISourceLocation makeSourceLocation(ILocation location);
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/IToken.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/IToken.java
new file mode 100644 (file)
index 0000000..aa925fd
--- /dev/null
@@ -0,0 +1,53 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.IHasPosition;
+
+public interface IToken extends IHasPosition {
+       public static final IToken EOF = BasicToken.makeOperator("<eof>", 0, 0);
+       
+       /**
+        * Returns the string value of this token.
+        * 
+        * If isIdentifier is false, then this string must be intern'd
+        * so that == matching can be used.
+        * 
+        * If isIdentifier is true, interning is not required.
+        */
+    public String getString();
+    
+    /**
+     * Whether this should be treated as a token or a generic identifier
+     */
+    public boolean isIdentifier();
+    
+    /**
+     * Whether this should be treated as a literal value
+     * 
+     * Kinds == "string", ???
+     * 
+     * returns null if this isn't a literal
+     */
+    public String getLiteralKind();
+    
+    
+    /**
+     * If this token represents a pre-parsed Pointcut, then return it;
+     * otherwise returns null.
+     * 
+     * Needed for the implementation of 'if'
+     */
+    public Pointcut maybeGetParsedPointcut();
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ITokenSource.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ITokenSource.java
new file mode 100644 (file)
index 0000000..ea777a4
--- /dev/null
@@ -0,0 +1,26 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.ISourceContext;
+
+
+public interface ITokenSource {
+       public IToken next();
+       public IToken peek();
+       public IToken peek(int offset);
+       public int getIndex();
+       public void setIndex(int newIndex);
+       public ISourceContext getSourceContext();
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/IVerificationRequired.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/IVerificationRequired.java
new file mode 100644 (file)
index 0000000..f1ce19e
--- /dev/null
@@ -0,0 +1,22 @@
+/* *******************************************************************
+ * Copyright (c) 2006 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement IBM     initial implementation 
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+
+/**
+ * Implementors provide a 'verify()' method that is invoked at the end of type
+ * binding completion.
+ * @see WildTypePattern.VerifyBoundsForTypePattern
+ */
+public interface IVerificationRequired {
+       public void verify();
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/IfPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/IfPointcut.java
new file mode 100644 (file)
index 0000000..eaa2e1f
--- /dev/null
@@ -0,0 +1,506 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     PARC                 initial implementation
+ *     Alexandre Vasseur    if() implementation for @AJ style
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.Advice;
+import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedMemberImpl;
+import org.aspectj.weaver.ResolvedPointcutDefinition;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.ShadowMunger;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Expr;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.ast.Var;
+
+public class IfPointcut extends Pointcut {
+       public ResolvedMember testMethod;
+       public int extraParameterFlags;
+
+       /**
+        * A token source dump that looks like a pointcut (but is NOT parseable at all - just here to help debugging etc)
+        */
+       private final String enclosingPointcutHint;
+
+       public Pointcut residueSource;
+       int baseArgsCount;
+
+       // XXX some way to compute args
+
+       public IfPointcut(ResolvedMember testMethod, int extraParameterFlags) {
+               this.testMethod = testMethod;
+               this.extraParameterFlags = extraParameterFlags;
+               this.pointcutKind = IF;
+               this.enclosingPointcutHint = null;
+       }
+
+       /**
+        * No-arg constructor for @AJ style, where the if() body is actually the @Pointcut annotated method
+        */
+       public IfPointcut(String enclosingPointcutHint) {
+               this.pointcutKind = IF;
+               this.enclosingPointcutHint = enclosingPointcutHint;
+               this.testMethod = null;// resolved during concretize
+               this.extraParameterFlags = -1;// allows to keep track of the @Aj style
+       }
+
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;
+       }
+
+       public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               return FuzzyBoolean.MAYBE;
+       }
+
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               // ??? this is not maximally efficient
+               return FuzzyBoolean.MAYBE;
+       }
+
+       public boolean alwaysFalse() {
+               return false;
+       }
+
+       public boolean alwaysTrue() {
+               return false;
+       }
+
+       // enh 76055
+       public Pointcut getResidueSource() {
+               return residueSource;
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.IF);
+               s.writeBoolean(testMethod != null); // do we have a test method?
+               if (testMethod != null)
+                       testMethod.write(s);
+               s.writeByte(extraParameterFlags);
+               writeLocation(s);
+       }
+
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               boolean hasTestMethod = s.readBoolean();
+               ResolvedMember resolvedTestMethod = null;
+               if (hasTestMethod) { // should always have a test method unless @AJ style
+                       resolvedTestMethod = ResolvedMemberImpl.readResolvedMember(s, context);
+               }
+               IfPointcut ret = new IfPointcut(resolvedTestMethod, s.readByte());
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               // ??? all we need is good error messages in here in cflow contexts
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof IfPointcut))
+                       return false;
+               IfPointcut o = (IfPointcut) other;
+               if (o.testMethod == null)
+                       return (this.testMethod == null);
+               return o.testMethod.equals(this.testMethod);
+       }
+
+       public int hashCode() {
+               int result = 17;
+               result = 37 * result + testMethod.hashCode();
+               return result;
+       }
+
+       public String toString() {
+               if (extraParameterFlags < 0) {
+                       // @AJ style
+                       return "if()";
+               } else {
+                       return "if(" + testMethod + ")";// FIXME AV - bad, this makes it unparsable. Perhaps we can use if() for code style
+                       // behind the scene!
+               }
+       }
+
+       // ??? The implementation of name binding and type checking in if PCDs is very convoluted
+       // There has to be a better way...
+       private boolean findingResidue = false;
+
+       // Similar to lastMatchedShadowId - but only for if PCDs.
+       private int ifLastMatchedShadowId;
+       private Test ifLastMatchedShadowResidue;
+
+       /**
+        * At each shadow that matched, the residue can be different.
+        */
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               if (findingResidue)
+                       return Literal.TRUE;
+               findingResidue = true;
+               try {
+
+                       // Have we already been asked this question?
+                       if (shadow.shadowId == ifLastMatchedShadowId)
+                               return ifLastMatchedShadowResidue;
+
+                       Test ret = Literal.TRUE;
+                       List args = new ArrayList();
+
+                       // code style
+                       if (extraParameterFlags >= 0) {
+                               // If there are no args to sort out, don't bother with the recursive call
+                               if (baseArgsCount > 0) {
+                                       ExposedState myState = new ExposedState(baseArgsCount);
+                                       // ??? we throw out the test that comes from this walk. All we want here
+                                       // is bindings for the arguments
+                                       residueSource.findResidue(shadow, myState);
+
+                                       UnresolvedType[] pTypes = (testMethod == null ? null : testMethod.getParameterTypes());
+                                       if (pTypes != null && baseArgsCount > pTypes.length) { // pr155347
+                                               throw new BCException("Unexpected problem with testMethod " + testMethod + ": expecting " + baseArgsCount
+                                                               + " arguments");
+                                       }
+                                       // pr118149
+                                       // It is possible for vars in myState (which would normally be set
+                                       // in the call to residueSource.findResidue) to not be set (be null)
+                                       // in an Or pointcut with if expressions in both branches, and where
+                                       // one branch is known statically to not match. In this situation we
+                                       // simply return Test.
+                                       for (int i = 0; i < baseArgsCount; i++) {
+                                               Var v = myState.get(i);
+                                               if (v == null)
+                                                       continue; // pr118149
+                                               args.add(v);
+                                               ret = Test.makeAnd(ret, Test.makeInstanceof(v, pTypes[i].resolve(shadow.getIWorld())));
+                                       }
+                               }
+
+                               // handle thisJoinPoint parameters
+                               if ((extraParameterFlags & Advice.ThisJoinPoint) != 0) {
+                                       args.add(shadow.getThisJoinPointVar());
+                               }
+
+                               if ((extraParameterFlags & Advice.ThisJoinPointStaticPart) != 0) {
+                                       args.add(shadow.getThisJoinPointStaticPartVar());
+                               }
+
+                               if ((extraParameterFlags & Advice.ThisEnclosingJoinPointStaticPart) != 0) {
+                                       args.add(shadow.getThisEnclosingJoinPointStaticPartVar());
+                               }
+                       } else {
+                               // @style is slightly different
+                               int currentStateIndex = 0;
+                               // FIXME AV - "args(jp)" test(jp, thejp) will fail here
+                               for (int i = 0; i < testMethod.getParameterTypes().length; i++) {
+                                       String argSignature = testMethod.getParameterTypes()[i].getSignature();
+                                       if (AjcMemberMaker.TYPEX_JOINPOINT.getSignature().equals(argSignature)) {
+                                               args.add(shadow.getThisJoinPointVar());
+                                       } else if (AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(argSignature)) {
+                                               args.add(shadow.getThisJoinPointVar());
+                                       } else if (AjcMemberMaker.TYPEX_STATICJOINPOINT.getSignature().equals(argSignature)) {
+                                               args.add(shadow.getThisJoinPointStaticPartVar());
+                                       } else if (AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(argSignature)) {
+                                               args.add(shadow.getThisEnclosingJoinPointStaticPartVar());
+                                       } else {
+                                               // we don't use i as JoinPoint.* can be anywhere in the signature in @style
+                                               Var v = state.get(currentStateIndex++);
+                                               args.add(v);
+                                               ret = Test.makeAnd(ret, Test.makeInstanceof(v, testMethod.getParameterTypes()[i]
+                                                               .resolve(shadow.getIWorld())));
+                                       }
+                               }
+                       }
+
+                       ret = Test.makeAnd(ret, Test.makeCall(testMethod, (Expr[]) args.toArray(new Expr[args.size()])));
+
+                       // Remember...
+                       ifLastMatchedShadowId = shadow.shadowId;
+                       ifLastMatchedShadowResidue = ret;
+                       return ret;
+               } finally {
+                       findingResidue = false;
+               }
+       }
+
+       // amc - the only reason this override seems to be here is to stop the copy, but
+       // that can be prevented by overriding shouldCopyLocationForConcretization,
+       // allowing me to make the method final in Pointcut.
+       // public Pointcut concretize(ResolvedType inAspect, IntMap bindings) {
+       // return this.concretize1(inAspect, bindings);
+       // }
+
+       protected boolean shouldCopyLocationForConcretize() {
+               return false;
+       }
+
+       private IfPointcut partiallyConcretized = null;
+
+       public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               // System.err.println("concretize: " + this + " already: " + partiallyConcretized);
+
+               if (isDeclare(bindings.getEnclosingAdvice())) {
+                       // Enforce rule about which designators are supported in declare
+                       inAspect.getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.IF_IN_DECLARE),
+                                       bindings.getEnclosingAdvice().getSourceLocation(), null);
+                       return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+               }
+
+               if (partiallyConcretized != null) {
+                       return partiallyConcretized;
+               }
+
+               final IfPointcut ret;
+               if (extraParameterFlags < 0 && testMethod == null) {
+                       // @AJ style, we need to find the testMethod in the aspect defining the "if()" enclosing pointcut
+                       ResolvedPointcutDefinition def = bindings.peekEnclosingDefinition();
+                       if (def != null) {
+                               ResolvedType aspect = inAspect.getWorld().resolve(def.getDeclaringType());
+                               for (Iterator memberIter = aspect.getMethods(); memberIter.hasNext();) {
+                                       ResolvedMember method = (ResolvedMember) memberIter.next();
+                                       if (def.getName().equals(method.getName())
+                                                       && def.getParameterTypes().length == method.getParameterTypes().length) {
+                                               boolean sameSig = true;
+                                               for (int j = 0; j < method.getParameterTypes().length; j++) {
+                                                       UnresolvedType argJ = method.getParameterTypes()[j];
+                                                       if (!argJ.equals(def.getParameterTypes()[j])) {
+                                                               sameSig = false;
+                                                               break;
+                                                       }
+                                               }
+                                               if (sameSig) {
+                                                       testMethod = method;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               if (testMethod == null) {
+                                       inAspect.getWorld().showMessage(IMessage.ERROR,
+                                                       "Cannot find if() body from '" + def.toString() + "' for '" + enclosingPointcutHint + "'",
+                                                       this.getSourceLocation(), null);
+                                       return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+                               }
+                       } else {
+                               testMethod = inAspect.getWorld().resolve(bindings.getAdviceSignature());
+                       }
+                       ret = new IfPointcut(enclosingPointcutHint);
+                       ret.testMethod = testMethod;
+               } else {
+                       ret = new IfPointcut(testMethod, extraParameterFlags);
+               }
+               ret.copyLocationFrom(this);
+               partiallyConcretized = ret;
+
+               // It is possible to directly code your pointcut expression in a per clause
+               // rather than defining a pointcut declaration and referencing it in your
+               // per clause. If you do this, we have problems (bug #62458). For now,
+               // let's police that you are trying to code a pointcut in a per clause and
+               // put out a compiler error.
+               if (bindings.directlyInAdvice() && bindings.getEnclosingAdvice() == null) {
+                       // Assumption: if() is in a per clause if we say we are directly in advice
+                       // but we have no enclosing advice.
+                       inAspect.getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.IF_IN_PERCLAUSE),
+                                       this.getSourceLocation(), null);
+                       return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+               }
+
+               if (bindings.directlyInAdvice()) {
+                       ShadowMunger advice = bindings.getEnclosingAdvice();
+                       if (advice instanceof Advice) {
+                               ret.baseArgsCount = ((Advice) advice).getBaseParameterCount();
+                       } else {
+                               ret.baseArgsCount = 0;
+                       }
+                       ret.residueSource = advice.getPointcut().concretize(inAspect, inAspect, ret.baseArgsCount, advice);
+               } else {
+                       ResolvedPointcutDefinition def = bindings.peekEnclosingDefinition();
+                       if (def == CflowPointcut.CFLOW_MARKER) {
+                               inAspect.getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.IF_LEXICALLY_IN_CFLOW),
+                                               getSourceLocation(), null);
+                               return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+                       }
+                       ret.baseArgsCount = def.getParameterTypes().length;
+
+                       // for @style, we have implicit binding for JoinPoint.* things
+                       // FIXME AV - will lead to failure for "args(jp)" test(jp, thejp) / see args() implementation
+                       if (ret.extraParameterFlags < 0) {
+                               ret.baseArgsCount = 0;
+                               for (int i = 0; i < testMethod.getParameterTypes().length; i++) {
+                                       String argSignature = testMethod.getParameterTypes()[i].getSignature();
+                                       if (AjcMemberMaker.TYPEX_JOINPOINT.getSignature().equals(argSignature)
+                                                       || AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(argSignature)
+                                                       || AjcMemberMaker.TYPEX_STATICJOINPOINT.getSignature().equals(argSignature)
+                                                       || AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(argSignature)) {
+
+                                       } else {
+                                               ret.baseArgsCount++;
+                                       }
+                               }
+                       }
+
+                       IntMap newBindings = IntMap.idMap(ret.baseArgsCount);
+                       newBindings.copyContext(bindings);
+                       ret.residueSource = def.getPointcut().concretize(inAspect, declaringType, newBindings);
+               }
+
+               return ret;
+       }
+
+       // we can't touch "if" methods
+       public Pointcut parameterizeWith(Map typeVariableMap, World w) {
+               return this;
+       }
+
+       // public static Pointcut MatchesNothing = new MatchesNothingPointcut();
+       // ??? there could possibly be some good optimizations to be done at this point
+       public static IfPointcut makeIfFalsePointcut(State state) {
+               IfPointcut ret = new IfFalsePointcut();
+               ret.state = state;
+               return ret;
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this, data);
+       }
+
+       public static class IfFalsePointcut extends IfPointcut {
+
+               public IfFalsePointcut() {
+                       super(null, 0);
+                       this.pointcutKind = Pointcut.IF_FALSE;
+               }
+
+               public int couldMatchKinds() {
+                       return Shadow.NO_SHADOW_KINDS_BITS;
+               }
+
+               public boolean alwaysFalse() {
+                       return true;
+               }
+
+               protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+                       return Literal.FALSE; // can only get here if an earlier error occurred
+               }
+
+               public FuzzyBoolean fastMatch(FastMatchInfo type) {
+                       return FuzzyBoolean.NO;
+               }
+
+               protected FuzzyBoolean matchInternal(Shadow shadow) {
+                       return FuzzyBoolean.NO;
+               }
+
+               public void resolveBindings(IScope scope, Bindings bindings) {
+               }
+
+               public void postRead(ResolvedType enclosingType) {
+               }
+
+               public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+                       if (isDeclare(bindings.getEnclosingAdvice())) {
+                               // Enforce rule about which designators are supported in declare
+                               inAspect.getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.IF_IN_DECLARE),
+                                               bindings.getEnclosingAdvice().getSourceLocation(), null);
+                               return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+                       }
+                       return makeIfFalsePointcut(state);
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+                       s.writeByte(Pointcut.IF_FALSE);
+               }
+
+               public int hashCode() {
+                       int result = 17;
+                       return result;
+               }
+
+               public String toString() {
+                       return "if(false)";
+               }
+       }
+
+       public static IfPointcut makeIfTruePointcut(State state) {
+               IfPointcut ret = new IfTruePointcut();
+               ret.state = state;
+               return ret;
+       }
+
+       public static class IfTruePointcut extends IfPointcut {
+
+               public IfTruePointcut() {
+                       super(null, 0);
+                       this.pointcutKind = Pointcut.IF_TRUE;
+               }
+
+               public boolean alwaysTrue() {
+                       return true;
+               }
+
+               protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+                       return Literal.TRUE; // can only get here if an earlier error occurred
+               }
+
+               public FuzzyBoolean fastMatch(FastMatchInfo type) {
+                       return FuzzyBoolean.YES;
+               }
+
+               protected FuzzyBoolean matchInternal(Shadow shadow) {
+                       return FuzzyBoolean.YES;
+               }
+
+               public void resolveBindings(IScope scope, Bindings bindings) {
+               }
+
+               public void postRead(ResolvedType enclosingType) {
+               }
+
+               public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+                       if (isDeclare(bindings.getEnclosingAdvice())) {
+                               // Enforce rule about which designators are supported in declare
+                               inAspect.getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.IF_IN_DECLARE),
+                                               bindings.getEnclosingAdvice().getSourceLocation(), null);
+                               return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+                       }
+                       return makeIfTruePointcut(state);
+               }
+
+               public void write(DataOutputStream s) throws IOException {
+                       s.writeByte(IF_TRUE);
+               }
+
+               public int hashCode() {
+                       int result = 37;
+                       return result;
+               }
+
+               public String toString() {
+                       return "if(true)";
+               }
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/KindedPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/KindedPointcut.java
new file mode 100644 (file)
index 0000000..2d68d17
--- /dev/null
@@ -0,0 +1,393 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.Checker;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.ShadowMunger;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+
+public class KindedPointcut extends Pointcut {
+       Shadow.Kind kind;
+       private SignaturePattern signature;
+       private int matchKinds;
+    
+    private ShadowMunger munger = null; // only set after concretization
+
+    public KindedPointcut(
+        Shadow.Kind kind,
+        SignaturePattern signature) {
+        this.kind = kind;
+        this.signature = signature;
+        this.pointcutKind = KINDED;
+        this.matchKinds = kind.bit;
+    }
+    public KindedPointcut(
+        Shadow.Kind kind,
+        SignaturePattern signature,
+        ShadowMunger munger) {
+        this(kind, signature);
+        this.munger = munger;
+    }
+
+    public SignaturePattern getSignature() {
+        return signature;
+    }
+
+    /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#couldMatchKinds()
+        */
+       public int couldMatchKinds() {
+               return matchKinds;
+       }
+       
+       public boolean couldEverMatchSameJoinPointsAs(KindedPointcut other) {
+               if (this.kind != other.kind) return false;
+               String myName = signature.getName().maybeGetSimpleName();
+               String yourName = other.signature.getName().maybeGetSimpleName();
+               if (myName != null && yourName != null) {
+                       if ( !myName.equals(yourName)) {
+                               return false;
+                       }
+               }
+               if (signature.getParameterTypes().ellipsisCount == 0) {
+                       if (other.signature.getParameterTypes().ellipsisCount == 0) {
+                               if (signature.getParameterTypes().getTypePatterns().length !=
+                                       other.signature.getParameterTypes().getTypePatterns().length) {
+                                       return false;
+                               }
+                       }
+               }
+               return true;
+       }
+       
+    public FuzzyBoolean fastMatch(FastMatchInfo info) {
+       if (info.getKind() != null) {
+                       if (info.getKind() != kind) return FuzzyBoolean.NO;
+       }
+
+               return FuzzyBoolean.MAYBE;
+       }       
+               
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               if (shadow.getKind() != kind) return FuzzyBoolean.NO;
+
+               if (shadow.getKind() == Shadow.SynchronizationLock && kind == Shadow.SynchronizationLock) return FuzzyBoolean.YES;
+               if (shadow.getKind() == Shadow.SynchronizationUnlock && kind == Shadow.SynchronizationUnlock) return FuzzyBoolean.YES;
+               
+               if (!signature.matches(shadow.getMatchingSignature(), shadow.getIWorld(),this.kind == Shadow.MethodCall)){
+
+            if(kind == Shadow.MethodCall) {
+                warnOnConfusingSig(shadow);
+                //warnOnBridgeMethod(shadow);
+            }
+            return FuzzyBoolean.NO; 
+        }
+
+               return FuzzyBoolean.YES;
+       }
+       
+       
+//     private void warnOnBridgeMethod(Shadow shadow) {
+//             if (shadow.getIWorld().getLint().noJoinpointsForBridgeMethods.isEnabled()) {
+//                     ResolvedMember rm = shadow.getSignature().resolve(shadow.getIWorld());
+//                     if (rm!=null) {
+//                     int shadowModifiers = rm.getModifiers(); //shadow.getSignature().getModifiers(shadow.getIWorld());
+//                         if (ResolvedType.hasBridgeModifier(shadowModifiers)) {
+//                               shadow.getIWorld().getLint().noJoinpointsForBridgeMethods.signal(new String[]{},getSourceLocation(),
+//                                             new ISourceLocation[]{shadow.getSourceLocation()});
+//                         }
+//            }
+//        }
+//     }
+       
+       private void warnOnConfusingSig(Shadow shadow) {
+               // Don't do all this processing if we don't need to !
+               if (!shadow.getIWorld().getLint().unmatchedSuperTypeInCall.isEnabled()) return;
+               
+        // no warnings for declare error/warning
+        if (munger instanceof Checker) return;
+        
+        World world = shadow.getIWorld();
+        
+               // warning never needed if the declaring type is any
+               UnresolvedType exactDeclaringType = signature.getDeclaringType().getExactType();
+        
+               ResolvedType shadowDeclaringType =
+                       shadow.getSignature().getDeclaringType().resolve(world);
+        
+               if (signature.getDeclaringType().isStar()
+                       || ResolvedType.isMissing(exactDeclaringType)
+                       || exactDeclaringType.resolve(world).isMissing())
+                       return;
+
+        // warning not needed if match type couldn't ever be the declaring type
+               if (!shadowDeclaringType.isAssignableFrom(exactDeclaringType.resolve(world))) {
+            return;
+               }
+
+               // if the method in the declaring type is *not* visible to the
+               // exact declaring type then warning not needed.
+               ResolvedMember rm = shadow.getSignature().resolve(world);
+               // rm can be null in the case where we are binary weaving, and looking at a class with a call to a method in another class,
+               // but because of class incompatibilities, the method does not exist on the target class anymore.
+               // this will be reported elsewhere.
+               if (rm == null) return; 
+               
+               int shadowModifiers = rm.getModifiers();
+               if (!ResolvedType
+                       .isVisible(
+                               shadowModifiers,
+                               shadowDeclaringType,
+                               exactDeclaringType.resolve(world))) {
+                       return;
+               }
+               
+               if (!signature.getReturnType().matchesStatically(shadow.getSignature().getReturnType().resolve(world))) {
+                       // Covariance issue...
+                       // The reason we didn't match is that the type pattern for the pointcut (Car) doesn't match the
+                       // return type for the specific declaration at the shadow. (FastCar Sub.getCar())
+                       // XXX Put out another XLINT in this case?
+                       return;
+               }
+               // PR60015 - Don't report the warning if the declaring type is object and 'this' is an interface
+               if (exactDeclaringType.resolve(world).isInterface() && shadowDeclaringType.equals(world.resolve("java.lang.Object"))) {
+                       return;
+               }
+
+               SignaturePattern nonConfusingPattern =
+                       new SignaturePattern(
+                               signature.getKind(),
+                               signature.getModifiers(),
+                               signature.getReturnType(),
+                               TypePattern.ANY,
+                               signature.getName(), 
+                               signature.getParameterTypes(),
+                               signature.getThrowsPattern(),
+                               signature.getAnnotationPattern());
+
+               if (nonConfusingPattern
+                       .matches(shadow.getSignature(), shadow.getIWorld(),true)) {
+                shadow.getIWorld().getLint().unmatchedSuperTypeInCall.signal(
+                    new String[] {
+                        shadow.getSignature().getDeclaringType().toString(),
+                        signature.getDeclaringType().toString()
+                    },
+                    this.getSourceLocation(),
+                    new ISourceLocation[] {shadow.getSourceLocation()} );               
+               }
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof KindedPointcut)) return false;
+               KindedPointcut o = (KindedPointcut)other;
+               return o.kind == this.kind && o.signature.equals(this.signature);
+       }
+    
+    public int hashCode() {
+        int result = 17;
+        result = 37*result + kind.hashCode();
+        result = 37*result + signature.hashCode();
+        return result;
+    }
+       
+       public String toString() {
+               StringBuffer buf = new StringBuffer();
+               buf.append(kind.getSimpleName());
+               buf.append("(");
+               buf.append(signature.toString());
+               buf.append(")");
+               return buf.toString();
+       }
+       
+       
+       public void postRead(ResolvedType enclosingType) {
+               signature.postRead(enclosingType);
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.KINDED);
+               kind.write(s);
+               signature.write(s);
+               writeLocation(s);
+       }
+       
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               Shadow.Kind kind = Shadow.Kind.read(s);
+               SignaturePattern sig = SignaturePattern.read(s, context);
+               KindedPointcut ret = new KindedPointcut(kind, sig);
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       // XXX note: there is no namebinding in any kinded pointcut.
+       // still might want to do something for better error messages
+       // We want to do something here to make sure we don't sidestep the parameter
+       // list in capturing type identifiers.
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               if (kind == Shadow.Initialization) {
+//                     scope.getMessageHandler().handleMessage(
+//                             MessageUtil.error(
+//                                     "initialization unimplemented in 1.1beta1",
+//                                     this.getSourceLocation()));
+               }
+               signature = signature.resolveBindings(scope, bindings);
+               
+               
+               if (kind == Shadow.ConstructorExecution) {              // Bug fix 60936
+                 if (signature.getDeclaringType() != null) {
+                       World world = scope.getWorld();
+                       UnresolvedType exactType = signature.getDeclaringType().getExactType();
+                       if (signature.getKind() == Member.CONSTRUCTOR &&
+                               !ResolvedType.isMissing(exactType) &&
+                               exactType.resolve(world).isInterface() &&
+                               !signature.getDeclaringType().isIncludeSubtypes()) {
+                                       world.getLint().noInterfaceCtorJoinpoint.signal(exactType.toString(), getSourceLocation());
+                               }
+                 }
+               }
+               
+               // no parameterized types
+               if (kind == Shadow.StaticInitialization) {
+                       HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor 
+                               visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
+                       signature.getDeclaringType().traverse(visitor, null);
+                       if (visitor.wellHasItThen/*?*/()) {
+                               scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.NO_STATIC_INIT_JPS_FOR_PARAMETERIZED_TYPES),
+                                               getSourceLocation()));
+                       }
+               }
+               
+               // no parameterized types in declaring type position
+               if ((kind == Shadow.FieldGet) || (kind == Shadow.FieldSet)) {
+                       HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor 
+                               visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
+                       signature.getDeclaringType().traverse(visitor, null);
+                       if (visitor.wellHasItThen/*?*/()) {
+                               scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.GET_AND_SET_DONT_SUPPORT_DEC_TYPE_PARAMETERS),
+                                               getSourceLocation()));
+                       }       
+                       
+                       // fields can't have a void type!
+                       UnresolvedType returnType = signature.getReturnType().getExactType();
+                       if (returnType == ResolvedType.VOID) {
+                               scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.FIELDS_CANT_HAVE_VOID_TYPE),
+                                               getSourceLocation()));                          
+                       }
+               }
+               
+               // no join points for initialization and preinitialization of parameterized types
+               // no throwable parameterized types
+               if ((kind == Shadow.Initialization) || (kind == Shadow.PreInitialization)) {
+                       HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor 
+                       visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
+                       signature.getDeclaringType().traverse(visitor, null);
+                       if (visitor.wellHasItThen/*?*/()) {
+                               scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.NO_INIT_JPS_FOR_PARAMETERIZED_TYPES),
+                                               getSourceLocation()));
+                       }                                               
+                       
+                       visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
+                       signature.getThrowsPattern().traverse(visitor, null);
+                       if (visitor.wellHasItThen/*?*/()) {
+                               scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.NO_GENERIC_THROWABLES),
+                                               getSourceLocation()));
+                       }                                                                       
+               }
+               
+               // no parameterized types in declaring type position
+               // no throwable parameterized types
+               if ((kind == Shadow.MethodExecution) || (kind == Shadow.ConstructorExecution)) {
+                       HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor 
+                       visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
+                       signature.getDeclaringType().traverse(visitor, null);
+                       if (visitor.wellHasItThen/*?*/()) {
+                               scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.EXECUTION_DOESNT_SUPPORT_PARAMETERIZED_DECLARING_TYPES),
+                                               getSourceLocation()));
+                       }                                               
+                       
+                       visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
+                       signature.getThrowsPattern().traverse(visitor, null);
+                       if (visitor.wellHasItThen/*?*/()) {
+                               scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.NO_GENERIC_THROWABLES),
+                                               getSourceLocation()));
+                       }                                                                       
+               }
+               
+               // no parameterized types in declaring type position
+               // no throwable parameterized types
+               if ((kind == Shadow.MethodCall) || (kind == Shadow.ConstructorCall)) {
+                       HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor 
+                       visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
+                       signature.getDeclaringType().traverse(visitor, null);
+                       if (visitor.wellHasItThen/*?*/()) {
+                               scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.CALL_DOESNT_SUPPORT_PARAMETERIZED_DECLARING_TYPES),
+                                               getSourceLocation()));
+                       }                                               
+                       
+                       visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
+                       signature.getThrowsPattern().traverse(visitor, null);
+                       if (visitor.wellHasItThen/*?*/()) {
+                               scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.NO_GENERIC_THROWABLES),
+                                               getSourceLocation()));
+                       }                                                       
+                       if (!scope.getWorld().isJoinpointArrayConstructionEnabled() && 
+                               kind==Shadow.ConstructorCall &&
+                               signature.getDeclaringType().isArray()) {
+                               scope.message(MessageUtil.warn(WeaverMessages.format(WeaverMessages.NO_NEWARRAY_JOINPOINTS_BY_DEFAULT),getSourceLocation()));
+                       }
+               }
+       }
+       
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
+       }
+       
+       public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType,  IntMap bindings) {
+               Pointcut ret = new KindedPointcut(kind, signature, bindings.getEnclosingAdvice());
+        ret.copyLocationFrom(this);
+        return ret;
+       }
+       
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               Pointcut ret = new KindedPointcut(kind, signature.parameterizeWith(typeVariableMap,w), munger );
+        ret.copyLocationFrom(this);
+        return ret;
+       }
+
+       public Shadow.Kind getKind() {
+               return kind;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ModifiersPattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ModifiersPattern.java
new file mode 100644 (file)
index 0000000..7d304c6
--- /dev/null
@@ -0,0 +1,99 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.aspectj.weaver.VersionedDataInputStream;
+
+public class ModifiersPattern extends PatternNode {
+       private int requiredModifiers;
+       private int forbiddenModifiers;
+       
+       public static final ModifiersPattern ANY = new ModifiersPattern(0, 0);
+       
+       public ModifiersPattern(int requiredModifiers, int forbiddenModifiers) {
+               this.requiredModifiers = requiredModifiers;
+               this.forbiddenModifiers = forbiddenModifiers;
+       }
+
+       public String toString() {
+               if (this == ANY) return "";
+               
+               String ret = Modifier.toString(requiredModifiers);
+               if (forbiddenModifiers == 0) return ret;
+               else return ret + " !" + Modifier.toString(forbiddenModifiers);
+       }
+    
+       public boolean equals(Object other) {
+               if (!(other instanceof ModifiersPattern)) return false;
+               ModifiersPattern o = (ModifiersPattern)other;
+               return o.requiredModifiers == this.requiredModifiers &&
+                               o.forbiddenModifiers == this.forbiddenModifiers;
+       }
+    public int hashCode() {
+        int result = 17;
+        result = 37*result + requiredModifiers;
+        result = 37*result + forbiddenModifiers;
+        return result;
+    }  
+    
+       public boolean matches(int modifiers) {
+               return ((modifiers & requiredModifiers) == requiredModifiers) &&
+                       ((modifiers & forbiddenModifiers) == 0);
+       }
+       
+
+       public static ModifiersPattern read(VersionedDataInputStream s) throws IOException {
+               int requiredModifiers = s.readShort();
+               int forbiddenModifiers = s.readShort();
+               if (requiredModifiers == 0 && forbiddenModifiers == 0) return ANY;
+               return new ModifiersPattern(requiredModifiers, forbiddenModifiers);
+       }
+
+       /**
+        * @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               //s.writeByte(MODIFIERS_PATTERN);
+               s.writeShort(requiredModifiers);
+               s.writeShort(forbiddenModifiers);
+       }
+       
+       
+       private static Map modifierFlags = null;
+
+       public static int getModifierFlag(String name) {
+               if (modifierFlags == null) {
+                       modifierFlags = new HashMap();
+                       int flag = 1;
+                       while (flag <= Modifier.STRICT) {
+                               String flagName = Modifier.toString(flag);
+                               modifierFlags.put(flagName, new Integer(flag));
+                               flag = flag << 1;
+                       }
+               }
+               Integer flag = (Integer)modifierFlags.get(name);
+               if (flag == null) return -1;
+               return flag.intValue();
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NameBindingPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NameBindingPointcut.java
new file mode 100644 (file)
index 0000000..511ff68
--- /dev/null
@@ -0,0 +1,52 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.util.List;
+
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.ast.Var;
+
+/**
+ * Common super type for Pointcuts that can bind formal parameters.
+ * 
+ * @author Erik Hilsdale
+ * @author Jim Hugunin
+ */
+public abstract class NameBindingPointcut extends Pointcut {
+
+       public NameBindingPointcut() {
+               super();
+       }
+
+       protected Test exposeStateForVar(Var var,TypePattern type, ExposedState state, World world) {
+               if (type instanceof BindingTypePattern) {
+                       BindingTypePattern b = (BindingTypePattern)type;
+                       state.set(b.getFormalIndex(), var);
+               }
+               ResolvedType myType = type.getExactType().resolve(world);
+               if (myType.isParameterizedType()) {
+                       // unchecked warning already issued...
+                       myType = (ResolvedType) myType.getRawType();
+               }
+               return Test.makeInstanceof(var, myType.resolve(world));
+       }
+       
+       public abstract List/*<BindingTypePattern>*/ getBindingTypePatterns();
+       public abstract List/*<BindingAnnotationTypePattern>*/ getBindingAnnotationTypePatterns();
+
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NamePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NamePattern.java
new file mode 100644 (file)
index 0000000..4a63c8d
--- /dev/null
@@ -0,0 +1,171 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.weaver.VersionedDataInputStream;
+
+public class NamePattern extends PatternNode {
+       char[] pattern;
+       int starCount = 0;
+       private int hashcode = -1;
+
+       public static final NamePattern ELLIPSIS = new NamePattern("");
+       public static final NamePattern ANY = new NamePattern("*");
+
+       public NamePattern(String name) {
+               this(name.toCharArray());
+       }
+       
+       public NamePattern(char[] pattern) {
+               this.pattern = pattern;
+               
+               for (int i=0, len=pattern.length; i<len; i++) {
+                       if (pattern[i] == '*') starCount++;
+               }
+               hashcode = new String(pattern).hashCode();
+       }
+       
+       public boolean matches(char[] a2) {
+               char[] a1 = pattern;
+               int len1 = a1.length;
+               int len2 = a2.length;
+               if (starCount == 0) {
+                       if (len1 != len2) return false;
+                       for (int i=0; i<len1; i++) {
+                               if (a1[i] != a2[i]) return false;
+                       }
+                       return true;
+               } else if (starCount == 1) {
+                       // just '*' matches anything
+                       if (len1 == 1) return true;
+                       if (len1 > len2+1) return false;
+                       
+                       int i2=0;
+                       for (int i1=0; i1<len1; i1++) {
+                               char c1 = a1[i1];
+                               if (c1 == '*') {
+                                       i2 = len2 - (len1-(i1+1));
+                               } else if (c1 != a2[i2++]) {
+                                       return false;
+                               }
+                       }
+                       return true;
+               } else {
+//            String pattern = new String(a1);
+//            String target = new String(a2);
+//            System.err.print("match(\"" + pattern + "\", \"" + target + "\") -> ");
+            boolean b = outOfStar(a1, a2, 0, 0, len1 - starCount, len2, starCount);
+//            System.err.println(b);
+            return b;
+               }
+    }
+    private static boolean outOfStar(final char[] pattern, final char[] target, 
+                                              int     pi,            int     ti, 
+                                              int     pLeft,         int     tLeft,
+                                       final int     starsLeft) {
+        if (pLeft > tLeft) return false;
+        while (true) {
+            // invariant: if (tLeft > 0) then (ti < target.length && pi < pattern.length) 
+            if (tLeft == 0) return true;
+            if (pLeft == 0) {
+                return (starsLeft > 0);  
+            }
+            if (pattern[pi] == '*') {
+                return inStar(pattern, target, pi+1, ti, pLeft, tLeft, starsLeft-1);
+            }
+            if (target[ti] != pattern[pi]) {
+                return false;
+            }
+            pi++; ti++; pLeft--; tLeft--;
+        }
+    }    
+    private static boolean inStar(final char[] pattern, final char[] target, 
+                                           int    pi,             int    ti, 
+                                     final int    pLeft,          int    tLeft,
+                                            int    starsLeft) {
+        // invariant: pLeft > 0, so we know we'll run out of stars and find a real char in pattern
+        char patternChar = pattern[pi];
+        while (patternChar == '*') {
+            starsLeft--;
+            patternChar = pattern[++pi];
+        }
+        while (true) {
+            // invariant: if (tLeft > 0) then (ti < target.length)
+            if (pLeft > tLeft) return false;
+            if (target[ti] == patternChar) {
+                if (outOfStar(pattern, target, pi+1, ti+1, pLeft-1, tLeft-1, starsLeft)) return true;
+            }
+            ti++; tLeft--;
+        }
+    }    
+       
+       public boolean matches(String other) {
+               return matches(other.toCharArray());
+       }
+       
+       public String toString() {
+               return new String(pattern);
+       }
+       
+       public boolean equals(Object other) {
+               if (other instanceof NamePattern) {
+                       NamePattern otherPat = (NamePattern)other;
+                       if (otherPat.starCount!=this.starCount) return false;
+                       if (otherPat.pattern.length!=this.pattern.length) return false;
+                       for (int i = 0; i < this.pattern.length; i++) {
+                               if (this.pattern[i]!=otherPat.pattern[i]) return false;                 
+                       }
+                       return true;
+               }
+               return false;
+       }
+       
+    public int hashCode() {
+       return hashcode;
+    }
+    
+    
+       public void write(DataOutputStream out) throws IOException {
+               out.writeUTF(new String(pattern));
+       }
+       
+       public static NamePattern read(VersionedDataInputStream in) throws IOException {
+               String s = in.readUTF();
+               if (s.length() == 0) return ELLIPSIS;
+               return new NamePattern(s);
+       }
+       /**
+        * Method maybeGetSimpleName.
+        * @return String
+        */
+       public String maybeGetSimpleName() {
+               if (starCount == 0 && pattern.length > 0) return new String(pattern);
+               return null;
+       }
+
+       /**
+        * Method isAny.
+        * @return boolean
+        */
+       public boolean isAny() {
+               return starCount == 1 && pattern.length == 1;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NotAnnotationTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NotAnnotationTypePattern.java
new file mode 100644 (file)
index 0000000..0280294
--- /dev/null
@@ -0,0 +1,120 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
+
+public class NotAnnotationTypePattern extends AnnotationTypePattern {
+
+       AnnotationTypePattern negatedPattern;
+       
+       public NotAnnotationTypePattern(AnnotationTypePattern pattern) {
+               this.negatedPattern = pattern;
+               setLocation(pattern.getSourceContext(), pattern.getStart(), pattern.getEnd());
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.AnnotationTypePattern#matches(org.aspectj.weaver.AnnotatedElement)
+        */
+       public FuzzyBoolean matches(AnnotatedElement annotated) {
+               return negatedPattern.matches(annotated).not();
+       }
+       
+       public FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations) {
+               return negatedPattern.matches(annotated,parameterAnnotations).not();
+       }
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.AnnotationTypePattern#resolve(org.aspectj.weaver.World)
+        */
+       public void resolve(World world) {
+               negatedPattern.resolve(world);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.AnnotationTypePattern#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings, boolean)
+        */
+       public AnnotationTypePattern resolveBindings(IScope scope,
+                       Bindings bindings, boolean allowBinding) {
+               negatedPattern = negatedPattern.resolveBindings(scope,bindings,allowBinding);
+               return this;
+       }
+
+       
+       public AnnotationTypePattern parameterizeWith(Map typeVariableMap,World w) {
+               AnnotationTypePattern newNegatedPattern = negatedPattern.parameterizeWith(typeVariableMap,w);
+               NotAnnotationTypePattern ret = new NotAnnotationTypePattern(newNegatedPattern);
+               ret.copyLocationFrom(this);
+               if (this.isForParameterAnnotationMatch()) ret.setForParameterAnnotationMatch();
+               return ret;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(AnnotationTypePattern.NOT);
+               negatedPattern.write(s);
+               writeLocation(s);
+               s.writeBoolean(isForParameterAnnotationMatch());
+       }
+
+       public static AnnotationTypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               AnnotationTypePattern ret = new NotAnnotationTypePattern(AnnotationTypePattern.read(s,context));
+               ret.readLocation(context,s);
+               if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160) {
+                       if (s.readBoolean()) ret.setForParameterAnnotationMatch();
+               }
+               return ret;
+       }
+       
+       public boolean equals(Object obj) {
+               if (!(obj instanceof NotAnnotationTypePattern)) return false;
+               NotAnnotationTypePattern other = (NotAnnotationTypePattern) obj;
+               return other.negatedPattern.equals(negatedPattern) && other.isForParameterAnnotationMatch()==isForParameterAnnotationMatch();
+       }
+
+       public int hashCode() {
+               int result = 17 + 37*negatedPattern.hashCode();
+               result = 37*result +(isForParameterAnnotationMatch()?0:1);
+               return result;
+       }
+       
+       public String toString() {
+               return "!" + negatedPattern.toString();
+       }
+       
+       public AnnotationTypePattern getNegatedPattern() {
+               return negatedPattern;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               negatedPattern.traverse(visitor,ret);
+               return ret;
+       }
+
+       public void setForParameterAnnotationMatch() {
+               negatedPattern.setForParameterAnnotationMatch();
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NotPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NotPointcut.java
new file mode 100644 (file)
index 0000000..4a131c9
--- /dev/null
@@ -0,0 +1,123 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Test;
+
+public class NotPointcut extends Pointcut {
+       private Pointcut body;
+       public NotPointcut(Pointcut negated) {
+               super();
+               this.body = negated;
+               this.pointcutKind = NOT;
+               setLocation(negated.getSourceContext(), negated.getStart(),negated.getEnd()); // should that be at least start-1?
+       }
+
+       public NotPointcut(Pointcut pointcut, int startPos) {
+               this(pointcut);
+               setLocation(pointcut.getSourceContext(), startPos, pointcut.getEnd());          
+       }
+
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;
+       }
+       
+       public Pointcut getNegatedPointcut() { return body; }
+
+       public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               return body.fastMatch(type).not();
+       }
+       
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               return body.match(shadow).not();
+       }
+
+       public String toString() {
+               return "!" + body.toString();
+
+       }
+       
+       public boolean equals(Object other) { 
+               if (!(other instanceof NotPointcut)) return false;
+               NotPointcut o = (NotPointcut)other;
+               return o.body.equals(body);
+       }
+    public int hashCode() {
+        return 37*23 + body.hashCode();
+    }
+
+
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               //Bindings old = bindings.copy();
+               
+               //Bindings newBindings = new Bindings(bindings.size());
+               
+               
+               body.resolveBindings(scope, null);
+               
+               //newBindings.checkEmpty(scope, "negation does not allow binding");
+               //bindings.checkEquals(old, scope);
+               
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.NOT);
+               body.write(s);
+               writeLocation(s);
+       }
+       
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               NotPointcut ret = new NotPointcut(Pointcut.read(s, context));
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               return Test.makeNot(body.findResidue(shadow, state));
+       }
+       
+       public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               Pointcut ret = new NotPointcut(body.concretize(inAspect, declaringType, bindings));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               Pointcut ret = new NotPointcut(body.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               this.body.traverse(visitor,ret);
+               return ret;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NotTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NotTypePattern.java
new file mode 100644 (file)
index 0000000..5ade60e
--- /dev/null
@@ -0,0 +1,154 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+/**
+ * !TypePattern
+ * 
+ * <p>any binding to formals is explicitly forbidden for any composite, ! is
+ * just the most obviously wrong case.
+ * 
+ * @author Erik Hilsdale
+ * @author Jim Hugunin
+ */
+public class NotTypePattern extends TypePattern {
+       private TypePattern negatedPattern;
+       
+       public NotTypePattern(TypePattern pattern) {
+               super(false,false);  //??? we override all methods that care about includeSubtypes
+               this.negatedPattern = pattern;
+               setLocation(pattern.getSourceContext(), pattern.getStart(), pattern.getEnd());
+       }
+
+    public TypePattern getNegatedPattern() {
+        return negatedPattern;
+    }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
+        */
+       protected boolean couldEverMatchSameTypesAs(TypePattern other) {
+               return true;
+       }
+       
+       public FuzzyBoolean matchesInstanceof(ResolvedType type) {
+               return negatedPattern.matchesInstanceof(type).not();
+       }
+
+       protected boolean matchesExactly(ResolvedType type) {
+               return (!negatedPattern.matchesExactly(type) && annotationPattern.matches(type).alwaysTrue());
+       }
+       
+       protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
+               return (!negatedPattern.matchesExactly(type,annotatedType) && annotationPattern.matches(annotatedType).alwaysTrue());
+       }
+               
+       public boolean matchesStatically(ResolvedType type) {
+               return !negatedPattern.matchesStatically(type);
+       }
+       
+       public void setAnnotationTypePattern(AnnotationTypePattern annPatt) {
+               super.setAnnotationTypePattern(annPatt);
+       }
+       
+       public void setIsVarArgs(boolean isVarArgs) {
+               negatedPattern.setIsVarArgs(isVarArgs);
+       }
+       
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(TypePattern.NOT);
+               negatedPattern.write(s);
+               annotationPattern.write(s);
+               writeLocation(s);
+       }
+       
+       public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               TypePattern ret = new NotTypePattern(TypePattern.read(s, context));
+               if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
+                       ret.annotationPattern = AnnotationTypePattern.read(s,context);
+               }
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public TypePattern resolveBindings(
+               IScope scope,
+               Bindings bindings,
+               boolean allowBinding, boolean requireExactType)
+       {
+               if (requireExactType) return notExactType(scope);
+               negatedPattern = negatedPattern.resolveBindings(scope, bindings, false, false);
+               return this;
+       }
+       
+       public TypePattern parameterizeWith(Map typeVariableMap,World w) {
+               TypePattern newNegatedPattern = negatedPattern.parameterizeWith(typeVariableMap,w);
+               NotTypePattern ret = new NotTypePattern(newNegatedPattern);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public String toString() {
+               StringBuffer buff = new StringBuffer();
+               if (annotationPattern != AnnotationTypePattern.ANY) {
+                       buff.append('(');
+                       buff.append(annotationPattern.toString());
+                       buff.append(' ');
+               }
+               buff.append('!');
+               buff.append(negatedPattern);
+               if (annotationPattern != AnnotationTypePattern.ANY) {
+                       buff.append(')');
+               }
+               return buff.toString();
+       }
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       public boolean equals(Object obj) {
+               if (! (obj instanceof NotTypePattern)) return false;
+               return (negatedPattern.equals(((NotTypePattern)obj).negatedPattern));
+       }
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       public int hashCode() {
+               return 17 + 37 * negatedPattern.hashCode();
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               negatedPattern.traverse(visitor, ret);
+               return ret;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/OrAnnotationTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/OrAnnotationTypePattern.java
new file mode 100644 (file)
index 0000000..9c70ac3
--- /dev/null
@@ -0,0 +1,123 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
+
+public class OrAnnotationTypePattern extends AnnotationTypePattern {
+
+       private AnnotationTypePattern left;
+       private AnnotationTypePattern right;
+       
+       public OrAnnotationTypePattern(AnnotationTypePattern left, AnnotationTypePattern right) {
+               this.left = left;
+               this.right = right;
+               setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
+       }
+
+       public FuzzyBoolean matches(AnnotatedElement annotated) {
+               return left.matches(annotated).or(right.matches(annotated));
+       }
+
+       public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations ) {
+               return left.matches(annotated,parameterAnnotations).or(right.matches(annotated,parameterAnnotations));
+       }
+       
+       public void resolve(World world) {
+               left.resolve(world);
+               right.resolve(world);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.AnnotationTypePattern#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings, boolean)
+        */
+       public AnnotationTypePattern resolveBindings(IScope scope,
+                       Bindings bindings, boolean allowBinding) {
+               left = left.resolveBindings(scope,bindings,allowBinding);
+               right =right.resolveBindings(scope,bindings,allowBinding);
+               return this;
+       }
+
+       public AnnotationTypePattern parameterizeWith(Map typeVariableMap,World w) {
+               AnnotationTypePattern newLeft = left.parameterizeWith(typeVariableMap,w);
+               AnnotationTypePattern newRight = right.parameterizeWith(typeVariableMap,w);
+               OrAnnotationTypePattern ret = new OrAnnotationTypePattern(newLeft,newRight);
+               ret.copyLocationFrom(this);
+               if (isForParameterAnnotationMatch()) ret.setForParameterAnnotationMatch();
+               return ret;
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               left.traverse(visitor,ret);
+               right.traverse(visitor,ret);
+               return ret;
+       }
+       
+       public static AnnotationTypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               AnnotationTypePattern p = new OrAnnotationTypePattern(
+                               AnnotationTypePattern.read(s,context),
+                               AnnotationTypePattern.read(s,context));
+               p.readLocation(context,s);
+               if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160) {
+                       if (s.readBoolean()) p.setForParameterAnnotationMatch();
+               }
+               return p;               
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(AnnotationTypePattern.OR);
+               left.write(s);
+               right.write(s);
+               writeLocation(s);
+               s.writeBoolean(isForParameterAnnotationMatch());
+       }
+       
+       public boolean equals(Object obj) {
+               if (!(obj instanceof OrAnnotationTypePattern)) return false;
+               OrAnnotationTypePattern other = (OrAnnotationTypePattern) obj;
+               return (left.equals(other.left) && right.equals(other.right)) && isForParameterAnnotationMatch()==other.isForParameterAnnotationMatch();
+       }
+       
+       public int hashCode() {
+               int result = 17;
+               result = result*37 + left.hashCode();
+               result = result*37 + right.hashCode();
+               result = result*37 + (isForParameterAnnotationMatch()?0:1);
+               return result;          
+       }
+       
+       public String toString() {
+               return "(" + left.toString() + " || " + right.toString() + ")";
+       }
+
+       public AnnotationTypePattern getLeft() { return left; }
+       public AnnotationTypePattern getRight() { return right; }
+
+       public void setForParameterAnnotationMatch() {
+               left.setForParameterAnnotationMatch();
+               right.setForParameterAnnotationMatch();
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/OrPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/OrPointcut.java
new file mode 100644 (file)
index 0000000..01637f3
--- /dev/null
@@ -0,0 +1,132 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Test;
+
+public class OrPointcut extends Pointcut {
+       Pointcut left, right;
+       private int couldMatchKinds;
+
+       public OrPointcut(Pointcut left, Pointcut right) {
+               super();
+               this.left = left;
+               this.right = right;
+               setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
+               this.pointcutKind = OR;
+               this.couldMatchKinds = left.couldMatchKinds() | right.couldMatchKinds();
+       }
+
+       public int couldMatchKinds() {
+               return couldMatchKinds;
+       }
+
+       public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               return left.fastMatch(type).or(right.fastMatch(type));
+       }
+       
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               FuzzyBoolean leftMatch = left.match(shadow);
+               if (leftMatch.alwaysTrue()) return leftMatch;
+               return leftMatch.or(right.match(shadow));
+       }
+       
+       public String toString() {
+               return "(" + left.toString() + " || " + right.toString() + ")";
+       }
+       
+       public boolean equals(Object other) { 
+               if (!(other instanceof OrPointcut)) return false;
+               OrPointcut o = (OrPointcut)other;
+               return o.left.equals(left) && o.right.equals(right);
+       }
+    public int hashCode() {
+        int result = 31;
+        result = 37*result + left.hashCode();
+        result = 37*result + right.hashCode();
+        return result;
+    }
+       /**
+        * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(IScope, Bindings)
+        */
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               Bindings old = bindings == null ? null : bindings.copy();
+               
+               left.resolveBindings(scope, bindings);
+               right.resolveBindings(scope, old);
+               if (bindings != null) bindings.checkEquals(old, scope);
+               
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.OR);
+               left.write(s);
+               right.write(s);
+               writeLocation(s);
+       }
+       
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               OrPointcut ret = new OrPointcut(Pointcut.read(s, context), Pointcut.read(s, context));
+               ret.readLocation(context, s);
+               return ret;
+       
+       }
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               return Test.makeOr(left.findResidue(shadow, state), right.findResidue(shadow, state));
+       }
+       
+       public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               Pointcut ret = new OrPointcut(left.concretize(inAspect, declaringType, bindings),
+                                                               right.concretize(inAspect, declaringType, bindings));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               Pointcut ret = new OrPointcut(left.parameterizeWith(typeVariableMap,w),
+                                                                         right.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public Pointcut getLeft() {
+               return left;
+       }
+
+       public Pointcut getRight() {
+               return right;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               left.traverse(visitor, ret);
+               right.traverse(visitor,ret);
+               return ret;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/OrTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/OrTypePattern.java
new file mode 100644 (file)
index 0000000..52a18d5
--- /dev/null
@@ -0,0 +1,184 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+/**
+ * left || right
+ * 
+ * <p>any binding to formals is explicitly forbidden for any composite by the language
+ * 
+ * @author Erik Hilsdale
+ * @author Jim Hugunin
+ */
+public class OrTypePattern extends TypePattern {
+       private TypePattern left, right;
+       
+       public OrTypePattern(TypePattern left, TypePattern right) {
+               super(false,false);  //??? we override all methods that care about includeSubtypes
+               this.left = left;
+               this.right = right;
+               setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
+       }
+
+    public TypePattern getRight() {
+        return right;
+    }
+
+    public TypePattern getLeft() {
+        return left;
+    }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
+        */
+       protected boolean couldEverMatchSameTypesAs(TypePattern other) {
+               return true; // don't dive at the moment...
+       }
+       
+       public FuzzyBoolean matchesInstanceof(ResolvedType type) {
+               return left.matchesInstanceof(type).or(right.matchesInstanceof(type));
+       }
+
+       protected boolean matchesExactly(ResolvedType type) {
+               //??? if these had side-effects, this sort-circuit could be a mistake
+               return left.matchesExactly(type) || right.matchesExactly(type);
+       }
+
+       protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
+               //??? if these had side-effects, this sort-circuit could be a mistake
+               return left.matchesExactly(type,annotatedType) || right.matchesExactly(type,annotatedType);
+       }
+       
+       public boolean matchesStatically(ResolvedType type) {
+               return left.matchesStatically(type) || right.matchesStatically(type);
+       }
+       
+       public void setIsVarArgs(boolean isVarArgs) {
+               this.isVarArgs = isVarArgs;
+               left.setIsVarArgs(isVarArgs);
+               right.setIsVarArgs(isVarArgs);
+       }
+       
+       public void setAnnotationTypePattern(AnnotationTypePattern annPatt) {
+               if (annPatt == AnnotationTypePattern.ANY) return;
+               if (left.annotationPattern == AnnotationTypePattern.ANY) {
+                       left.setAnnotationTypePattern(annPatt);
+               } else {
+                       left.setAnnotationTypePattern(
+                                       new AndAnnotationTypePattern(left.annotationPattern,annPatt));
+               }
+               if (right.annotationPattern == AnnotationTypePattern.ANY) {
+                       right.setAnnotationTypePattern(annPatt);                        
+               } else {
+                       right.setAnnotationTypePattern(
+                                       new AndAnnotationTypePattern(right.annotationPattern,annPatt));                 
+               }
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(TypePattern.OR);
+               left.write(s);
+               right.write(s);
+               writeLocation(s);
+       }
+       
+       public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               OrTypePattern ret = new OrTypePattern(TypePattern.read(s, context), TypePattern.read(s, context));
+               ret.readLocation(context, s);
+               if (ret.left.isVarArgs && ret.right.isVarArgs) ret.isVarArgs = true;
+               return ret;
+       }
+
+       public TypePattern resolveBindings(
+               IScope scope,
+               Bindings bindings,
+               boolean allowBinding, boolean requireExactType)
+       {
+               if (requireExactType) return notExactType(scope);
+               left = left.resolveBindings(scope, bindings, false, false);
+               right = right.resolveBindings(scope, bindings, false, false);
+               return this;
+       }
+       
+       public TypePattern parameterizeWith(Map typeVariableMap,World w) {
+               TypePattern newLeft = left.parameterizeWith(typeVariableMap,w);
+               TypePattern newRight = right.parameterizeWith(typeVariableMap,w);
+               OrTypePattern ret = new OrTypePattern(newLeft,newRight);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public String toString() {
+               StringBuffer buff = new StringBuffer();
+               if (annotationPattern != AnnotationTypePattern.ANY) {
+                       buff.append('(');
+                       buff.append(annotationPattern.toString());
+                       buff.append(' ');
+               }
+               buff.append('(');
+               buff.append(left.toString());
+               buff.append(" || ");
+               buff.append(right.toString());
+               buff.append(')');
+               if (annotationPattern != AnnotationTypePattern.ANY) {
+                       buff.append(')');
+               }
+               return buff.toString();
+       }
+
+       public boolean isStarAnnotation() {
+               return left.isStarAnnotation() || right.isStarAnnotation();
+       }
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       public boolean equals(Object obj) {
+               if (! (obj instanceof OrTypePattern)) return false;
+               OrTypePattern other = (OrTypePattern) obj;
+               return left.equals(other.left) && right.equals(other.right);
+       }
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       public int hashCode() {
+               int ret = 17;
+               ret = ret + 37 * left.hashCode();
+               ret = ret + 37 * right.hashCode();
+               return ret;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               left.traverse(visitor, ret);
+               right.traverse(visitor, ret);
+               return ret;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ParserException.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ParserException.java
new file mode 100644 (file)
index 0000000..cce9287
--- /dev/null
@@ -0,0 +1,31 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.IHasPosition;
+
+
+public class ParserException extends RuntimeException {
+       private IHasPosition token;
+       
+       public ParserException(String message, IHasPosition token) {
+               super(message);
+               this.token = token;
+       }
+       
+       public IHasPosition getLocation() {
+               return token;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternNode.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternNode.java
new file mode 100644 (file)
index 0000000..8cf9f3f
--- /dev/null
@@ -0,0 +1,89 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.weaver.IHasSourceLocation;
+import org.aspectj.weaver.ISourceContext;
+
+public abstract class PatternNode implements IHasSourceLocation {
+       protected int start, end;
+       protected ISourceContext sourceContext;
+
+       public PatternNode() {
+               super();
+               start = end = -1;
+       }
+
+       public int getStart() {
+               return start + (sourceContext != null ? sourceContext.getOffset() : 0);
+       }
+
+       public int getEnd() {
+               return end + (sourceContext != null ? sourceContext.getOffset() : 0);
+       }
+       
+       public ISourceContext getSourceContext() {
+               return sourceContext;
+       }
+       
+       public String getFileName() {
+               return "unknown";
+       }
+
+    public void setLocation(ISourceContext sourceContext, int start, int end) {
+       this.sourceContext = sourceContext;
+       this.start = start;
+       this.end = end;
+    }
+    
+    public void copyLocationFrom(PatternNode other) {
+       this.start = other.start;
+       this.end = other.end;
+       this.sourceContext = other.sourceContext;
+    }
+    
+    public ISourceLocation getSourceLocation() {
+       //System.out.println("get context: " + this + " is " + sourceContext);
+       if (sourceContext == null) {
+               //System.err.println("no context: " + this);
+               return null;
+       }
+       return sourceContext.makeSourceLocation(this);
+    }
+
+       public abstract void write(DataOutputStream s) throws IOException;
+
+
+       public void writeLocation(DataOutputStream s) throws IOException {
+               s.writeInt(start);
+               s.writeInt(end);
+       }
+       
+       public void readLocation(ISourceContext context, DataInputStream s) throws IOException {
+               start = s.readInt();
+               end = s.readInt();
+               this.sourceContext = context;
+       }
+
+    public abstract Object accept(PatternNodeVisitor visitor, Object data);
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               return accept(visitor,data);
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java
new file mode 100644 (file)
index 0000000..3fedd71
--- /dev/null
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ * 
+ * Contributors:
+ *   Alexandre Vasseur         initial implementation
+ *   Adrian Colyer                refactoring for traversal and grouping by kind
+ *******************************************************************************/
+package org.aspectj.weaver.patterns;
+
+
+/**
+ * A Pointcut or TypePattern visitor
+ *
+ * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+ */
+public interface PatternNodeVisitor {
+
+       // Annotation type patterns
+       Object visit(AndAnnotationTypePattern node, Object data);
+    Object visit(AnyAnnotationTypePattern node, Object data);
+    Object visit(EllipsisAnnotationTypePattern node, Object data);
+    Object visit(ExactAnnotationTypePattern node, Object data);
+    Object visit(BindingAnnotationTypePattern node, Object data);
+    Object visit(NotAnnotationTypePattern node, Object data);
+    Object visit(OrAnnotationTypePattern node, Object data);
+    Object visit(WildAnnotationTypePattern node, Object data);
+    Object visit(AnnotationPatternList node, Object data);
+
+    // Regular type patterns   
+    Object visit(AndTypePattern node, Object data);    
+    Object visit(AnyTypePattern node, Object data);
+    Object visit(AnyWithAnnotationTypePattern node, Object data);
+    Object visit(EllipsisTypePattern node, Object data);
+    Object visit(ExactTypePattern node, Object data);
+    Object visit(BindingTypePattern node, Object data);
+    Object visit(NotTypePattern node, Object data);
+    Object visit(NoTypePattern node, Object data);
+    Object visit(OrTypePattern node, Object data);
+    Object visit(WildTypePattern node, Object data);
+    Object visit(TypePatternList node, Object data);
+    Object visit(HasMemberTypePattern node, Object data);
+
+    // Pointcuts
+       Object visit(AndPointcut node, Object data);
+    Object visit(CflowPointcut node, Object data);
+    Object visit(ConcreteCflowPointcut node, Object data);
+    Object visit(HandlerPointcut node, Object data);
+    Object visit(IfPointcut node, Object data);
+    Object visit(KindedPointcut node, Object data);
+    Object visit(Pointcut.MatchesNothingPointcut node, Object data);
+    Object visit(AnnotationPointcut node, Object data);
+    Object visit(ArgsAnnotationPointcut node, Object data);
+    Object visit(ArgsPointcut node, Object data);
+    Object visit(ThisOrTargetAnnotationPointcut node, Object data);
+    Object visit(ThisOrTargetPointcut node, Object data);
+    Object visit(WithinAnnotationPointcut node, Object data);
+    Object visit(WithinCodeAnnotationPointcut node, Object data);
+    Object visit(NotPointcut node, Object data);
+    Object visit(OrPointcut node, Object data);
+    Object visit(ReferencePointcut node, Object data);
+    Object visit(WithinPointcut node, Object data);
+    Object visit(WithincodePointcut node, Object data);
+
+       // Per-clauses
+    Object visit(PerCflow node, Object data);
+    Object visit(PerFromSuper node, Object data);
+    Object visit(PerObject node, Object data);
+    Object visit(PerSingleton node, Object data);
+    Object visit(PerTypeWithin node, Object data);
+
+       
+       // Declares
+    Object visit(DeclareAnnotation node, Object data);
+    Object visit(DeclareErrorOrWarning node, Object data);
+    Object visit(DeclareParents node, Object data);
+    Object visit(DeclarePrecedence node, Object data);
+    Object visit(DeclareSoft node, Object data);
+
+       // Miscellaneous patterns
+    Object visit(ModifiersPattern node, Object data);
+    Object visit(NamePattern node, Object data);
+    Object visit(SignaturePattern node, Object data);
+    Object visit(ThrowsPattern node, Object data);
+       Object visit(TypeVariablePattern node, Object data);
+       Object visit(TypeVariablePatternList node,Object data);
+
+       // Catch-all
+    Object visit(PatternNode node, Object data);
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java
new file mode 100644 (file)
index 0000000..a1110eb
--- /dev/null
@@ -0,0 +1,1585 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ *               2005 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation
+ *     Adrian Colyer many updates since.... 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.MemberKind;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.internal.tools.PointcutDesignatorHandlerBasedPointcut;
+import org.aspectj.weaver.reflect.ReflectionWorld;
+import org.aspectj.weaver.tools.ContextBasedMatcher;
+import org.aspectj.weaver.tools.PointcutDesignatorHandler;
+
+//XXX doesn't handle errors for extra tokens very well (sometimes ignores)
+public class PatternParser {
+               
+       private ITokenSource tokenSource;       
+       private ISourceContext sourceContext;
+       
+       /** not thread-safe, but this class is not intended to be... */
+       private boolean allowHasTypePatterns = false;
+       
+       /** extension handlers used in weaver tools API only */
+       private Set pointcutDesignatorHandlers = Collections.EMPTY_SET;
+       private ReflectionWorld world;
+       
+       /**
+        * Constructor for PatternParser.
+        */
+       public PatternParser(ITokenSource tokenSource) {
+               super();
+               this.tokenSource = tokenSource;
+               this.sourceContext = tokenSource.getSourceContext();
+       }
+       
+       /** only used by weaver tools API */
+       public void setPointcutDesignatorHandlers(Set handlers, ReflectionWorld world) {
+               this.pointcutDesignatorHandlers = handlers;
+               this.world = world;
+       }
+
+       public PerClause maybeParsePerClause() {
+               IToken tok = tokenSource.peek();
+               if (tok == IToken.EOF) return null;
+               if (tok.isIdentifier()) {
+                       String name = tok.getString();
+                       if (name.equals("issingleton")) {
+                               return parsePerSingleton();
+                       } else if (name.equals("perthis")) {
+                               return parsePerObject(true);
+                       } else if (name.equals("pertarget")) {
+                               return parsePerObject(false);
+                       } else if (name.equals("percflow")) {
+                               return parsePerCflow(false);
+                       } else if (name.equals("percflowbelow")) {
+                               return parsePerCflow(true);
+                       } else if (name.equals("pertypewithin")) { // PTWIMPL Parse the pertypewithin clause
+                               return parsePerTypeWithin();
+                       } else {
+                               return null;
+                       }
+               }
+               return null;
+       }
+
+       private PerClause parsePerCflow(boolean isBelow) {
+               parseIdentifier();
+               eat("(");
+               Pointcut entry = parsePointcut();
+               eat(")");
+               return new PerCflow(entry, isBelow);
+       }
+
+
+       private PerClause parsePerObject(boolean isThis) {
+               parseIdentifier();
+               eat("(");
+               Pointcut entry = parsePointcut();
+               eat(")");
+               return new PerObject(entry, isThis);
+       }
+       
+       private PerClause parsePerTypeWithin() {
+               parseIdentifier();
+               eat("(");
+               TypePattern withinTypePattern = parseTypePattern();
+               eat(")");
+               return new PerTypeWithin(withinTypePattern);
+       }
+
+
+       private PerClause parsePerSingleton() {
+               parseIdentifier();
+               eat("(");
+               eat(")");
+               return new PerSingleton();
+       }
+
+
+       public Declare parseDeclare() {
+               int startPos = tokenSource.peek().getStart();
+               
+               eatIdentifier("declare");
+               String kind = parseIdentifier();
+               Declare ret;
+               if (kind.equals("error")) {
+                       eat(":");
+                       ret = parseErrorOrWarning(true);
+               } else if (kind.equals("warning")) {
+                       eat(":");
+                       ret = parseErrorOrWarning(false);
+               } else if (kind.equals("precedence")) {
+                       eat(":");
+                       ret = parseDominates();
+               } else if (kind.equals("dominates")) {
+                       throw new ParserException("name changed to declare precedence", tokenSource.peek(-2));
+               } else if (kind.equals("parents")) {
+                       ret = parseParents();
+               } else if (kind.equals("soft")) {
+                       eat(":");
+                       ret = parseSoft();
+               } else {
+                       throw new ParserException("expected one of error, warning, parents, soft, precedence, @type, @method, @constructor, @field",
+                               tokenSource.peek(-1));
+               }
+           int endPos = tokenSource.peek(-1).getEnd();
+               ret.setLocation(sourceContext, startPos, endPos);
+               return ret;
+       }
+       
+       public Declare parseDeclareAnnotation() {
+               int startPos = tokenSource.peek().getStart();
+               
+               eatIdentifier("declare");
+               eat("@");
+               String kind = parseIdentifier();
+               eat(":");
+               Declare ret;
+               if (kind.equals("type")) {
+                       ret = parseDeclareAtType();
+               } else if (kind.equals("method")) {
+                       ret = parseDeclareAtMethod(true);
+               } else if (kind.equals("field")) {
+                       ret = parseDeclareAtField();                    
+               } else if (kind.equals("constructor")) {
+                       ret = parseDeclareAtMethod(false);                      
+               } else {
+                       throw new ParserException("one of type, method, field, constructor",tokenSource.peek(-1));
+               }
+               eat(";");
+           int endPos = tokenSource.peek(-1).getEnd();
+               ret.setLocation(sourceContext, startPos, endPos);
+               return ret;
+               
+       }
+       
+       public DeclareAnnotation parseDeclareAtType() {
+               allowHasTypePatterns = true;
+               TypePattern p = parseTypePattern();
+               allowHasTypePatterns = false;
+               return new DeclareAnnotation(DeclareAnnotation.AT_TYPE,p);
+       }
+
+       public DeclareAnnotation parseDeclareAtMethod(boolean isMethod) {
+               SignaturePattern sp = parseMethodOrConstructorSignaturePattern();
+               boolean isConstructorPattern = (sp.getKind() == Member.CONSTRUCTOR);
+               if (isMethod && isConstructorPattern) {
+                               throw new ParserException("method signature pattern",tokenSource.peek(-1));
+               }
+               if (!isMethod && !isConstructorPattern) {
+                       throw new ParserException("constructor signature pattern",tokenSource.peek(-1));
+               }
+               if (isConstructorPattern) return new DeclareAnnotation(DeclareAnnotation.AT_CONSTRUCTOR,sp);
+               else                      return new DeclareAnnotation(DeclareAnnotation.AT_METHOD,sp);
+       }
+
+       public DeclareAnnotation parseDeclareAtField() {
+               return new DeclareAnnotation(DeclareAnnotation.AT_FIELD,parseFieldSignaturePattern());          
+       }
+
+       public DeclarePrecedence parseDominates() {
+               List l = new ArrayList();
+               do {
+                       l.add(parseTypePattern());
+               } while (maybeEat(","));
+               
+               return new DeclarePrecedence(l);
+       }
+
+       private Declare parseParents() {
+               /*
+                * simplified design requires use of raw types for declare parents, no generic spec. allowed
+                * String[] typeParameters = maybeParseSimpleTypeVariableList();
+                */
+               eat(":");
+               allowHasTypePatterns = true;
+               TypePattern p = parseTypePattern(false,false);
+               allowHasTypePatterns = false;
+               IToken t = tokenSource.next();
+               if (!(t.getString().equals("extends") || t.getString().equals("implements"))) {
+                       throw new ParserException("extends or implements", t);
+               }
+               boolean isExtends = t.getString().equals("extends");
+               
+               List l = new ArrayList();
+               do {
+                       l.add(parseTypePattern());
+               } while (maybeEat(","));
+               
+               //XXX somewhere in the chain we need to enforce that we have only ExactTypePatterns
+               
+               DeclareParents decp = new DeclareParents(p, l,isExtends);
+               return decp;
+       }
+
+       private Declare parseSoft() {
+               TypePattern p = parseTypePattern();
+               eat(":");
+               Pointcut pointcut = parsePointcut();
+               return new DeclareSoft(p, pointcut);
+       }
+
+
+
+       private Declare parseErrorOrWarning(boolean isError) {
+               Pointcut pointcut = parsePointcut();
+               eat(":");
+               String message = parsePossibleStringSequence(true);
+               return new DeclareErrorOrWarning(isError, pointcut, message);
+       }
+
+       public Pointcut parsePointcut() {
+               Pointcut p = parseAtomicPointcut(); 
+               if (maybeEat("&&")) {
+                       p = new AndPointcut(p, parseNotOrPointcut());
+               }  
+               
+               if (maybeEat("||")) {
+                       p = new OrPointcut(p, parsePointcut());
+               }
+
+               return p;
+       }
+       
+       private Pointcut parseNotOrPointcut() {
+               Pointcut p = parseAtomicPointcut();
+               if (maybeEat("&&")) {                   
+                       p = new AndPointcut(p, parsePointcut());
+               } 
+               return p;               
+       }
+       
+       private Pointcut parseAtomicPointcut() {
+               if (maybeEat("!")) {
+                       int startPos = tokenSource.peek(-1).getStart();
+                       Pointcut p = new NotPointcut(parseAtomicPointcut(), startPos);
+                       return p;                       
+               }
+               if (maybeEat("(")) {
+                       Pointcut p = parsePointcut();
+                       eat(")");
+                       return p;
+               }
+               if (maybeEat("@")) {
+                       int startPos = tokenSource.peek().getStart();
+                       Pointcut p = parseAnnotationPointcut();
+                   int endPos = tokenSource.peek(-1).getEnd();
+                   p.setLocation(sourceContext, startPos, endPos);
+                       return p;
+               }
+               int startPos = tokenSource.peek().getStart();
+           Pointcut p = parseSinglePointcut();
+           int endPos = tokenSource.peek(-1).getEnd();
+           p.setLocation(sourceContext, startPos, endPos);
+           return p;
+       }
+       
+       
+
+       public Pointcut parseSinglePointcut() {         
+               int start = tokenSource.getIndex();
+               IToken t = tokenSource.peek();
+               Pointcut p = t.maybeGetParsedPointcut();
+               if (p != null) {
+                       tokenSource.next();
+                       return p;
+               }
+               
+               String kind = parseIdentifier();
+//             IToken possibleTypeVariableToken = tokenSource.peek();
+//             String[] typeVariables = maybeParseSimpleTypeVariableList();
+               if (kind.equals("execution") || kind.equals("call") || 
+                       kind.equals("get") || kind.equals("set")) {
+                       p = parseKindedPointcut(kind);
+               } else if (kind.equals("args")) {
+                       p = parseArgsPointcut();
+               } else if (kind.equals("this")) {
+                       p = parseThisOrTargetPointcut(kind);
+               } else if (kind.equals("target")) {
+                       p = parseThisOrTargetPointcut(kind);                    
+               } else if (kind.equals("within")) {
+                       p = parseWithinPointcut();
+               } else if (kind.equals("withincode")) {
+                       p = parseWithinCodePointcut();
+               } else if (kind.equals("cflow")) {
+                       p = parseCflowPointcut(false);
+               } else if (kind.equals("cflowbelow")) {
+                       p = parseCflowPointcut(true);
+               } else  if (kind.equals("adviceexecution")) {
+                       eat("(");
+                       eat(")");
+                       p = new KindedPointcut(Shadow.AdviceExecution,
+                               new SignaturePattern(Member.ADVICE, ModifiersPattern.ANY, 
+                                       TypePattern.ANY, TypePattern.ANY, NamePattern.ANY, 
+                                       TypePatternList.ANY, 
+                                       ThrowsPattern.ANY,
+                                       AnnotationTypePattern.ANY));
+               } else  if (kind.equals("handler")) {
+                       eat("(");
+                       TypePattern typePat = parseTypePattern(false,false);
+                       eat(")");
+                       p = new HandlerPointcut(typePat);
+               } else  if (kind.equals("lock") || kind.equals("unlock")) {
+                       p = parseMonitorPointcut(kind);
+               } else  if (kind.equals("initialization")) {
+                       eat("(");
+                       SignaturePattern sig = parseConstructorSignaturePattern();
+                       eat(")");
+                       p = new KindedPointcut(Shadow.Initialization, sig);
+               } else  if (kind.equals("staticinitialization")) {
+                       eat("(");
+                       TypePattern typePat = parseTypePattern(false,false);
+                       eat(")");
+                       p = new KindedPointcut(Shadow.StaticInitialization,
+                                       new SignaturePattern(Member.STATIC_INITIALIZATION, ModifiersPattern.ANY, 
+                                       TypePattern.ANY, typePat, NamePattern.ANY, TypePatternList.EMPTY, 
+                                       ThrowsPattern.ANY,AnnotationTypePattern.ANY));
+               }  else  if (kind.equals("preinitialization")) {
+                       eat("(");
+                       SignaturePattern sig = parseConstructorSignaturePattern();
+                       eat(")");
+                       p = new KindedPointcut(Shadow.PreInitialization, sig);
+               } else  if (kind.equals("if")) {
+                       // @style support allows if(), if(true), if(false)      
+                       eat("(");
+                       if (maybeEatIdentifier("true")) {
+                               eat(")");
+                               p = new IfPointcut.IfTruePointcut();
+                       } else if (maybeEatIdentifier("false")) {
+                           eat(")");
+                               p = new IfPointcut.IfFalsePointcut();
+                       } else {
+                               eat(")");
+                               // TODO - Alex has some token stuff going on here to get a readable name in place of ""...
+                               p = new IfPointcut("");
+                       }
+               } 
+               else {
+                       boolean matchedByExtensionDesignator = false;
+                       // see if a registered handler wants to parse it, otherwise
+                       // treat as a reference pointcut
+                       for (Iterator iter = this.pointcutDesignatorHandlers.iterator(); iter.hasNext();) {
+                               PointcutDesignatorHandler pcd = (PointcutDesignatorHandler) iter.next();
+                               if (pcd.getDesignatorName().equals(kind)) {
+                                       p = parseDesignatorPointcut(pcd);
+                                       matchedByExtensionDesignator = true;
+                               }
+                               
+                       }
+                       if (!matchedByExtensionDesignator) {
+                               tokenSource.setIndex(start);
+                               p = parseReferencePointcut();
+                       }
+               }
+               return p;
+       }
+
+       private void assertNoTypeVariables(String[] tvs, String errorMessage,IToken token) {
+               if ( tvs != null ) throw new ParserException(errorMessage,token);
+       }
+       
+       public Pointcut parseAnnotationPointcut() {             
+               int start = tokenSource.getIndex();
+               IToken t = tokenSource.peek();
+               String kind = parseIdentifier();
+               IToken possibleTypeVariableToken = tokenSource.peek();
+               String[] typeVariables = maybeParseSimpleTypeVariableList();
+               if (typeVariables != null) {
+                       String message = "(";
+                       assertNoTypeVariables(typeVariables, message, possibleTypeVariableToken);
+               }
+               tokenSource.setIndex(start);
+               if (kind.equals("annotation")) {
+                       return parseAtAnnotationPointcut();
+               } else if (kind.equals("args")) {
+                       return parseArgsAnnotationPointcut();
+               } else if (kind.equals("this") || kind.equals("target")) {
+                       return parseThisOrTargetAnnotationPointcut();
+               } else if (kind.equals("within")) {
+                       return parseWithinAnnotationPointcut();
+               } else if (kind.equals("withincode")) {
+                       return parseWithinCodeAnnotationPointcut();
+               } throw new ParserException("pointcut name", t);
+       }
+       
+       private Pointcut parseAtAnnotationPointcut() {
+               parseIdentifier();
+               eat("(");
+               if (maybeEat(")")) {
+                       throw new ParserException("@AnnotationName or parameter", tokenSource.peek());
+               }
+               ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern(); 
+               eat(")");
+               return new AnnotationPointcut(type);
+       }
+
+       
+       private SignaturePattern parseConstructorSignaturePattern() {
+               SignaturePattern ret = parseMethodOrConstructorSignaturePattern();
+               if (ret.getKind() == Member.CONSTRUCTOR) return ret;
+               
+               throw new ParserException("constructor pattern required, found method pattern",
+                               ret);
+       }
+
+       
+       private Pointcut parseWithinCodePointcut() {
+               //parseIdentifier();
+               eat("(");
+               SignaturePattern sig = parseMethodOrConstructorSignaturePattern();
+               eat(")");
+               return new WithincodePointcut(sig);
+       }
+
+       private Pointcut parseCflowPointcut(boolean isBelow) {
+               //parseIdentifier();
+               eat("(");
+               Pointcut entry = parsePointcut();
+               eat(")");
+               return new CflowPointcut(entry, isBelow, null);
+       }
+
+       /**
+        * Method parseWithinPointcut.
+        * @return Pointcut
+        */
+       private Pointcut parseWithinPointcut() {
+               //parseIdentifier();
+               eat("(");
+               TypePattern type = parseTypePattern();
+               eat(")");
+               return new WithinPointcut(type);
+       }
+
+
+       /**
+        * Method parseThisOrTargetPointcut.
+        * @return Pointcut
+        */
+       private Pointcut parseThisOrTargetPointcut(String kind) {
+               eat("(");
+               TypePattern type = parseTypePattern();
+               eat(")");
+               return new ThisOrTargetPointcut(kind.equals("this"), type);
+       }
+
+       private Pointcut parseThisOrTargetAnnotationPointcut() {
+               String kind = parseIdentifier();
+               eat("(");
+               if (maybeEat(")")) {
+                       throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek());
+               }
+               ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern(); 
+               eat(")");
+               return new ThisOrTargetAnnotationPointcut(kind.equals("this"),type);            
+       }
+
+       private Pointcut parseWithinAnnotationPointcut() {
+               /* String kind = */parseIdentifier();
+               eat("(");
+               if (maybeEat(")")) {
+                       throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek());
+               }
+               AnnotationTypePattern type = parseAnnotationNameOrVarTypePattern(); 
+               eat(")");
+               return new WithinAnnotationPointcut(type);              
+       }
+
+       private Pointcut parseWithinCodeAnnotationPointcut() {
+               /*String kind = */parseIdentifier();
+               eat("(");
+               if (maybeEat(")")) {
+                       throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek());
+               }
+               ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern(); 
+               eat(")");
+               return new WithinCodeAnnotationPointcut(type);          
+       }
+
+       /**
+        * Method parseArgsPointcut.
+        * @return Pointcut
+        */
+       private Pointcut parseArgsPointcut() {
+               //parseIdentifier();
+               TypePatternList arguments = parseArgumentsPattern(false);
+               return new ArgsPointcut(arguments);
+       }
+       
+       private Pointcut parseArgsAnnotationPointcut() {
+               parseIdentifier();
+               AnnotationPatternList arguments = parseArgumentsAnnotationPattern();
+               return new ArgsAnnotationPointcut(arguments);
+       }
+
+       private Pointcut parseReferencePointcut() {
+               TypePattern onType = parseTypePattern();
+               NamePattern name = null;
+               if (onType.typeParameters.size() > 0) {
+                       eat(".");
+                       name = parseNamePattern();
+               } else {
+                       name = tryToExtractName(onType);
+               }
+               if (name == null) {
+               throw new ParserException("name pattern", tokenSource.peek());
+       }
+       if (onType.toString().equals("")) {
+               onType = null;
+       }
+               
+               String simpleName = name.maybeGetSimpleName();
+               if (simpleName ==  null) {
+                       throw new ParserException("(",tokenSource.peek(-1));
+               }
+
+               TypePatternList arguments = parseArgumentsPattern(false);
+               return new ReferencePointcut(onType, simpleName, arguments);
+       }
+       
+       private Pointcut parseDesignatorPointcut(PointcutDesignatorHandler pcdHandler) {
+               eat("(");
+               int parenCount = 1;
+               StringBuffer pointcutBody = new StringBuffer();
+               while (parenCount > 0) {
+                       if (maybeEat("(")) {
+                               parenCount++;
+                               pointcutBody.append("(");
+                       } else if (maybeEat(")")) {
+                               parenCount--;
+                               if (parenCount > 0) {
+                                       pointcutBody.append(")");
+                               }
+                       } else {
+                               pointcutBody.append(nextToken().getString());
+                       }
+               }
+               ContextBasedMatcher pcExpr = pcdHandler.parse(pointcutBody.toString());
+               return new PointcutDesignatorHandlerBasedPointcut(pcExpr,world);
+       }
+
+
+       public List parseDottedIdentifier() {
+               List ret = new ArrayList();
+               ret.add(parseIdentifier());
+               while (maybeEat(".")) {
+                       ret.add(parseIdentifier());
+               }
+               return ret;
+       }
+
+
+       
+       private KindedPointcut parseKindedPointcut(String kind) {
+               eat("(");
+               SignaturePattern sig;
+
+               Shadow.Kind shadowKind = null;
+               if (kind.equals("execution")) {
+                       sig = parseMethodOrConstructorSignaturePattern();
+                       if (sig.getKind() == Member.METHOD) {
+                               shadowKind = Shadow.MethodExecution;
+                       } else if (sig.getKind() == Member.CONSTRUCTOR) {
+                               shadowKind = Shadow.ConstructorExecution;
+                       }          
+               } else if (kind.equals("call")) {
+                       sig = parseMethodOrConstructorSignaturePattern();
+                       if (sig.getKind() == Member.METHOD) {
+                               shadowKind = Shadow.MethodCall;
+                       } else if (sig.getKind() == Member.CONSTRUCTOR) {
+                               shadowKind = Shadow.ConstructorCall;
+                       }                 
+               } else if (kind.equals("get")) {
+                       sig = parseFieldSignaturePattern();
+                       shadowKind = Shadow.FieldGet;
+               } else if (kind.equals("set")) {
+                       sig = parseFieldSignaturePattern();
+                       shadowKind = Shadow.FieldSet;
+               } else {
+                       throw new ParserException("bad kind: " + kind, tokenSource.peek());
+               }
+               eat(")");
+               return new KindedPointcut(shadowKind, sig);
+       }
+       
+       /** Covers the 'lock()' and 'unlock()' pointcuts */
+       private KindedPointcut parseMonitorPointcut(String kind) {
+               eat("(");
+//             TypePattern type = TypePattern.ANY;
+               eat(")");
+               
+               if (kind.equals("lock")) {
+                       return new KindedPointcut(Shadow.SynchronizationLock,
+                                   new SignaturePattern(Member.MONITORENTER, ModifiersPattern.ANY, 
+                                               TypePattern.ANY, 
+                                               TypePattern.ANY,
+//                                             type,
+                                               NamePattern.ANY, 
+                                               TypePatternList.ANY, 
+                                               ThrowsPattern.ANY,
+                                               AnnotationTypePattern.ANY));
+               } else {
+                       return new KindedPointcut(Shadow.SynchronizationUnlock,
+                                   new SignaturePattern(Member.MONITORENTER, ModifiersPattern.ANY, 
+                                               TypePattern.ANY, 
+                                               TypePattern.ANY, 
+//                                             type,
+                                               NamePattern.ANY, 
+                                               TypePatternList.ANY, 
+                                               ThrowsPattern.ANY,
+                                               AnnotationTypePattern.ANY));
+               }
+       }
+       
+       public TypePattern parseTypePattern() {
+               return parseTypePattern(false,false);
+       }
+       
+       public TypePattern parseTypePattern(boolean insideTypeParameters,boolean parameterAnnotationsPossible) {
+               TypePattern p = parseAtomicTypePattern(insideTypeParameters,parameterAnnotationsPossible); 
+               if (maybeEat("&&")) {
+                       p = new AndTypePattern(p, parseNotOrTypePattern(insideTypeParameters,parameterAnnotationsPossible));
+               }  
+               
+               if (maybeEat("||")) {
+                       p = new OrTypePattern(p, parseTypePattern(insideTypeParameters,parameterAnnotationsPossible));
+               }               
+               return p;
+       }
+       
+       private TypePattern parseNotOrTypePattern(boolean insideTypeParameters,boolean parameterAnnotationsPossible) {
+               TypePattern p = parseAtomicTypePattern(insideTypeParameters,parameterAnnotationsPossible);
+               if (maybeEat("&&")) {                   
+                       p = new AndTypePattern(p, parseTypePattern(insideTypeParameters,parameterAnnotationsPossible));
+               } 
+               return p;               
+       }
+       
+       
+       // Need to differentiate in here between two kinds of annotation pattern - depending on where the ( is
+       
+       private TypePattern parseAtomicTypePattern(boolean insideTypeParameters,boolean parameterAnnotationsPossible) {
+               AnnotationTypePattern ap = maybeParseAnnotationPattern(); // might be parameter annotation pattern or type annotation pattern
+               if (maybeEat("!")) {
+                       //int startPos = tokenSource.peek(-1).getStart();
+                       //??? we lose source location for true start of !type
+                       
+                       // An annotation, if processed, is outside of the Not - so here we have to build
+                       // an And pattern containing the annotation and the not as left and right children
+                       // *unless* the annotation pattern was just 'Any' then we can skip building the 
+                       // And and just return the Not directly (pr228980)
+                   TypePattern p = null;
+            TypePattern tp = parseAtomicTypePattern(insideTypeParameters,parameterAnnotationsPossible);
+                   if (!(ap instanceof AnyAnnotationTypePattern)) {
+                       p = new NotTypePattern(tp);
+                       p = new AndTypePattern(setAnnotationPatternForTypePattern(TypePattern.ANY,ap,false),p);
+                   } else {
+                       p = new NotTypePattern(tp);
+                   }
+                       return p;                       
+               }
+               if (maybeEat("(")) {
+                       TypePattern p = parseTypePattern(insideTypeParameters,false);
+                       if ((p instanceof NotTypePattern) && !(ap instanceof AnyAnnotationTypePattern)) {
+                           // dont set the annotation on it, we don't want the annotation to be 
+                           // considered as part of the not, it is outside the not (pr228980)
+                           TypePattern tp = setAnnotationPatternForTypePattern(TypePattern.ANY, ap, parameterAnnotationsPossible);
+                           p = new AndTypePattern(tp,p);
+                       } else {
+                           p = setAnnotationPatternForTypePattern(p,ap,parameterAnnotationsPossible);
+                       }
+                       eat(")");
+                       boolean isVarArgs = maybeEat("...");
+                       if (isVarArgs) p.setIsVarArgs(isVarArgs);
+                       boolean isIncludeSubtypes = maybeEat("+");
+                       if (isIncludeSubtypes) p.includeSubtypes = true;  // need the test because (A+) should not set subtypes to false!
+                       return p;
+               }
+               int startPos = tokenSource.peek().getStart();
+           TypePattern p = parseSingleTypePattern(insideTypeParameters);
+           int endPos = tokenSource.peek(-1).getEnd();
+           p = setAnnotationPatternForTypePattern(p,ap,false);
+           p.setLocation(sourceContext, startPos, endPos);
+           return p;
+       }
+       
+
+       private TypePattern setAnnotationPatternForTypePattern(TypePattern t, AnnotationTypePattern ap,boolean parameterAnnotationsPattern) {
+               TypePattern ret = t;
+               if (parameterAnnotationsPattern) ap.setForParameterAnnotationMatch();
+               if (ap != AnnotationTypePattern.ANY) {
+                       if (t == TypePattern.ANY) {
+                               ret = new WildTypePattern(new NamePattern[] {NamePattern.ANY},false,0,false,null);
+                       }
+                       if (t.annotationPattern == AnnotationTypePattern.ANY) {
+                               ret.setAnnotationTypePattern(ap);                               
+                       } else {
+                               ret.setAnnotationTypePattern(new AndAnnotationTypePattern(ap,t.annotationPattern)); //???
+                       }
+               }
+               return ret;
+       }
+       
+       public AnnotationTypePattern maybeParseAnnotationPattern() {
+               AnnotationTypePattern ret = AnnotationTypePattern.ANY;
+               AnnotationTypePattern nextPattern = null;
+               while ((nextPattern = maybeParseSingleAnnotationPattern()) != null) {
+                       if (ret == AnnotationTypePattern.ANY) {
+                               ret = nextPattern;
+                       } else {
+                               ret = new AndAnnotationTypePattern(ret,nextPattern);
+                       }
+               }
+               return ret;
+       }
+
+       // PVAL cope with annotation values at other places in this code
+       public AnnotationTypePattern maybeParseSingleAnnotationPattern() {
+               AnnotationTypePattern ret = null;
+               Map values = null;
+               // LALR(2) - fix by making "!@" a single token
+               int startIndex = tokenSource.getIndex();
+               if (maybeEat("!")) {
+                       if (maybeEat("@")) {
+                               if (maybeEat("(")) {
+                                       TypePattern p = parseTypePattern();
+                                       ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p));
+                                       eat(")");
+                                       return ret;
+                               } else {
+                                       TypePattern p = parseSingleTypePattern();
+                                       if (maybeEatAdjacent("(")) {
+                                               values = parseAnnotationValues();
+                                               eat(")");
+                                               ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p,values));
+                                       } else {
+                                               ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p));                                           
+                                       }
+                                       return ret;
+                               }
+                       } else {
+                               tokenSource.setIndex(startIndex); // not for us!
+                               return ret;
+                       }
+               }
+               if (maybeEat("@")) {
+                       if (maybeEat("(")) {
+                               TypePattern p = parseTypePattern();
+                               ret = new WildAnnotationTypePattern(p);
+                               eat(")");
+                               return ret;
+                       } else {
+                               TypePattern p = parseSingleTypePattern();
+                               if (maybeEatAdjacent("(")) {
+                                       values = parseAnnotationValues();
+                                       eat(")");
+                                       ret = new WildAnnotationTypePattern(p,values);
+                               } else {
+                                       ret = new WildAnnotationTypePattern(p);
+                               }
+                               return ret;
+                       }
+               } else {
+                       tokenSource.setIndex(startIndex); // not for us!
+                       return ret;
+               }               
+       }
+       
+       // Parse annotation values.  In an expression in @A(a=b,c=d) this method will be 
+       // parsing the a=b,c=d.)
+       public Map/*String,String*/ parseAnnotationValues() {
+               Map values = new HashMap();
+               boolean seenDefaultValue = false;
+               do {
+                       String possibleKeyString = parseAnnotationNameValuePattern();
+                       if (possibleKeyString==null) {
+                               throw new ParserException("expecting simple literal ",tokenSource.peek(-1));
+                       }
+                       // did they specify just a single entry 'v'  or a keyvalue pair 'k=v'
+                       if (maybeEat("=")) { 
+                               // it was a key!
+                               String valueString = parseAnnotationNameValuePattern();
+                               if (valueString==null) {
+                                       throw new ParserException("expecting simple literal ",tokenSource.peek(-1));
+                               }
+                               values.put(possibleKeyString,valueString);
+                       } else {
+                               if (seenDefaultValue) {
+                                       throw new ParserException("cannot specify two default values",tokenSource.peek(-1));
+                               }
+                               seenDefaultValue = true;
+                               values.put("value",possibleKeyString);
+                       }
+               } while (maybeEat(",")); // keep going whilst there are ','
+               return values;
+       }
+       
+       public TypePattern parseSingleTypePattern() {
+               return parseSingleTypePattern(false);
+       }
+       
+       public TypePattern parseSingleTypePattern(boolean insideTypeParameters) {
+               if (insideTypeParameters && maybeEat("?")) return parseGenericsWildcardTypePattern();
+               if (allowHasTypePatterns) {
+                       if (maybeEatIdentifier("hasmethod")) return parseHasMethodTypePattern();
+                       if (maybeEatIdentifier("hasfield")) return parseHasFieldTypePattern();
+               }
+               
+               List names = parseDottedNamePattern(); 
+               
+               int dim = 0;
+               while (maybeEat("[")) {
+                       eat("]");
+                       dim++;
+               }
+               
+               TypePatternList typeParameters = maybeParseTypeParameterList();
+               int endPos = tokenSource.peek(-1).getEnd();
+
+        boolean isVarArgs = maybeEat("...");
+
+               boolean includeSubtypes = maybeEat("+");
+
+               //??? what about the source location of any's????
+               if (names.size() == 1 && ((NamePattern)names.get(0)).isAny() && 
+                               dim == 0 && !isVarArgs && typeParameters == null ) return TypePattern.ANY;
+               
+               // Notice we increase the dimensions if varargs is set.  this is to allow type matching to
+               // succeed later: The actual signature at runtime of a method declared varargs is an array type of
+               // the original declared type (so Integer... becomes Integer[] in the bytecode).  So, here for the
+               // pattern 'Integer...' we create a WildTypePattern 'Integer[]' with varargs set.  If this matches
+               // during shadow matching, we confirm that the varargs flags match up before calling it a successful
+               // match.
+               return new WildTypePattern(names, includeSubtypes, dim+(isVarArgs?1:0), endPos,isVarArgs,typeParameters);
+       }
+       
+       public TypePattern parseHasMethodTypePattern() {
+               int startPos = tokenSource.peek(-1).getStart();
+               eat("(");
+               SignaturePattern sp = parseMethodOrConstructorSignaturePattern();
+               eat(")");
+           int endPos = tokenSource.peek(-1).getEnd();
+               HasMemberTypePattern ret = new HasMemberTypePattern(sp);
+               ret.setLocation(sourceContext, startPos, endPos);
+               return ret;
+       }
+       
+       public TypePattern parseHasFieldTypePattern() {
+               int startPos = tokenSource.peek(-1).getStart();
+               eat("(");
+               SignaturePattern sp = parseFieldSignaturePattern();
+               eat(")");
+           int endPos = tokenSource.peek(-1).getEnd();
+               HasMemberTypePattern ret = new HasMemberTypePattern(sp);
+               ret.setLocation(sourceContext, startPos, endPos);
+               return ret;
+       }
+       
+       public TypePattern parseGenericsWildcardTypePattern() {
+               List names = new ArrayList();
+               names.add(new NamePattern("?"));
+               TypePattern upperBound = null;
+               TypePattern[] additionalInterfaceBounds = new TypePattern[0];
+               TypePattern lowerBound = null;
+               if (maybeEatIdentifier("extends")) {
+                       upperBound = parseTypePattern(false,false);
+                       additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds();
+               }
+               if (maybeEatIdentifier("super")) {
+                       lowerBound = parseTypePattern(false,false);
+               }
+               int endPos = tokenSource.peek(-1).getEnd();
+               return new WildTypePattern(names,false,0,endPos,false,null,upperBound,additionalInterfaceBounds,lowerBound);
+       }
+       
+//     private AnnotationTypePattern completeAnnotationPattern(AnnotationTypePattern p) {
+//             if (maybeEat("&&")) {
+//                     return new AndAnnotationTypePattern(p,parseNotOrAnnotationPattern());
+//             }
+//             if (maybeEat("||")) {
+//                     return new OrAnnotationTypePattern(p,parseAnnotationTypePattern());
+//             }
+//             return p;
+//     }
+//
+//     protected AnnotationTypePattern parseAnnotationTypePattern() {
+//             AnnotationTypePattern ap = parseAtomicAnnotationPattern();
+//             if (maybeEat("&&")) {
+//                     ap = new AndAnnotationTypePattern(ap, parseNotOrAnnotationPattern());
+//             }  
+//             
+//             if (maybeEat("||")) {
+//                     ap = new OrAnnotationTypePattern(ap, parseAnnotationTypePattern());
+//             }               
+//             return ap;
+//     }
+//
+//     private AnnotationTypePattern parseNotOrAnnotationPattern() {
+//             AnnotationTypePattern p = parseAtomicAnnotationPattern();
+//             if (maybeEat("&&")) {
+//                     p = new AndAnnotationTypePattern(p,parseAnnotationTypePattern());
+//             }
+//             return p;
+//     }
+       
+       
+       protected ExactAnnotationTypePattern parseAnnotationNameOrVarTypePattern() {
+               ExactAnnotationTypePattern p = null;
+               int startPos = tokenSource.peek().getStart();
+               if (maybeEat("@")) {
+                       throw new ParserException("@Foo form was deprecated in AspectJ 5 M2: annotation name or var ",tokenSource.peek(-1));
+               }
+               p = parseSimpleAnnotationName();
+               int endPos = tokenSource.peek(-1).getEnd();
+               p.setLocation(sourceContext,startPos,endPos);
+               // For optimized syntax that allows binding directly to annotation values (pr234943)
+         if (maybeEat("(")) {
+            String formalName = parseIdentifier();
+            p = new ExactAnnotationFieldTypePattern(p, formalName);
+            eat(")");
+        }
+        return p;
+    }
+
+    /**
+     * @return
+        */
+       private ExactAnnotationTypePattern parseSimpleAnnotationName() {
+               // the @ has already been eaten...
+               ExactAnnotationTypePattern p;
+               StringBuffer annotationName = new StringBuffer();
+               annotationName.append(parseIdentifier());
+               while (maybeEat(".")) {
+                       annotationName.append('.');
+                       annotationName.append(parseIdentifier());
+               }
+               UnresolvedType type = UnresolvedType.forName(annotationName.toString());
+               p = new ExactAnnotationTypePattern(type,null);
+               return p;
+       }
+
+//     private AnnotationTypePattern parseAtomicAnnotationPattern() {
+//             if (maybeEat("!")) {
+//                     //int startPos = tokenSource.peek(-1).getStart();
+//                     //??? we lose source location for true start of !type
+//                     AnnotationTypePattern p = new NotAnnotationTypePattern(parseAtomicAnnotationPattern());
+//                     return p;                       
+//             }
+//             if (maybeEat("(")) {
+//                     AnnotationTypePattern p = parseAnnotationTypePattern();
+//                     eat(")");
+//                     return p;
+//             }
+//             int startPos = tokenSource.peek().getStart();
+//             eat("@");
+//             StringBuffer annotationName = new StringBuffer();
+//             annotationName.append(parseIdentifier());
+//             while (maybeEat(".")) {
+//                     annotationName.append('.');
+//                     annotationName.append(parseIdentifier());
+//             }
+//             UnresolvedType type = UnresolvedType.forName(annotationName.toString());
+//             AnnotationTypePattern p = new ExactAnnotationTypePattern(type);
+//         int endPos = tokenSource.peek(-1).getEnd();
+//         p.setLocation(sourceContext, startPos, endPos);
+//         return p;           
+//     }
+       
+
+       public List parseDottedNamePattern() {
+               List names = new ArrayList();
+               StringBuffer buf = new StringBuffer();
+               IToken previous = null;
+               boolean justProcessedEllipsis = false; // Remember if we just dealt with an ellipsis (PR61536)
+               boolean justProcessedDot = false; 
+               boolean onADot = false;
+
+               while (true) {
+                       IToken tok = null;
+                       int startPos = tokenSource.peek().getStart();
+                       String afterDot = null;
+                       while (true) {
+                               if (previous !=null && previous.getString().equals(".")) justProcessedDot = true;
+                               tok = tokenSource.peek();
+                               onADot = (tok.getString().equals("."));
+                               if (previous != null) {
+                                       if (!isAdjacent(previous, tok)) break;
+                               }
+                               if (tok.getString() == "*" || (tok.isIdentifier() && tok.getString()!="...")) {
+                                       buf.append(tok.getString());
+                               } else if (tok.getString()=="...") {
+                                       break;
+                               } else if (tok.getLiteralKind() != null) {
+                                       //System.err.println("literal kind: " + tok.getString());
+                                       String s = tok.getString();
+                                       int dot = s.indexOf('.');
+                                       if (dot != -1) {
+                                               buf.append(s.substring(0, dot));
+                                               afterDot = s.substring(dot+1);
+                                               previous = tokenSource.next();
+                                               break;
+                                       }
+                                       buf.append(s);  // ??? so-so
+                               } else {
+                                       break;
+                               }
+                               previous = tokenSource.next();
+                               //XXX need to handle floats and other fun stuff
+                       }
+                       int endPos = tokenSource.peek(-1).getEnd();
+                       if (buf.length() == 0 && names.isEmpty()) {
+                               throw new ParserException("name pattern", tok);
+                       } 
+                       
+                       if (buf.length() == 0 && justProcessedEllipsis) {
+                               throw new ParserException("name pattern cannot finish with ..", tok);
+                       }
+                       if (buf.length() == 0 && justProcessedDot && !onADot) {
+                                       throw new ParserException("name pattern cannot finish with .", tok);
+                       }
+                       
+                       if (buf.length() == 0) {
+                               names.add(NamePattern.ELLIPSIS);
+                               justProcessedEllipsis = true;
+                       } else {
+                               checkLegalName(buf.toString(), previous);
+                               NamePattern ret = new NamePattern(buf.toString());
+                               ret.setLocation(sourceContext, startPos, endPos);
+                               names.add(ret);
+                               justProcessedEllipsis = false;
+                       }
+                       
+                       if (afterDot == null) {
+                               buf.setLength(0);
+                               // no elipsis or dotted name part
+                if (!maybeEat(".")) break;
+                // go on
+                               else previous = tokenSource.peek(-1);
+                       } else {
+                               buf.setLength(0);
+                               buf.append(afterDot);
+                               afterDot = null;
+                       }
+               }
+               //System.err.println("parsed: " + names);
+               return names;
+       }
+       
+       // supported form 'a.b.c.d' or just 'a'
+       public String parseAnnotationNameValuePattern() {
+               StringBuffer buf = new StringBuffer();
+               IToken tok;
+//             int startPos = 
+                       tokenSource.peek().getStart();
+               boolean dotOK = false;
+               int depth = 0;
+               while (true) {
+                       tok = tokenSource.peek();
+                       // keep going until we hit ')' or '=' or ','
+                       if (tok.getString()==")" && depth==0) break;
+                       if (tok.getString()=="=" && depth==0) break;
+                       if (tok.getString()=="," && depth==0) break;
+                       
+                       // keep track of nested brackets
+                       if (tok.getString()=="(") depth++;
+                       if (tok.getString()==")") depth--;
+                       if (tok.getString()=="{") depth++;
+                       if (tok.getString()=="}") depth--;
+
+                       if (tok.getString()=="." && !dotOK) {
+                               throw new ParserException("dot not expected",tok);
+                       }
+                       buf.append(tok.getString());
+                       tokenSource.next();
+                       dotOK=true;
+               }
+               if (buf.length()==0) return null;
+               else                 return buf.toString();
+       }
+       
+       
+       public NamePattern parseNamePattern() {
+               StringBuffer buf = new StringBuffer();
+               IToken previous = null;
+               IToken tok;
+               int startPos = tokenSource.peek().getStart();
+               while (true) {
+                       tok = tokenSource.peek();
+                       if (previous != null) {
+                               if (!isAdjacent(previous, tok)) break;
+                       }
+                       if (tok.getString() == "*" || tok.isIdentifier()) {
+                               buf.append(tok.getString());
+                       } else if (tok.getLiteralKind() != null) {
+                               //System.err.println("literal kind: " + tok.getString());
+                               String s = tok.getString();
+                               if (s.indexOf('.') != -1) break;
+                               buf.append(s);  // ??? so-so
+                       } else {
+                               break;
+                       }
+                       previous = tokenSource.next();
+                       //XXX need to handle floats and other fun stuff
+               }
+               int endPos = tokenSource.peek(-1).getEnd();
+               if (buf.length() == 0) {
+                       throw new ParserException("name pattern", tok);
+               } 
+               
+               checkLegalName(buf.toString(), previous);
+               NamePattern ret = new NamePattern(buf.toString());
+               ret.setLocation(sourceContext, startPos, endPos);
+               return ret;
+       }
+       
+       private void checkLegalName(String s, IToken tok) {
+               char ch = s.charAt(0);
+               if (!(ch == '*' || Character.isJavaIdentifierStart(ch))) {
+                       throw new ParserException("illegal identifier start (" + ch + ")", tok);
+               }
+               
+               for (int i=1, len=s.length(); i < len; i++) {
+                       ch = s.charAt(i);
+                       if (!(ch == '*' || Character.isJavaIdentifierPart(ch))) {
+                               throw new ParserException("illegal identifier character (" + ch + ")", tok);
+                       }
+               }
+               
+       }
+
+
+       private boolean isAdjacent(IToken first, IToken second) {
+               return first.getEnd() == second.getStart()-1;
+       }
+
+       
+       public ModifiersPattern parseModifiersPattern() {
+               int requiredFlags = 0;
+               int forbiddenFlags = 0;
+               int start;
+               while (true) {
+                   start = tokenSource.getIndex();
+                   boolean isForbidden = false;
+                   isForbidden = maybeEat("!");
+                   IToken t = tokenSource.next();
+                   int flag = ModifiersPattern.getModifierFlag(t.getString());
+                   if (flag == -1) break;
+                   if (isForbidden) forbiddenFlags |= flag;
+                   else requiredFlags |= flag;
+               }
+               
+               tokenSource.setIndex(start);
+               if (requiredFlags == 0 && forbiddenFlags == 0) {
+                       return ModifiersPattern.ANY;
+               } else {
+                       return new ModifiersPattern(requiredFlags, forbiddenFlags);
+               }
+       }
+       
+       public TypePatternList parseArgumentsPattern(boolean parameterAnnotationsPossible) {
+               List patterns = new ArrayList();
+               eat("(");
+               
+               // ()
+               if (maybeEat(")")) {
+                       return new TypePatternList();
+               }
+               
+               do {
+                       if (maybeEat(".")) { // ..
+                               eat(".");
+                               patterns.add(TypePattern.ELLIPSIS);
+                       } else { 
+                               patterns.add(parseTypePattern(false,parameterAnnotationsPossible));
+                       }
+               } while (maybeEat(","));
+               eat(")");
+               return new TypePatternList(patterns);
+       }
+       
+       public AnnotationPatternList parseArgumentsAnnotationPattern() {
+               List patterns = new ArrayList();
+               eat("(");
+               if (maybeEat(")")) {
+                       return new AnnotationPatternList();
+               }
+               
+               do {
+                       if (maybeEat(".")) {
+                               eat(".");
+                               patterns.add(AnnotationTypePattern.ELLIPSIS);
+                       } else if (maybeEat("*")) {
+                               patterns.add(AnnotationTypePattern.ANY);
+                       } else {
+                               patterns.add(parseAnnotationNameOrVarTypePattern());
+                       }
+               } while (maybeEat(","));
+               eat(")");
+               return new AnnotationPatternList(patterns);
+       }
+       
+       
+       public ThrowsPattern parseOptionalThrowsPattern() {
+               IToken t = tokenSource.peek();
+               if (t.isIdentifier() && t.getString().equals("throws")) {
+                       tokenSource.next();
+                       List required = new ArrayList();
+                       List forbidden = new ArrayList();
+                       do {
+                               boolean isForbidden = maybeEat("!");
+                               //???might want an error for a second ! without a paren
+                               TypePattern p = parseTypePattern();
+                               if (isForbidden) forbidden.add(p);
+                               else required.add(p);
+                       } while (maybeEat(","));
+                       return new ThrowsPattern(new TypePatternList(required), new TypePatternList(forbidden));                
+               }
+               return ThrowsPattern.ANY;
+       }
+       
+       
+       public SignaturePattern parseMethodOrConstructorSignaturePattern() {
+               int startPos = tokenSource.peek().getStart();
+               AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern();
+               ModifiersPattern modifiers = parseModifiersPattern();
+               TypePattern returnType = parseTypePattern(false,false);
+               
+               TypePattern declaringType;
+               NamePattern name = null;
+               MemberKind kind;
+               // here we can check for 'new'
+               if (maybeEatNew(returnType)) {
+                       kind = Member.CONSTRUCTOR;
+                       if (returnType.toString().length() == 0) {
+                               declaringType = TypePattern.ANY;
+                       } else {
+                               declaringType = returnType;
+                       }
+                       returnType = TypePattern.ANY; 
+                       name = NamePattern.ANY;
+               } else {
+                       kind = Member.METHOD;
+                       IToken nameToken = tokenSource.peek();
+                       declaringType = parseTypePattern(false,false);
+                       if (maybeEat(".")) {
+                               nameToken = tokenSource.peek();
+                           name = parseNamePattern();
+                   } else {
+                       name = tryToExtractName(declaringType);
+                       if (declaringType.toString().equals("")) {
+                               declaringType = TypePattern.ANY;
+                       }
+                   }
+               if (name == null) {
+                       throw new ParserException("name pattern", tokenSource.peek());
+               }
+               String simpleName = name.maybeGetSimpleName();
+               //XXX should add check for any Java keywords
+               if (simpleName != null && simpleName.equals("new")) {
+                       throw new ParserException("method name (not constructor)", 
+                                                               nameToken);
+               }
+               }
+               
+               TypePatternList parameterTypes = parseArgumentsPattern(true);
+
+               ThrowsPattern throwsPattern = parseOptionalThrowsPattern();
+               SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType, name, parameterTypes, throwsPattern, annotationPattern);
+           int endPos = tokenSource.peek(-1).getEnd();
+           ret.setLocation(sourceContext, startPos, endPos);
+               return ret;
+       }
+
+       private boolean maybeEatNew(TypePattern returnType) {
+               if (returnType instanceof WildTypePattern) {
+                       WildTypePattern p = (WildTypePattern)returnType;
+                       if (p.maybeExtractName("new")) return true;
+               }
+               int start = tokenSource.getIndex();
+               if (maybeEat(".")) {
+                       String id = maybeEatIdentifier();
+                       if (id != null && id.equals("new")) return true;
+                       tokenSource.setIndex(start);
+               }
+               
+               return false;
+       }
+
+       
+       public SignaturePattern parseFieldSignaturePattern() {
+               int startPos = tokenSource.peek().getStart();
+               
+       //      TypePatternList followMe = TypePatternList.ANY;
+               
+               AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern();
+               ModifiersPattern modifiers = parseModifiersPattern();
+               TypePattern returnType = parseTypePattern();
+               TypePattern declaringType = parseTypePattern();
+               NamePattern name;
+               //System.err.println("parsed field: " + declaringType.toString());
+               if (maybeEat(".")) {
+                   name = parseNamePattern();
+           } else {
+               name = tryToExtractName(declaringType);
+               if (name == null) throw new ParserException("name pattern",tokenSource.peek());
+               if (declaringType.toString().equals("")) {
+                       declaringType = TypePattern.ANY;
+               }
+               }
+               SignaturePattern ret = new SignaturePattern(Member.FIELD, modifiers, returnType,
+                                       declaringType, name, TypePatternList.ANY, ThrowsPattern.ANY,annotationPattern);
+                                       
+               int endPos = tokenSource.peek(-1).getEnd();
+           ret.setLocation(sourceContext, startPos, endPos);
+               return ret;
+       }
+       
+       
+       private NamePattern tryToExtractName(TypePattern nextType) {
+               if (nextType == TypePattern.ANY) {
+                       return NamePattern.ANY;
+               } else if (nextType instanceof WildTypePattern) {
+                       WildTypePattern p = (WildTypePattern)nextType;
+                       return p.extractName();
+               } else {
+                   return null;
+               }
+       }
+       
+       /**
+        * Parse type variable declarations for a generic method or at the start of a signature pointcut to identify
+        * type variable names in a generic type.
+        * @param includeParameterizedTypes
+        * @return
+        */
+       public TypeVariablePatternList maybeParseTypeVariableList() {
+               if (!maybeEat("<")) return null;
+               List typeVars = new ArrayList();
+               TypeVariablePattern t = parseTypeVariable();
+               typeVars.add(t);
+               while (maybeEat(",")) {
+                       TypeVariablePattern nextT = parseTypeVariable();
+                       typeVars.add(nextT);
+               }
+               eat(">");
+               TypeVariablePattern[] tvs = new TypeVariablePattern[typeVars.size()];
+               typeVars.toArray(tvs);
+               return new TypeVariablePatternList(tvs);
+       }
+       
+       // of the form execution<T,S,V> - allows identifiers only
+       public String[] maybeParseSimpleTypeVariableList() {
+               if (!maybeEat("<")) return null;
+               List typeVarNames = new ArrayList();
+               do {
+                       typeVarNames.add(parseIdentifier());
+               } while (maybeEat(","));
+               eat(">","',' or '>'");
+               String[] tvs = new String[typeVarNames.size()];
+               typeVarNames.toArray(tvs);
+               return tvs;
+       }
+       
+       public TypePatternList maybeParseTypeParameterList() {
+               if (!maybeEat("<")) return null;
+               List typePats = new ArrayList();
+               do {
+                       TypePattern tp = parseTypePattern(true,false);
+                       typePats.add(tp);
+               } while(maybeEat(","));
+               eat(">");
+               TypePattern[] tps = new TypePattern[typePats.size()];
+               typePats.toArray(tps);
+               return new TypePatternList(tps);                
+       }
+       
+       public TypeVariablePattern parseTypeVariable() {
+               TypePattern upperBound = null;
+               TypePattern[] additionalInterfaceBounds = null;
+               TypePattern lowerBound = null;
+               String typeVariableName = parseIdentifier();
+               if (maybeEatIdentifier("extends")) {
+                       upperBound = parseTypePattern();
+                       additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds();
+               } else if (maybeEatIdentifier("super")) {
+                       lowerBound = parseTypePattern();
+               }
+               return new TypeVariablePattern(typeVariableName,upperBound,additionalInterfaceBounds,lowerBound);
+       }
+       
+       private TypePattern[] maybeParseAdditionalInterfaceBounds() {
+               List boundsList = new ArrayList();
+               while (maybeEat("&")) {
+                       TypePattern tp = parseTypePattern();
+                       boundsList.add(tp);
+               }
+               if (boundsList.size() == 0) return null;
+               TypePattern[] ret = new TypePattern[boundsList.size()];
+               boundsList.toArray(ret);
+               return ret;
+       }
+
+       public String parsePossibleStringSequence(boolean shouldEnd) {
+               StringBuffer result = new StringBuffer();
+               
+               IToken token = tokenSource.next();
+               if (token.getLiteralKind()==null) {
+                       throw new ParserException("string",token);
+               }
+               while (token.getLiteralKind().equals("string")) {
+                       result.append(token.getString());                       
+                       boolean plus = maybeEat("+");
+                       if (!plus) break;
+                       token = tokenSource.next();
+                       if (token.getLiteralKind()==null) {
+                               throw new ParserException("string",token);
+                       }
+               }
+               eatIdentifier(";");
+               IToken t = tokenSource.next();
+               if (shouldEnd && t!=IToken.EOF) {
+                       throw new ParserException("<string>;",token);
+               }
+               // bug 125027: since we've eaten the ";" we need to set the index
+               // to be one less otherwise the end position isn't set correctly.
+               int currentIndex = tokenSource.getIndex();
+               tokenSource.setIndex(currentIndex-1);
+               
+               return result.toString();
+               
+       }
+       
+       public String parseStringLiteral() {
+               IToken token = tokenSource.next();
+               String literalKind = token.getLiteralKind();
+               if (literalKind == "string") {
+                       return token.getString();
+               }
+
+               throw new ParserException("string", token);
+       }
+       
+       public String parseIdentifier() {
+               IToken token = tokenSource.next();
+               if (token.isIdentifier()) return token.getString();
+               throw new ParserException("identifier", token);
+       }
+       
+       public void eatIdentifier(String expectedValue) {
+               IToken next = tokenSource.next();
+               if (!next.getString().equals(expectedValue)) {
+                       throw new ParserException(expectedValue, next);
+               }
+       }
+       
+       public boolean maybeEatIdentifier(String expectedValue) {
+               IToken next = tokenSource.peek();
+               if (next.getString().equals(expectedValue)) {
+                       tokenSource.next();
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+       
+       public void eat(String expectedValue) {
+               eat(expectedValue,expectedValue);
+       }
+       
+       private void eat(String expectedValue,String expectedMessage) {
+               IToken next = nextToken();
+               if (next.getString() != expectedValue) {
+                       if (expectedValue.equals(">") && next.getString().startsWith(">")) {
+                               // handle problem of >> and >>> being lexed as single tokens
+                               pendingRightArrows = BasicToken.makeLiteral(next.getString().substring(1).intern(), "string", next.getStart()+1, next.getEnd());
+                               return;
+                       }
+                       throw new ParserException(expectedMessage, next);
+               }
+       }
+
+       private IToken pendingRightArrows;
+       private IToken nextToken() {
+               if (pendingRightArrows != null) {
+                       IToken ret = pendingRightArrows;
+                       pendingRightArrows = null;
+                       return ret;
+               } else {
+                       return tokenSource.next();
+               }
+       }
+       
+       public boolean maybeEatAdjacent(String token) {
+               IToken next = tokenSource.peek();
+               if (next.getString() == token) {
+                       if (isAdjacent(tokenSource.peek(-1),next)) {
+                               tokenSource.next();
+                               return true;
+                       }
+               }               
+               return false;
+       }
+       
+       public boolean maybeEat(String token) {
+               IToken next = tokenSource.peek();
+               if (next.getString() == token) {
+                       tokenSource.next();
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+       
+       public String maybeEatIdentifier() {
+               IToken next = tokenSource.peek();
+               if (next.isIdentifier()) {
+                       tokenSource.next();
+                       return next.getString();
+               } else {
+                       return null;
+               }
+       }
+               
+       public boolean peek(String token) {
+               IToken next = tokenSource.peek();
+               return next.getString() == token;
+       }
+
+       public void checkEof() {
+               IToken last = tokenSource.next();
+               if (last != IToken.EOF) {
+                       throw new ParserException("unexpected pointcut element", last);
+               }
+       }
+       
+       public PatternParser(String data) {
+               this(BasicTokenSource.makeTokenSource(data,null));
+       }
+       
+       public PatternParser(String data, ISourceContext context) {
+               this(BasicTokenSource.makeTokenSource(data,context));
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerCflow.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerCflow.java
new file mode 100644 (file)
index 0000000..7cc0a24
--- /dev/null
@@ -0,0 +1,171 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.Advice;
+import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.CrosscuttingMembers;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.ResolvedMemberImpl;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Expr;
+import org.aspectj.weaver.ast.Test;
+
+public class PerCflow extends PerClause {
+       private final boolean isBelow;
+       private final Pointcut entry;
+
+       public PerCflow(Pointcut entry, boolean isBelow) {
+               this.entry = entry;
+               this.isBelow = isBelow;
+       }
+
+       // -----
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this, data);
+       }
+
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;
+       }
+
+       public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               return FuzzyBoolean.MAYBE;
+       }
+
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               return FuzzyBoolean.YES;
+       }
+
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               // assert bindings == null;
+               entry.resolve(scope);
+       }
+
+       public Pointcut parameterizeWith(Map typeVariableMap, World w) {
+               PerCflow ret = new PerCflow(entry.parameterizeWith(typeVariableMap, w), isBelow);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               Expr myInstance = Expr.makeCallExpr(AjcMemberMaker.perCflowAspectOfMethod(inAspect), Expr.NONE, inAspect);
+               state.setAspectInstance(myInstance);
+               return Test.makeCall(AjcMemberMaker.perCflowHasAspectMethod(inAspect), Expr.NONE);
+       }
+
+       public PerClause concretize(ResolvedType inAspect) {
+               PerCflow ret = new PerCflow(entry, isBelow);
+               ret.inAspect = inAspect;
+               if (inAspect.isAbstract())
+                       return ret;
+
+               Member cflowStackField = new ResolvedMemberImpl(Member.FIELD, inAspect, Modifier.STATIC | Modifier.PUBLIC | Modifier.FINAL,
+                               UnresolvedType.forName(NameMangler.CFLOW_STACK_TYPE), NameMangler.PERCFLOW_FIELD_NAME, UnresolvedType.NONE);
+
+               World world = inAspect.getWorld();
+
+               CrosscuttingMembers xcut = inAspect.crosscuttingMembers;
+
+               Collection previousCflowEntries = xcut.getCflowEntries();
+               Pointcut concreteEntry = entry.concretize(inAspect, inAspect, 0, null); // IntMap
+               // .
+               // EMPTY
+               // )
+               // ;
+               List innerCflowEntries = new ArrayList(xcut.getCflowEntries());
+               innerCflowEntries.removeAll(previousCflowEntries);
+
+               xcut.addConcreteShadowMunger(Advice.makePerCflowEntry(world, concreteEntry, isBelow, cflowStackField, inAspect,
+                               innerCflowEntries));
+
+               // ATAJ: add a munger to add the aspectOf(..) to the @AJ aspects
+               if (inAspect.isAnnotationStyleAspect() && !inAspect.isAbstract()) {
+                       inAspect.crosscuttingMembers.addLateTypeMunger(inAspect.getWorld().getWeavingSupport().makePerClauseAspect(inAspect,
+                                       getKind()));
+               }
+
+               // ATAJ inline around advice support - don't use a late munger to allow
+               // around inling for itself
+               if (inAspect.isAnnotationStyleAspect() && !inAspect.getWorld().isXnoInline()) {
+                       inAspect.crosscuttingMembers.addTypeMunger(inAspect.getWorld().getWeavingSupport()
+                                       .createAccessForInlineMunger(inAspect));
+               }
+
+               return ret;
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               PERCFLOW.write(s);
+               entry.write(s);
+               s.writeBoolean(isBelow);
+               writeLocation(s);
+       }
+
+       public static PerClause readPerClause(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               PerCflow ret = new PerCflow(Pointcut.read(s, context), s.readBoolean());
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public PerClause.Kind getKind() {
+               return PERCFLOW;
+       }
+
+       public Pointcut getEntry() {
+               return entry;
+       }
+
+       public String toString() {
+               return "percflow(" + inAspect + " on " + entry + ")";
+       }
+
+       public String toDeclarationString() {
+               if (isBelow)
+                       return "percflowbelow(" + entry + ")";
+               return "percflow(" + entry + ")";
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof PerCflow))
+                       return false;
+               PerCflow pc = (PerCflow) other;
+               return (pc.isBelow && isBelow) && ((pc.inAspect == null) ? (inAspect == null) : pc.inAspect.equals(inAspect))
+                               && ((pc.entry == null) ? (entry == null) : pc.entry.equals(entry));
+       }
+
+       public int hashCode() {
+               int result = 17;
+               result = 37 * result + (isBelow ? 0 : 1);
+               result = 37 * result + ((inAspect == null) ? 0 : inAspect.hashCode());
+               result = 37 * result + ((entry == null) ? 0 : entry.hashCode());
+               return result;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerClause.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerClause.java
new file mode 100644 (file)
index 0000000..62b2b1b
--- /dev/null
@@ -0,0 +1,91 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.IOException;
+
+import org.aspectj.util.TypeSafeEnum;
+import org.aspectj.weaver.*;
+
+// PTWIMPL New kind added to this class, can be (de)serialized
+public abstract class PerClause extends Pointcut {
+       protected ResolvedType inAspect;
+
+       public static PerClause readPerClause(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               Kind kind = Kind.read(s);
+               if (kind == SINGLETON) return PerSingleton.readPerClause(s, context);
+               else if (kind == PERCFLOW) return PerCflow.readPerClause(s, context);
+               else if (kind == PEROBJECT) return PerObject.readPerClause(s, context);
+               else if (kind == FROMSUPER) return PerFromSuper.readPerClause(s, context);
+               else if (kind == PERTYPEWITHIN) return PerTypeWithin.readPerClause(s,context);
+                       
+               throw new BCException("unknown kind: " + kind);
+       }
+
+    public final Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+       throw new RuntimeException("unimplemented: wrong concretize");
+    }
+
+       public abstract PerClause concretize(ResolvedType inAspect);
+       
+       public abstract PerClause.Kind getKind();
+       
+       public abstract String toDeclarationString();
+       
+       public static class Kind extends TypeSafeEnum {
+        public Kind(String name, int key) { super(name, key); }
+        
+        public static Kind read(VersionedDataInputStream s) throws IOException {
+            int key = s.readByte();
+            switch(key) {
+                case 1: return SINGLETON;
+                case 2: return PERCFLOW;
+                case 3: return PEROBJECT;
+                case 4: return FROMSUPER;
+                case 5: return PERTYPEWITHIN;
+            }
+            throw new BCException("weird kind " + key);
+        }
+    }
+
+       public static final Kind SINGLETON = new Kind("issingleton", 1);
+       public static final Kind PERCFLOW  = new Kind("percflow", 2);
+       public static final Kind PEROBJECT  = new Kind("perobject", 3);
+       public static final Kind FROMSUPER  = new Kind("fromsuper", 4);
+       public static final Kind PERTYPEWITHIN = new Kind("pertypewithin",5);
+
+    public static class KindAnnotationPrefix extends TypeSafeEnum {
+        private KindAnnotationPrefix(String name, int key) {
+            super(name, key);
+        }
+
+        public String extractPointcut(String perClause) {
+            int from = getName().length();
+            int to = perClause.length()-1;
+            if (!perClause.startsWith(getName())
+                || !perClause.endsWith(")")
+                || from > perClause.length()) {
+                throw new RuntimeException("cannot read perclause " + perClause);
+            }
+
+            return perClause.substring(from, to);
+        }
+
+        public static final KindAnnotationPrefix PERCFLOW = new KindAnnotationPrefix("percflow(", 1);
+        public static final KindAnnotationPrefix PERCFLOWBELOW = new KindAnnotationPrefix("percflowbelow(", 2);
+        public static final KindAnnotationPrefix PERTHIS = new KindAnnotationPrefix("perthis(", 3);
+        public static final KindAnnotationPrefix PERTARGET = new KindAnnotationPrefix("pertarget(", 4);
+        public static final KindAnnotationPrefix PERTYPEWITHIN = new KindAnnotationPrefix("pertypewithin(", 5);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerFromSuper.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerFromSuper.java
new file mode 100644 (file)
index 0000000..13c81fe
--- /dev/null
@@ -0,0 +1,135 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Test;
+
+public class PerFromSuper extends PerClause {
+       private PerClause.Kind kind;
+       
+       public PerFromSuper(PerClause.Kind kind) {
+               this.kind = kind;
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;
+       }
+
+       public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               throw new RuntimeException("unimplemented");
+       }
+               
+    protected FuzzyBoolean matchInternal(Shadow shadow) {
+        throw new RuntimeException("unimplemented");
+    }
+
+    public void resolveBindings(IScope scope, Bindings bindings) {
+       // this method intentionally left blank
+    }
+
+    protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+       throw new RuntimeException("unimplemented");
+    }
+
+
+       public PerClause concretize(ResolvedType inAspect) {
+               PerClause p = lookupConcretePerClause(inAspect.getSuperclass());
+               if (p == null) {
+                       inAspect.getWorld().getMessageHandler().handleMessage(
+                         MessageUtil.error(WeaverMessages.format(WeaverMessages.MISSING_PER_CLAUSE,inAspect.getSuperclass()), getSourceLocation())
+                       );
+            return new PerSingleton().concretize(inAspect);// AV: fallback on something else NPE in AJDT
+               } else {
+            if (p.getKind() != kind) {
+                inAspect.getWorld().getMessageHandler().handleMessage(
+                  MessageUtil.error(WeaverMessages.format(WeaverMessages.WRONG_PER_CLAUSE,kind,p.getKind()),
+                                    getSourceLocation())
+                );
+            }
+            return p.concretize(inAspect);
+        }
+       }
+       
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               return this;
+       }
+       
+       
+       
+       public PerClause lookupConcretePerClause(ResolvedType lookupType) {
+               PerClause ret = lookupType.getPerClause();
+               if (ret == null) return null;
+               if (ret instanceof PerFromSuper) {
+                       return lookupConcretePerClause(lookupType.getSuperclass());
+               }
+               return ret;
+       }
+       
+
+    public void write(DataOutputStream s) throws IOException {
+       FROMSUPER.write(s);
+       kind.write(s);
+       writeLocation(s);
+    }
+    
+       public static PerClause readPerClause(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               PerFromSuper ret = new PerFromSuper(Kind.read(s));
+               ret.readLocation(context, s);
+               return ret;
+       }
+       
+       public String toString() {
+               return "perFromSuper(" + kind + ", " + inAspect + ")";
+       }
+       
+       public String toDeclarationString() {
+               return "";
+       }
+
+       public PerClause.Kind getKind() {
+               return kind;
+       }
+
+    public boolean equals(Object other) {
+       if (!(other instanceof PerFromSuper)) return false;
+       PerFromSuper pc = (PerFromSuper)other;   
+       return pc.kind.equals(kind) 
+                       && ((pc.inAspect == null) ? (inAspect == null) : pc.inAspect.equals(inAspect));
+    }
+    
+    public int hashCode() {
+        int result = 17;
+        result = 37*result + kind.hashCode();
+        result = 37*result + ((inAspect == null) ? 0 : inAspect.hashCode());     
+        return result;
+    }
+    
+       
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerObject.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerObject.java
new file mode 100644 (file)
index 0000000..ab28c8f
--- /dev/null
@@ -0,0 +1,187 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.Advice;
+import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.PerObjectInterfaceTypeMunger;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.ResolvedTypeMunger;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Expr;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.ast.Var;
+
+public class PerObject extends PerClause {
+       private final boolean isThis;
+       private final Pointcut entry;
+
+       private static final int thisKindSet;
+       private static final int targetKindSet;
+
+       static {
+               int thisFlags = Shadow.ALL_SHADOW_KINDS_BITS;
+               int targFlags = Shadow.ALL_SHADOW_KINDS_BITS;
+               for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
+                       Shadow.Kind kind = Shadow.SHADOW_KINDS[i];
+                       if (kind.neverHasThis())
+                               thisFlags -= kind.bit;
+                       if (kind.neverHasTarget())
+                               targFlags -= kind.bit;
+               }
+               thisKindSet = thisFlags;
+               targetKindSet = targFlags;
+       }
+
+       public PerObject(Pointcut entry, boolean isThis) {
+               this.entry = entry;
+               this.isThis = isThis;
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this, data);
+       }
+
+       public int couldMatchKinds() {
+               return isThis ? thisKindSet : targetKindSet;
+       }
+
+       // -----
+       public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               return FuzzyBoolean.MAYBE;
+       }
+
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               // System.err.println("matches " + this + " ? " + shadow + ", " +
+               // shadow.hasTarget());
+               // ??? could probably optimize this better by testing could match
+               if (isThis)
+                       return FuzzyBoolean.fromBoolean(shadow.hasThis());
+               else
+                       return FuzzyBoolean.fromBoolean(shadow.hasTarget());
+       }
+
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               // assert bindings == null;
+               entry.resolve(scope);
+       }
+
+       public Pointcut parameterizeWith(Map typeVariableMap, World w) {
+               PerObject ret = new PerObject(entry.parameterizeWith(typeVariableMap, w), isThis);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       private Var getVar(Shadow shadow) {
+               return isThis ? shadow.getThisVar() : shadow.getTargetVar();
+       }
+
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               Expr myInstance = Expr.makeCallExpr(AjcMemberMaker.perObjectAspectOfMethod(inAspect), new Expr[] { getVar(shadow) },
+                               inAspect);
+               state.setAspectInstance(myInstance);
+               return Test.makeCall(AjcMemberMaker.perObjectHasAspectMethod(inAspect), new Expr[] { getVar(shadow) });
+       }
+
+       public PerClause concretize(ResolvedType inAspect) {
+               PerObject ret = new PerObject(entry, isThis);
+
+               ret.inAspect = inAspect;
+               if (inAspect.isAbstract())
+                       return ret;
+
+               World world = inAspect.getWorld();
+
+               Pointcut concreteEntry = entry.concretize(inAspect, inAspect, 0, null);
+               // concreteEntry = new AndPointcut(this, concreteEntry);
+               // concreteEntry.state = Pointcut.CONCRETE;
+               inAspect.crosscuttingMembers.addConcreteShadowMunger(Advice.makePerObjectEntry(world, concreteEntry, isThis, inAspect));
+
+               // FIXME AV - don't use lateMunger here due to test
+               // "inheritance, around advice and abstract pointcuts"
+               // see #75442 thread. Issue with weaving order.
+               ResolvedTypeMunger munger = new PerObjectInterfaceTypeMunger(inAspect, concreteEntry);
+               inAspect.crosscuttingMembers.addLateTypeMunger(world.getWeavingSupport().concreteTypeMunger(munger, inAspect));
+
+               // ATAJ: add a munger to add the aspectOf(..) to the @AJ aspects
+               if (inAspect.isAnnotationStyleAspect() && !inAspect.isAbstract()) {
+                       inAspect.crosscuttingMembers.addLateTypeMunger(inAspect.getWorld().getWeavingSupport().makePerClauseAspect(inAspect,
+                                       getKind()));
+               }
+
+               // ATAJ inline around advice support - don't use a late munger to allow
+               // around inling for itself
+               if (inAspect.isAnnotationStyleAspect() && !inAspect.getWorld().isXnoInline()) {
+                       inAspect.crosscuttingMembers.addTypeMunger(world.getWeavingSupport().createAccessForInlineMunger(inAspect));
+               }
+
+               return ret;
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               PEROBJECT.write(s);
+               entry.write(s);
+               s.writeBoolean(isThis);
+               writeLocation(s);
+       }
+
+       public static PerClause readPerClause(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               PerClause ret = new PerObject(Pointcut.read(s, context), s.readBoolean());
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public PerClause.Kind getKind() {
+               return PEROBJECT;
+       }
+
+       public boolean isThis() {
+               return isThis;
+       }
+
+       public String toString() {
+               return "per" + (isThis ? "this" : "target") + "(" + entry + ")";
+       }
+
+       public String toDeclarationString() {
+               return toString();
+       }
+
+       public Pointcut getEntry() {
+               return entry;
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof PerObject))
+                       return false;
+               PerObject pc = (PerObject) other;
+               return (pc.isThis && isThis) && ((pc.inAspect == null) ? (inAspect == null) : pc.inAspect.equals(inAspect))
+                               && ((pc.entry == null) ? (entry == null) : pc.entry.equals(entry));
+       }
+
+       public int hashCode() {
+               int result = 17;
+               result = 37 * result + (isThis ? 0 : 1);
+               result = 37 * result + ((inAspect == null) ? 0 : inAspect.hashCode());
+               result = 37 * result + ((entry == null) ? 0 : entry.hashCode());
+               return result;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerSingleton.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerSingleton.java
new file mode 100644 (file)
index 0000000..e91e9f4
--- /dev/null
@@ -0,0 +1,173 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Expr;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+
+public class PerSingleton extends PerClause {
+
+       private ResolvedMember perSingletonAspectOfMethod;
+
+       public PerSingleton() {
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this, data);
+       }
+
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;
+       }
+
+       public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               return FuzzyBoolean.YES;
+       }
+
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               return FuzzyBoolean.YES;
+       }
+
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               // this method intentionally left blank
+       }
+
+       public Pointcut parameterizeWith(Map typeVariableMap, World w) {
+               return this;
+       }
+
+       public Test findResidueInternal(Shadow shadow, ExposedState state) {
+               // TODO: the commented code is for slow Aspects.aspectOf() style - keep
+               // or remove
+               //
+               // Expr myInstance =
+               // Expr.makeCallExpr(AjcMemberMaker.perSingletonAspectOfMethod(inAspect),
+               // Expr.NONE, inAspect);
+               //
+               // state.setAspectInstance(myInstance);
+               //
+               // // we have no test
+               // // a NoAspectBoundException will be thrown if we need an instance of
+               // this
+               // // aspect before we are bound
+               // return Literal.TRUE;
+               // if (!Ajc5MemberMaker.isSlowAspect(inAspect)) {
+               if (perSingletonAspectOfMethod == null) {
+                       // Build this just once
+                       perSingletonAspectOfMethod = AjcMemberMaker.perSingletonAspectOfMethod(inAspect);
+               }
+               Expr myInstance = Expr.makeCallExpr(perSingletonAspectOfMethod, Expr.NONE, inAspect);
+
+               state.setAspectInstance(myInstance);
+
+               // we have no test
+               // a NoAspectBoundException will be thrown if we need an instance of
+               // this
+               // aspect before we are bound
+               return Literal.TRUE;
+               // } else {
+               // CallExpr callAspectOf =Expr.makeCallExpr(
+               // Ajc5MemberMaker.perSingletonAspectOfMethod(inAspect),
+               // new Expr[]{
+               // Expr.makeStringConstantExpr(inAspect.getName(), inAspect),
+               // //FieldGet is using ResolvedType and I don't need that here
+               // new FieldGetOn(Member.ajClassField, shadow.getEnclosingType())
+               // },
+               // inAspect
+               // );
+               // Expr castedCallAspectOf = new CastExpr(callAspectOf,
+               // inAspect.getName());
+               // state.setAspectInstance(castedCallAspectOf);
+               // return Literal.TRUE;
+               // }
+       }
+
+       public PerClause concretize(ResolvedType inAspect) {
+               PerSingleton ret = new PerSingleton();
+
+               ret.copyLocationFrom(this);
+
+               World world = inAspect.getWorld();
+
+               ret.inAspect = inAspect;
+
+               // ATAJ: add a munger to add the aspectOf(..) to the @AJ aspects
+               if (inAspect.isAnnotationStyleAspect() && !inAspect.isAbstract()) {
+                       // TODO will those change be ok if we add a serializable aspect ?
+                       // dig:
+                       // "can't be Serializable/Cloneable unless -XserializableAspects"
+                       if (getKind() == SINGLETON) { // pr149560
+                               inAspect.crosscuttingMembers.addTypeMunger(world.getWeavingSupport().makePerClauseAspect(inAspect, getKind()));
+                       } else {
+                               inAspect.crosscuttingMembers.addLateTypeMunger(world.getWeavingSupport().makePerClauseAspect(inAspect, getKind()));
+                       }
+               }
+
+               // ATAJ inline around advice support
+               if (inAspect.isAnnotationStyleAspect() && !inAspect.getWorld().isXnoInline()) {
+                       inAspect.crosscuttingMembers.addTypeMunger(world.getWeavingSupport().createAccessForInlineMunger(inAspect));
+               }
+
+               return ret;
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               SINGLETON.write(s);
+               writeLocation(s);
+       }
+
+       public static PerClause readPerClause(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               PerSingleton ret = new PerSingleton();
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public PerClause.Kind getKind() {
+               return SINGLETON;
+       }
+
+       public String toString() {
+               return "persingleton(" + inAspect + ")";
+       }
+
+       public String toDeclarationString() {
+               return "";
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof PerSingleton))
+                       return false;
+               PerSingleton pc = (PerSingleton) other;
+               return ((pc.inAspect == null) ? (inAspect == null) : pc.inAspect.equals(inAspect));
+       }
+
+       public int hashCode() {
+               int result = 17;
+               result = 37 * result + ((inAspect == null) ? 0 : inAspect.hashCode());
+               return result;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerThisOrTargetPointcutVisitor.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerThisOrTargetPointcutVisitor.java
new file mode 100644 (file)
index 0000000..7d62ae8
--- /dev/null
@@ -0,0 +1,216 @@
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ * 
+ * Contributors:
+ *   Alexandre Vasseur         initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.ResolvedPointcutDefinition;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+
+/**
+ * A visitor that turns a pointcut into a type pattern equivalent for a perthis or pertarget matching: - pertarget(target(Foo)) =>
+ * Foo+ (this one is a special case..) - pertarget(execution(* Foo.do()) => Foo - perthis(call(* Foo.do()) => * - perthis(!call(*
+ * Foo.do()) => * (see how the ! has been absorbed here..)
+ * 
+ * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+ */
+public class PerThisOrTargetPointcutVisitor extends AbstractPatternNodeVisitor {
+
+       /** A maybe marker */
+       private final static TypePattern MAYBE = new TypePatternMayBe();
+
+       private final boolean m_isTarget;
+       private final ResolvedType m_fromAspectType;
+
+       public PerThisOrTargetPointcutVisitor(boolean isTarget, ResolvedType fromAspectType) {
+               m_isTarget = isTarget;
+               m_fromAspectType = fromAspectType;
+       }
+
+       public TypePattern getPerTypePointcut(Pointcut perClausePointcut) {
+               return (TypePattern) perClausePointcut.accept(this, perClausePointcut);
+       }
+
+       // -- visitor methods, all is like Identity visitor except when it comes to transform pointcuts
+
+       public Object visit(WithinPointcut node, Object data) {
+               if (m_isTarget) {
+                       // pertarget(.. && within(Foo)) => true
+                       // pertarget(.. && !within(Foo)) => true as well !
+                       return MAYBE;
+               } else {
+                       return node.getTypePattern();
+               }
+       }
+
+       public Object visit(WithincodePointcut node, Object data) {
+               if (m_isTarget) {
+                       // pertarget(.. && withincode(* Foo.do())) => true
+                       // pertarget(.. && !withincode(* Foo.do())) => true as well !
+                       return MAYBE;
+               } else {
+                       return node.getSignature().getDeclaringType();
+               }
+       }
+
+       public Object visit(WithinAnnotationPointcut node, Object data) {
+               if (m_isTarget) {
+                       return MAYBE;
+               } else {
+                       return new AnyWithAnnotationTypePattern(node.getAnnotationTypePattern());
+               }
+       }
+
+       public Object visit(WithinCodeAnnotationPointcut node, Object data) {
+               if (m_isTarget) {
+                       return MAYBE;
+               } else {
+                       return MAYBE;// FIXME AV - can we optimize ? perthis(@withincode(Foo)) = hasmethod(..)
+               }
+       }
+
+       public Object visit(KindedPointcut node, Object data) {
+               if (node.getKind().equals(Shadow.AdviceExecution)) {
+                       return MAYBE;// TODO AV - can we do better ?
+               } else if (node.getKind().equals(Shadow.ConstructorExecution) || node.getKind().equals(Shadow.Initialization)
+                               || node.getKind().equals(Shadow.MethodExecution) || node.getKind().equals(Shadow.PreInitialization)
+                               || node.getKind().equals(Shadow.StaticInitialization)) {
+                       return node.getSignature().getDeclaringType();
+               } else if (node.getKind().equals(Shadow.ConstructorCall) || node.getKind().equals(Shadow.FieldGet)
+                               || node.getKind().equals(Shadow.FieldSet) || node.getKind().equals(Shadow.MethodCall)) {
+                       if (m_isTarget) {
+                               return node.getSignature().getDeclaringType();
+                       } else {
+                               return MAYBE;
+                       }
+               } else if (node.getKind().equals(Shadow.ExceptionHandler)) {
+                       return MAYBE;
+               } else {
+                       throw new ParserException("Undetermined - should not happen: " + node.getKind().getSimpleName(), null);
+               }
+       }
+
+       public Object visit(AndPointcut node, Object data) {
+               return new AndTypePattern(getPerTypePointcut(node.left), getPerTypePointcut(node.right));
+       }
+
+       public Object visit(OrPointcut node, Object data) {
+               return new OrTypePattern(getPerTypePointcut(node.left), getPerTypePointcut(node.right));
+       }
+
+       public Object visit(NotPointcut node, Object data) {
+               // TypePattern negated = getPerTypePointcut(node.getNegatedPointcut());
+               // if (MAYBE.equals(negated)) {
+               // return MAYBE;
+               // }
+               // return new NotTypePattern(negated);
+               // AMC - the only safe thing to return here is maybe...
+               // see for example pr114054
+               return MAYBE;
+       }
+
+       public Object visit(ThisOrTargetAnnotationPointcut node, Object data) {
+               if (m_isTarget && !node.isThis()) {
+                       return new AnyWithAnnotationTypePattern(node.getAnnotationTypePattern());
+               } else if (!m_isTarget && node.isThis()) {
+                       return new AnyWithAnnotationTypePattern(node.getAnnotationTypePattern());
+               } else {
+                       // perthis(@target(Foo))
+                       return MAYBE;
+               }
+       }
+
+       public Object visit(ThisOrTargetPointcut node, Object data) {
+               if ((m_isTarget && !node.isThis()) || (!m_isTarget && node.isThis())) {
+                       String pointcutString = node.getType().toString();
+                       // see pr115788 "<nothing>" means there was a problem resolving types - that will be reported so dont blow up
+                       // the parser here..
+                       if (pointcutString.equals("<nothing>")) {
+                               return new NoTypePattern();
+                       }
+                       // pertarget(target(Foo)) => Foo+ for type pattern matching
+                       // perthis(this(Foo)) => Foo+ for type pattern matching
+                       // TODO AV - we do like a deep copy by parsing it again.. quite dirty, would need a clean deep copy
+                       TypePattern copy = new PatternParser(pointcutString.replace('$', '.')).parseTypePattern();
+                       // TODO AV - see dirty replace from $ to . here as inner classes are with $ instead (#108488)
+                       copy.includeSubtypes = true;
+                       return copy;
+               } else {
+                       // perthis(target(Foo)) => maybe
+                       return MAYBE;
+               }
+       }
+
+       public Object visit(ReferencePointcut node, Object data) {
+               // && pc_ref()
+               // we know there is no support for binding in perClause: perthis(pc_ref(java.lang.String))
+               // TODO AV - may need some work for generics..
+
+               ResolvedPointcutDefinition pointcutDec;
+               ResolvedType searchStart = m_fromAspectType;
+               if (node.onType != null) {
+                       searchStart = node.onType.resolve(m_fromAspectType.getWorld());
+                       if (searchStart.isMissing()) {
+                               return MAYBE;// this should not happen since concretize will fails but just in case..
+                       }
+               }
+               pointcutDec = searchStart.findPointcut(node.name);
+
+               return getPerTypePointcut(pointcutDec.getPointcut());
+       }
+
+       public Object visit(IfPointcut node, Object data) {
+               return TypePattern.ANY;
+       }
+
+       public Object visit(HandlerPointcut node, Object data) {
+               // quiet unexpected since a KindedPointcut but do as if...
+               return MAYBE;
+       }
+
+       public Object visit(CflowPointcut node, Object data) {
+               return MAYBE;
+       }
+
+       public Object visit(ConcreteCflowPointcut node, Object data) {
+               return MAYBE;
+       }
+
+       public Object visit(ArgsPointcut node, Object data) {
+               return MAYBE;
+       }
+
+       public Object visit(ArgsAnnotationPointcut node, Object data) {
+               return MAYBE;
+       }
+
+       public Object visit(AnnotationPointcut node, Object data) {
+               return MAYBE;
+       }
+
+       public Object visit(Pointcut.MatchesNothingPointcut node, Object data) {
+               // a small hack since the usual MatchNothing has its toString = "<nothing>" which is not parseable back
+               // while I use back parsing for check purpose.
+               return new NoTypePattern() {
+                       public String toString() {
+                               return "false";
+                       }
+               };
+       }
+
+       /**
+        * A MayBe type pattern that acts as ANY except that !MAYBE = MAYBE
+        * 
+        * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+        */
+       private static class TypePatternMayBe extends AnyTypePattern {
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerTypeWithin.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerTypeWithin.java
new file mode 100644 (file)
index 0000000..9c1fd65
--- /dev/null
@@ -0,0 +1,230 @@
+/* *******************************************************************
+ * Copyright (c) 2005 IBM
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.Message;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.Advice;
+import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.PerTypeWithinTargetTypeMunger;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.ResolvedTypeMunger;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Expr;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+
+// PTWIMPL Represents a parsed pertypewithin()
+public class PerTypeWithin extends PerClause {
+
+       private TypePattern typePattern;
+
+       // Any shadow could be considered within a pertypewithin() type pattern
+       private static final int kindSet = Shadow.ALL_SHADOW_KINDS_BITS;
+
+       public TypePattern getTypePattern() {
+               return typePattern;
+       }
+
+       public PerTypeWithin(TypePattern p) {
+               typePattern = p;
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this, data);
+       }
+
+       public int couldMatchKinds() {
+               return kindSet;
+       }
+
+       public Pointcut parameterizeWith(Map typeVariableMap, World w) {
+               PerTypeWithin ret = new PerTypeWithin(typePattern.parameterizeWith(typeVariableMap, w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       // -----
+       public FuzzyBoolean fastMatch(FastMatchInfo info) {
+               if (typePattern.annotationPattern instanceof AnyAnnotationTypePattern) {
+                       return isWithinType(info.getType());
+               }
+               return FuzzyBoolean.MAYBE;
+       }
+
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               ResolvedType enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(), true);
+               if (enclosingType.isMissing()) {
+                       // PTWIMPL ?? Add a proper message
+                       IMessage msg = new Message("Cant find type pertypewithin matching...", shadow.getSourceLocation(), true,
+                                       new ISourceLocation[] { getSourceLocation() });
+                       shadow.getIWorld().getMessageHandler().handleMessage(msg);
+               }
+
+               // See pr106554 - we can't put advice calls in an interface when the
+               // advice is defined
+               // in a pertypewithin aspect - the JPs only exist in the static
+               // initializer and can't
+               // call the localAspectOf() method.
+               if (enclosingType.isInterface())
+                       return FuzzyBoolean.NO;
+
+               typePattern.resolve(shadow.getIWorld());
+               return isWithinType(enclosingType);
+       }
+
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               typePattern = typePattern.resolveBindings(scope, bindings, false, false);
+       }
+
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               // Member ptwField =
+               // AjcMemberMaker.perTypeWithinField(shadow.getEnclosingType
+               // (),inAspect);
+
+               Expr myInstance = Expr.makeCallExpr(AjcMemberMaker.perTypeWithinLocalAspectOf(shadow.getEnclosingType(), inAspect/*
+                                                                                                                                                                                                                                                * shadow.
+                                                                                                                                                                                                                                                * getEnclosingType
+                                                                                                                                                                                                                                                * ( )
+                                                                                                                                                                                                                                                */),
+                               Expr.NONE, inAspect);
+               state.setAspectInstance(myInstance);
+
+               // this worked at one point
+               // Expr myInstance =
+               // Expr.makeFieldGet(ptwField,shadow.getEnclosingType()
+               // .resolve(shadow.getIWorld()));//inAspect);
+               // state.setAspectInstance(myInstance);
+
+               // return Test.makeFieldGetCall(ptwField,null,Expr.NONE);
+               // cflowField, cflowCounterIsValidMethod, Expr.NONE
+
+               // This is what is in the perObject variant of this ...
+               // Expr myInstance =
+               // Expr.makeCallExpr(AjcMemberMaker.perTypeWithinAspectOfMethod(inAspect)
+               // ,
+               // new Expr[] {getVar(shadow)}, inAspect);
+               // state.setAspectInstance(myInstance);
+               // return
+               // Test.makeCall(AjcMemberMaker.perTypeWithinHasAspectMethod(inAspect),
+               // new Expr[] { getVar(shadow) });
+               //      
+
+               return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
+       }
+
+       public PerClause concretize(ResolvedType inAspect) {
+               PerTypeWithin ret = new PerTypeWithin(typePattern);
+               ret.copyLocationFrom(this);
+               ret.inAspect = inAspect;
+               if (inAspect.isAbstract())
+                       return ret;
+
+               World world = inAspect.getWorld();
+
+               SignaturePattern sigpat = new SignaturePattern(Member.STATIC_INITIALIZATION, ModifiersPattern.ANY, TypePattern.ANY,
+                               TypePattern.ANY,// typePattern,
+                               NamePattern.ANY, TypePatternList.ANY, ThrowsPattern.ANY, AnnotationTypePattern.ANY);
+
+               Pointcut staticInitStar = new KindedPointcut(Shadow.StaticInitialization, sigpat);
+               Pointcut withinTp = new WithinPointcut(typePattern);
+               Pointcut andPcut = new AndPointcut(staticInitStar, withinTp);
+               // We want the pointcut to be 'staticinitialization(*) &&
+               // within(<typepattern>' -
+               // we *cannot* shortcut this to staticinitialization(<typepattern>)
+               // because it
+               // doesnt mean the same thing.
+
+               // This munger will initialize the aspect instance field in the matched
+               // type
+
+               inAspect.crosscuttingMembers.addConcreteShadowMunger(Advice.makePerTypeWithinEntry(world, andPcut, inAspect));
+
+               ResolvedTypeMunger munger = new PerTypeWithinTargetTypeMunger(inAspect, ret);
+               inAspect.crosscuttingMembers.addTypeMunger(world.getWeavingSupport().concreteTypeMunger(munger, inAspect));
+
+               // ATAJ: add a munger to add the aspectOf(..) to the @AJ aspects
+               if (inAspect.isAnnotationStyleAspect() && !inAspect.isAbstract()) {
+                       inAspect.crosscuttingMembers.addLateTypeMunger(world.getWeavingSupport().makePerClauseAspect(inAspect, getKind()));
+               }
+
+               // ATAJ inline around advice support - don't use a late munger to allow
+               // around inling for itself
+               if (inAspect.isAnnotationStyleAspect() && !world.isXnoInline()) {
+                       inAspect.crosscuttingMembers.addTypeMunger(world.getWeavingSupport().createAccessForInlineMunger(inAspect));
+               }
+
+               return ret;
+
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               PERTYPEWITHIN.write(s);
+               typePattern.write(s);
+               writeLocation(s);
+       }
+
+       public static PerClause readPerClause(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               PerClause ret = new PerTypeWithin(TypePattern.read(s, context));
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public PerClause.Kind getKind() {
+               return PERTYPEWITHIN;
+       }
+
+       public String toString() {
+               return "pertypewithin(" + typePattern + ")";
+       }
+
+       public String toDeclarationString() {
+               return toString();
+       }
+
+       private FuzzyBoolean isWithinType(ResolvedType type) {
+               while (type != null) {
+                       if (typePattern.matchesStatically(type)) {
+                               return FuzzyBoolean.YES;
+                       }
+                       type = type.getDeclaringType();
+               }
+               return FuzzyBoolean.NO;
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof PerTypeWithin))
+                       return false;
+               PerTypeWithin pc = (PerTypeWithin) other;
+               return ((pc.inAspect == null) ? (inAspect == null) : pc.inAspect.equals(inAspect))
+                               && ((pc.typePattern == null) ? (typePattern == null) : pc.typePattern.equals(typePattern));
+       }
+
+       public int hashCode() {
+               int result = 17;
+               result = 37 * result + ((inAspect == null) ? 0 : inAspect.hashCode());
+               result = 37 * result + ((typePattern == null) ? 0 : typePattern.hashCode());
+               return result;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/Pointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/Pointcut.java
new file mode 100644 (file)
index 0000000..784b3df
--- /dev/null
@@ -0,0 +1,396 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.util.TypeSafeEnum;
+import org.aspectj.weaver.Advice;
+import org.aspectj.weaver.AdviceKind;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.Checker;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.PoliceExtensionUse;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.ShadowMunger;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+
+/**
+ * The lifecycle of Pointcuts is modeled by Pointcut.State.   It has three things:
+ * 
+ * <p>Creation -- SYMBOLIC -- then resolve(IScope) -- RESOLVED -- concretize(...) -- CONCRETE
+ * 
+ * @author Erik Hilsdale
+ * @author Jim Hugunin
+ * 
+ * A day in the life of a pointcut.... - AMC.
+ * ==========================================
+ * 
+ * Pointcuts are created by the PatternParser, which is called by ajdt to
+ * parse a pointcut from the PseudoTokens AST node (which in turn are part
+ * of a PointcutDesignator AST node). 
+ * 
+ * Pointcuts are resolved by ajdt when an AdviceDeclaration or a 
+ * PointcutDeclaration has its statements resolved. This happens as
+ * part of completeTypeBindings in the AjLookupEnvironment which is
+ * called after the diet parse phase of the compiler. Named pointcuts,
+ * and references to named pointcuts are instances of ReferencePointcut. 
+ * 
+ * At the end of the compilation process, the pointcuts are serialized
+ * (write method) into attributes in the class file.
+ * 
+ * When the weaver loads the class files, it unpacks the attributes
+ * and deserializes the pointcuts (read). All aspects are added to the
+ * world, by calling addOrReplaceAspect on
+ * the crosscutting members set of the world. When aspects are added or
+ * replaced, the crosscutting members in the aspect are extracted as
+ * ShadowMungers (each holding a pointcut). The ShadowMungers are
+ * concretized, which concretizes the pointcuts. At this stage
+ * ReferencePointcuts are replaced by their declared content.
+ * 
+ * During weaving, the weaver processes type by type. It first culls
+ * potentially matching ShadowMungers by calling the fastMatch method
+ * on their pointcuts. Only those that might match make it through to
+ * the next phase. At the next phase, all of the shadows within the
+ * type are created and passed to the pointcut for matching (match). 
+ * 
+ * When the actual munging happens, matched pointcuts are asked for
+ * their residue (findResidue) - the runtime test if any. Because of
+ * negation, findResidue may be called on pointcuts that could never
+ * match the shadow.
+ * 
+ */
+public abstract class Pointcut extends PatternNode {
+       public static final class State extends TypeSafeEnum {
+               public State(String name, int key) {
+                       super(name, key);
+               }
+       }
+
+    /**
+     * ATAJ the name of the formal for which we don't want any warning when unbound since
+     * we consider them as implicitly bound. f.e. JoinPoint for @AJ advices
+     */
+    public String[] m_ignoreUnboundBindingForNames = new String[0];
+
+       public static final State SYMBOLIC = new State("symbolic", 0);
+       public static final State RESOLVED = new State("resolved", 1);
+       public static final State CONCRETE = new State("concrete", 2);
+
+       protected byte pointcutKind;
+       
+       public State state;
+
+       protected int lastMatchedShadowId;
+       private FuzzyBoolean lastMatchedShadowResult;
+       private String[] typeVariablesInScope = new String[0];
+       
+       protected boolean hasBeenParameterized = false;
+       
+       /**
+        * Constructor for Pattern.
+        */
+       public Pointcut() {
+               super();
+               this.state = SYMBOLIC;
+       }
+       
+
+       /**
+        * Could I match any shadows in the code defined within this type?
+        */
+       public abstract FuzzyBoolean fastMatch(FastMatchInfo info);
+       
+       /**
+        * The set of ShadowKinds that this Pointcut could possibly match -
+        * an int whose bits are set according to the Kinds specified in Shadow.java
+        */
+       public abstract int couldMatchKinds();
+       
+       public String[] getTypeVariablesInScope() {
+               return typeVariablesInScope;
+       }
+       
+       public void setTypeVariablesInScope(String[] typeVars) {
+               this.typeVariablesInScope = typeVars;
+       }
+       
+       /**
+        * Do I really match this shadow?
+        * XXX implementors need to handle state
+        */
+       public final FuzzyBoolean match(Shadow shadow) {
+               if (shadow.shadowId == lastMatchedShadowId) return lastMatchedShadowResult;
+               FuzzyBoolean ret;
+               // this next test will prevent a lot of un-needed matching going on....
+               if (shadow.getKind().isSet(couldMatchKinds())) {
+                       ret = matchInternal(shadow);
+               } else {
+                       ret = FuzzyBoolean.NO;
+               }
+               lastMatchedShadowId = shadow.shadowId;
+               lastMatchedShadowResult = ret;
+               return ret;
+       }
+       
+       protected abstract FuzzyBoolean matchInternal(Shadow shadow);
+       
+       public static final byte KINDED = 1;
+       public static final byte WITHIN = 2;
+       public static final byte THIS_OR_TARGET = 3;
+       public static final byte ARGS = 4;
+       public static final byte AND = 5;
+       public static final byte OR = 6;
+       public static final byte NOT = 7;
+       public static final byte REFERENCE = 8;
+       public static final byte IF = 9;
+       public static final byte CFLOW = 10;
+       public static final byte WITHINCODE = 12;
+       public static final byte HANDLER = 13;
+       public static final byte IF_TRUE = 14;
+       public static final byte IF_FALSE = 15;
+       public static final byte ANNOTATION = 16;
+       public static final byte ATWITHIN = 17;
+       public static final byte ATWITHINCODE = 18;
+       public static final byte ATTHIS_OR_TARGET = 19;
+       
+       public static final byte NONE = 20; // DO NOT CHANGE OR REORDER THIS SEQUENCE, THIS VALUE CAN BE PUT OUT BY ASPECTJ1.2.1
+
+       public static final byte ATARGS = 21;
+       public static final byte USER_EXTENSION = 22;
+
+       public byte getPointcutKind() { return pointcutKind; }
+
+       // internal, only called from resolve
+       protected abstract void resolveBindings(IScope scope, Bindings bindings);
+       
+    /**
+     * Returns this pointcut mutated
+     */
+    public final Pointcut resolve(IScope scope) {
+       assertState(SYMBOLIC);
+       Bindings bindingTable = new Bindings(scope.getFormalCount());
+       IScope bindingResolutionScope = scope;
+       if (typeVariablesInScope.length > 0) {
+               bindingResolutionScope = new ScopeWithTypeVariables(typeVariablesInScope,scope);
+       }
+        this.resolveBindings(bindingResolutionScope, bindingTable);
+        bindingTable.checkAllBound(bindingResolutionScope);
+        this.state = RESOLVED;
+        return this;   
+    }
+    
+       /**
+        * Returns a new pointcut
+        * Only used by test cases
+        */
+    public final Pointcut concretize(ResolvedType inAspect, ResolvedType declaringType, int arity) {
+        Pointcut ret = concretize(inAspect, declaringType, IntMap.idMap(arity));
+        // copy the unbound ignore list
+        ret.m_ignoreUnboundBindingForNames = m_ignoreUnboundBindingForNames;
+        return ret;
+    }
+       
+       
+       //XXX this is the signature we're moving to
+       public final Pointcut concretize(ResolvedType inAspect, ResolvedType declaringType, int arity, ShadowMunger advice) {
+               //if (state == CONCRETE) return this; //???
+               IntMap map = IntMap.idMap(arity);
+               map.setEnclosingAdvice(advice);
+               map.setConcreteAspect(inAspect);
+               return concretize(inAspect, declaringType, map);
+       }
+       
+       public boolean isDeclare(ShadowMunger munger) {
+               if (munger == null) return false; // ??? Is it actually an error if we get a null munger into this method.
+               if (munger instanceof Checker) return true;
+               if (((Advice)munger).getKind().equals(AdviceKind.Softener)) return true;
+               return false;
+       }
+       
+       
+       public final Pointcut concretize(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               //!!! add this test -- assertState(RESOLVED);
+               Pointcut ret = this.concretize1(inAspect, declaringType, bindings);
+        if (shouldCopyLocationForConcretize()) ret.copyLocationFrom(this);
+               ret.state = CONCRETE;
+        // copy the unbound ignore list
+        ret.m_ignoreUnboundBindingForNames = m_ignoreUnboundBindingForNames;
+               return ret;
+       }
+       
+       
+       protected boolean shouldCopyLocationForConcretize() {
+               return true;
+       }
+
+
+       /**
+        * Resolves and removes ReferencePointcuts, replacing with basic ones
+        * 
+        * @param inAspect the aspect to resolve relative to
+        * @param bindings a Map from formal index in the current lexical context
+        *                               -> formal index in the concrete advice that will run
+        * 
+        * This must always return a new Pointcut object (even if the concretized
+        * Pointcut is identical to the resolved one).  That behavior is
+        * assumed in many places.
+        * XXX fix implementors to handle state
+        */
+       protected abstract Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings);
+       
+       
+       //XXX implementors need to handle state
+       /**
+        * This can be called from NotPointcut even for Pointcuts that
+        * don't match the shadow
+        */
+       public final Test findResidue(Shadow shadow, ExposedState state) {
+//             if (shadow.shadowId == lastMatchedShadowId) return lastMatchedShadowResidue;
+               Test ret = findResidueInternal(shadow,state);
+//             lastMatchedShadowResidue = ret;
+               lastMatchedShadowId = shadow.shadowId;
+               return ret;
+       }
+       
+       protected abstract Test findResidueInternal(Shadow shadow,ExposedState state);
+
+       //XXX we're not sure whether or not this is needed
+       //XXX currently it's unused  we're keeping it around as a stub
+       public void postRead(ResolvedType enclosingType) {}
+       
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               byte kind = s.readByte();
+               Pointcut ret;
+               
+               switch(kind) {
+                       case KINDED: ret = KindedPointcut.read(s, context); break;
+                       case WITHIN: ret = WithinPointcut.read(s, context); break;
+                       case THIS_OR_TARGET: ret = ThisOrTargetPointcut.read(s, context); break;
+                       case ARGS: ret = ArgsPointcut.read(s, context); break;
+                       case AND: ret = AndPointcut.read(s, context); break;
+                       case OR: ret = OrPointcut.read(s, context); break;
+                       case NOT: ret = NotPointcut.read(s, context); break;
+                       case REFERENCE: ret = ReferencePointcut.read(s, context); break;
+                       case IF: ret = IfPointcut.read(s, context); break;
+                       case CFLOW: ret = CflowPointcut.read(s, context); break;
+                       case WITHINCODE: ret = WithincodePointcut.read(s, context); break;
+                       case HANDLER: ret = HandlerPointcut.read(s, context); break;
+                       case IF_TRUE: ret = IfPointcut.makeIfTruePointcut(RESOLVED); break;
+                       case IF_FALSE: ret = IfPointcut.makeIfFalsePointcut(RESOLVED); break;
+                       case ANNOTATION: ret = AnnotationPointcut.read(s, context); break;
+                       case ATWITHIN: ret = WithinAnnotationPointcut.read(s, context); break;
+                       case ATWITHINCODE: ret = WithinCodeAnnotationPointcut.read(s, context); break;
+                       case ATTHIS_OR_TARGET: ret = ThisOrTargetAnnotationPointcut.read(s, context); break;
+                       case ATARGS: ret = ArgsAnnotationPointcut.read(s,context); break;
+                       case NONE: ret = makeMatchesNothing(RESOLVED); break;
+                       default:
+                               throw new BCException("unknown kind: " + kind);
+               }
+               ret.state = RESOLVED;
+               ret.pointcutKind = kind;
+               return ret;
+               
+       }
+       
+       public void check(ISourceContext ctx,World world) {
+               // this is a quick visitor...
+       PoliceExtensionUse pointcutPolice = new PoliceExtensionUse(world,this);
+       this.accept(pointcutPolice, null);
+       if (pointcutPolice.synchronizationDesignatorEncountered())
+               world.setSynchronizationPointcutsInUse();
+       }
+       
+
+       //public void prepare(Shadow shadow) {}
+    
+    // ---- test method
+    
+    public static Pointcut fromString(String str) {
+        PatternParser parser = new PatternParser(str);
+        return parser.parsePointcut();
+    }
+    
+    static class MatchesNothingPointcut extends Pointcut {
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+                       return Literal.FALSE; // can only get here if an earlier error occurred
+               }
+
+               public int couldMatchKinds() {
+                       return Shadow.NO_SHADOW_KINDS_BITS;
+               }
+               
+               public FuzzyBoolean fastMatch(FastMatchInfo type) {
+                       return FuzzyBoolean.NO;
+               }
+               
+               protected FuzzyBoolean matchInternal(Shadow shadow) {
+                       return FuzzyBoolean.NO;
+               }
+                               
+               public void resolveBindings(IScope scope, Bindings bindings) {
+               }
+               
+               public void postRead(ResolvedType enclosingType) {
+               }
+
+               public Pointcut concretize1(
+                       ResolvedType inAspect,
+                       ResolvedType declaringType, 
+                       IntMap bindings) {
+                       return makeMatchesNothing(state);
+               }
+
+
+               public void write(DataOutputStream s) throws IOException {
+                       s.writeByte(NONE);
+               }
+               
+               public String toString() { return ""; }
+
+        public Object accept(PatternNodeVisitor visitor, Object data) {
+            return visitor.visit(this, data);
+        }
+        
+        public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               return this;
+        }
+       }
+    
+    //public static Pointcut MatchesNothing = new MatchesNothingPointcut();
+    //??? there could possibly be some good optimizations to be done at this point
+    public static Pointcut makeMatchesNothing(State state) {
+       Pointcut ret = new MatchesNothingPointcut();
+       ret.state = state;
+       return ret;
+    }
+
+       public void assertState(State state) {
+               if (this.state != state) {
+                       throw new BCException("expected state: " + state + " got: " + this.state);
+               }
+       }
+       
+       public abstract Pointcut parameterizeWith(Map typeVariableMap,World w);
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PointcutEvaluationExpenseComparator.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PointcutEvaluationExpenseComparator.java
new file mode 100644 (file)
index 0000000..8c1c07f
--- /dev/null
@@ -0,0 +1,114 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.util.Comparator;
+
+import org.aspectj.weaver.Shadow;
+
+public class PointcutEvaluationExpenseComparator implements Comparator {
+
+       private static final int MATCHES_NOTHING = -1;
+       private static final int WITHIN = 1;
+       private static final int ATWITHIN = 2;
+       private static final int STATICINIT = 3;
+       private static final int ADVICEEXECUTION = 4;
+       private static final int HANDLER = 5;
+       private static final int GET_OR_SET = 6;
+       private static final int WITHINCODE = 7;
+       private static final int ATWITHINCODE = 8;
+       private static final int EXE_INIT_PREINIT = 9;
+       private static final int CALL = 10;
+       private static final int ANNOTATION = 11;
+       private static final int THIS_OR_TARGET = 12;
+       private static final int AT_THIS_OR_TARGET = 13;
+       private static final int ARGS = 14;
+       private static final int AT_ARGS = 15;
+       private static final int CFLOW = 16;
+       private static final int IF = 17;
+       private static final int OTHER = 20;
+       
+       /**
+        * Compare 2 pointcuts based on an estimate of how expensive they may be
+        * to evaluate.
+        * 
+        * within
+        * @within
+        * staticinitialization  [make sure this has a fast match method]
+        * adviceexecution
+        * handler
+        * get, set
+        * withincode
+        * @withincode
+        * execution, initialization, preinitialization
+        * call
+        * @annotation
+        * this, target
+        * @this, @target
+        * args
+        * @args
+        * cflow, cflowbelow
+        * if
+        */
+       public int compare(Object o1, Object o2) {
+               Pointcut p1 = (Pointcut) o1;
+               Pointcut p2 = (Pointcut) o2;
+               
+               // important property for a well-defined comparator
+               if (p1.equals(p2)) return 0;            
+               int result = getScore(p1) - getScore(p2);
+               if (result == 0) {
+                       // they have the same evaluation expense, but are not 'equal'
+                       // sort by hashCode
+                       result = p1.hashCode() - p2.hashCode();
+                       if (result == 0) /*not allowed if ne*/ return -1;
+               }
+               return result;
+       }
+
+       // a higher score means a more expensive evaluation
+       private int getScore(Pointcut p) {
+               if (p.couldMatchKinds()==Shadow.NO_SHADOW_KINDS_BITS) return MATCHES_NOTHING;
+               if (p instanceof WithinPointcut) return WITHIN;
+               if (p instanceof WithinAnnotationPointcut) return ATWITHIN;
+               if (p instanceof KindedPointcut) {
+                       KindedPointcut kp = (KindedPointcut) p;
+                       Shadow.Kind kind = kp.getKind();
+                       if (kind == Shadow.AdviceExecution) {
+                               return ADVICEEXECUTION;
+                       } else if ((kind == Shadow.ConstructorCall) || (kind == Shadow.MethodCall)) {
+                               return CALL;
+                       } else if ((kind == Shadow.ConstructorExecution) || (kind == Shadow.MethodExecution) ||
+                                          (kind == Shadow.Initialization) || (kind == Shadow.PreInitialization)) {
+                               return EXE_INIT_PREINIT;
+                       } else if (kind == Shadow.ExceptionHandler) {
+                               return HANDLER;
+                       } else if ((kind == Shadow.FieldGet) || (kind == Shadow.FieldSet)) {
+                               return GET_OR_SET;
+                       } else if (kind == Shadow.StaticInitialization) {
+                               return STATICINIT;
+                       } else return OTHER;
+               }
+               if (p instanceof AnnotationPointcut) return ANNOTATION;
+               if (p instanceof ArgsPointcut) return ARGS;
+               if (p instanceof ArgsAnnotationPointcut) return AT_ARGS;
+               if (p instanceof CflowPointcut) return CFLOW;
+               if (p instanceof HandlerPointcut) return HANDLER;
+               if (p instanceof IfPointcut) return IF;
+               if (p instanceof ThisOrTargetPointcut) return THIS_OR_TARGET;
+               if (p instanceof ThisOrTargetAnnotationPointcut) return AT_THIS_OR_TARGET;
+               if (p instanceof WithincodePointcut) return WITHINCODE;
+               if (p instanceof WithinCodeAnnotationPointcut) return ATWITHINCODE;
+               if (p instanceof NotPointcut) return getScore(((NotPointcut)p).getNegatedPointcut());
+               if (p instanceof AndPointcut) return getScore(((AndPointcut)p).getLeft());
+               if (p instanceof OrPointcut) return getScore(((OrPointcut)p).getLeft());
+               return OTHER;           
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PointcutRewriter.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PointcutRewriter.java
new file mode 100644 (file)
index 0000000..7adce39
--- /dev/null
@@ -0,0 +1,440 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.util.Iterator;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.patterns.Pointcut.MatchesNothingPointcut;
+
+/**
+ * @author colyer
+ * 
+ * Performs term rewriting for pointcut expressions.
+ * 
+ */
+public class PointcutRewriter {
+
+       private static final boolean WATCH_PROGRESS = false;
+       
+       /**
+        * Set forcerewrite if you want to override the checking for something already in DNF (useful for
+        * some testing)
+        * Repeated processing of something already in DNF is expensive (it ends up being done for
+        * every pointcut on every incremental compile) - so let's not do it if we don't have to.
+        * See pr113257
+        */
+       public Pointcut rewrite(Pointcut pc,boolean forceRewrite) {
+               Pointcut result = pc;//checkPC(result);
+               if (forceRewrite || !isDNF(pc)) {
+                       if (WATCH_PROGRESS) System.out.println("Initial pointcut is        ==> " + format(pc));
+                       result = distributeNot(result);//checkPC(result);
+                       if (WATCH_PROGRESS) System.out.println("Distributing NOT gives     ==> " + format(result));
+                       result = pullUpDisjunctions(result);//checkPC(result);
+                       if (WATCH_PROGRESS) System.out.println("Pull up disjunctions gives ==> " + format(result));             
+           } else {
+                       if (WATCH_PROGRESS) System.out.println("Not distributing NOTs or pulling up disjunctions, already DNF ==> "+format(pc));
+           }
+               result = simplifyAnds(result);  //checkPC(result);
+               if (WATCH_PROGRESS) System.out.println("Simplifying ANDs gives     ==> " + format(result));
+               result = removeNothings(result); //checkPC(result);
+           if (WATCH_PROGRESS) System.out.println("Removing nothings gives    ==> " + format(result));
+               result = sortOrs(result); //checkPC(result);
+               if (WATCH_PROGRESS) System.out.println("Sorting ORs gives          ==> " + format(result));
+               return result;
+       }
+       
+//     /**
+//      * Checks pointcuts - used for debugging.
+//      * - this variant checks if the context has been lost, since
+//      *   that can indicate an NPE will happen later reporting a message (pr162657).
+//      *   Not finished, but helped locate the problem ;)
+//      */
+//     private void checkPC(Pointcut pc) {
+//             if (isNot(pc)) {
+//                     NotPointcut npc = (NotPointcut)pc;
+//                     checkPC(npc.getNegatedPointcut());
+//                     if (npc.getSourceContext()==null) {
+//                             System.out.println("Lost context for "+npc);
+//                             throw new RuntimeException("Lost context");
+//                     }
+//             } else if (isOr(pc)) {
+//                     OrPointcut opc = (OrPointcut)pc;
+//                     checkPC(opc.getLeft());
+//                     checkPC(opc.getRight());
+//                     if (opc.getSourceContext()==null) {
+//                             System.out.println("Lost context for "+opc);
+//                             throw new RuntimeException("Lost context");
+//                     }
+//             } else if (isAnd(pc)) {
+//                     AndPointcut apc = (AndPointcut)pc;
+//                     checkPC(apc.getLeft());
+//                     checkPC(apc.getRight());
+//                     if (apc.getSourceContext()==null) {
+//                             System.out.println("Lost context for "+apc);
+//                             throw new RuntimeException("Lost context");
+//                     }
+//             } else {
+//                     if (pc.getSourceContext()==null) {
+//                             System.out.println("Lost context for "+pc);
+//                             throw new RuntimeException("Lost context");             
+//                     }
+//             }
+//     }
+                               
+       public Pointcut rewrite(Pointcut pc) {
+               return rewrite(pc,false);
+       }
+       
+       /**
+        * Check if a pointcut is in DNF - if it is then it should be lots of 'ORs' up the 
+        * top with 'ANDs' beneath them.
+        */
+       private boolean isDNF(Pointcut pc) {
+               return isDNFHelper(pc,true);
+       }
+       
+       /**
+        * Helper function for determining DNFness.  Records when we have crossed the point of allowing ORs.
+        */
+       private boolean isDNFHelper(Pointcut pc,boolean canStillHaveOrs) {
+               if (isAnd(pc)) {
+                       AndPointcut ap = (AndPointcut)pc;
+                       return isDNFHelper(ap.getLeft(),false) && isDNFHelper(ap.getRight(),false);
+               } else if (isOr(pc)) {
+                       if (!canStillHaveOrs) return false;
+                       OrPointcut op = (OrPointcut)pc;
+                       return isDNFHelper(op.getLeft(),true) && isDNFHelper(op.getRight(),true);
+               } else if (isNot(pc)) {
+                       return isDNFHelper(((NotPointcut)pc).getNegatedPointcut(),canStillHaveOrs);
+               } else {
+                       return true;
+               }
+       }
+       
+       /** 
+        * Allows formatting of the output pointcut for debugging...
+        */
+       public static String format(Pointcut p) {
+               String s = p.toString();
+               // Regex param needs '(' and '*' changing to '.'
+//             s = s.replaceAll("persingleton.pkg1.monitoring.ErrorMonitoring.","M");
+//             s = s.replaceAll("args.BindingTypePattern.java.lang.Throwable, 0.","Z");
+//             s = s.replaceAll("within.pkg1.monitoring.DoMonitorErrors+.","X");
+//             s=s.replaceAll("within.pkg1.monitoring....","Y");
+//             s=s.replaceAll("if.true.","N");
+               return s;
+       }
+       
+       
+       
+       // !!X => X
+       // !(X && Y) => !X || !Y
+       // !(X || Y) => !X && !Y
+       private Pointcut distributeNot(Pointcut pc) {
+               if (isNot(pc)) {
+                       NotPointcut npc = (NotPointcut) pc;
+                       Pointcut notBody = distributeNot(npc.getNegatedPointcut());
+                       if (isNot(notBody)) {
+                               // !!X => X
+                               return ((NotPointcut)notBody).getNegatedPointcut();
+                       } else if (isAnd(notBody)) {
+                               // !(X && Y) => !X || !Y
+                               AndPointcut apc = (AndPointcut) notBody;
+                               Pointcut newLeft = distributeNot(new NotPointcut(apc.getLeft(),npc.getStart())); 
+                               Pointcut newRight = distributeNot(new NotPointcut(apc.getRight(),npc.getStart()));
+                               return new OrPointcut(newLeft,newRight);
+                       } else if (isOr(notBody)) {
+                               // !(X || Y) => !X && !Y
+                               OrPointcut opc = (OrPointcut) notBody;
+                               Pointcut newLeft = distributeNot(new NotPointcut(opc.getLeft(),npc.getStart())); 
+                               Pointcut newRight = distributeNot(new NotPointcut(opc.getRight(),npc.getStart()));
+                               return new AndPointcut(newLeft,newRight);                               
+                       } else {
+                               return new NotPointcut(notBody,npc.getStart());
+                       }
+               } else if (isAnd(pc)) {
+                       AndPointcut apc = (AndPointcut) pc;
+                       Pointcut left = distributeNot(apc.getLeft());
+                       Pointcut right = distributeNot(apc.getRight());
+                       return new AndPointcut(left,right);
+               } else if (isOr(pc)) {
+                       OrPointcut opc = (OrPointcut) pc;
+                       Pointcut left = distributeNot(opc.getLeft());
+                       Pointcut right = distributeNot(opc.getRight());
+                       return new OrPointcut(left,right);
+               } else {
+                       return pc;
+               }
+       }
+       
+       // A && (B || C) => (A && B) || (A && C)
+       // (A || B) && C => (A && C) || (B && C)
+       private Pointcut pullUpDisjunctions(Pointcut pc) {
+               if (isNot(pc)) {
+                       NotPointcut npc = (NotPointcut)pc;
+                                               return new NotPointcut(pullUpDisjunctions(npc.getNegatedPointcut()));
+               } else if (isAnd(pc)) {
+                       AndPointcut apc = (AndPointcut) pc;
+                       // dive into left and right here...
+                       Pointcut left = pullUpDisjunctions(apc.getLeft());
+                       Pointcut right = pullUpDisjunctions(apc.getRight());
+                       if (isOr(left) && !isOr(right)) {
+                               // (A || B) && C => (A && C) || (B && C)
+                               Pointcut leftLeft = ((OrPointcut)left).getLeft();
+                               Pointcut leftRight = ((OrPointcut)left).getRight();
+                               return pullUpDisjunctions(
+                                                       new OrPointcut(
+                                                                       new AndPointcut(leftLeft,right),
+                                                                       new AndPointcut(leftRight,right))
+                                                       );
+                       } else if (isOr(right) && !isOr(left)) {
+                               // A && (B || C) => (A && B) || (A && C)
+                               Pointcut rightLeft = ((OrPointcut)right).getLeft();
+                               Pointcut rightRight = ((OrPointcut)right).getRight();
+                               return pullUpDisjunctions(
+                                                       new OrPointcut(
+                                                                       new AndPointcut(left,rightLeft),
+                                                                       new AndPointcut(left,rightRight))
+                                                       );
+                       }  else if (isOr(right) && isOr(left)) {
+                               // (A || B) && (C || D) => (A && C) || (A && D) || (B && C) || (B && D)
+                               Pointcut A = pullUpDisjunctions(((OrPointcut)left).getLeft());
+                               Pointcut B = pullUpDisjunctions(((OrPointcut)left).getRight());
+                               Pointcut C = pullUpDisjunctions(((OrPointcut)right).getLeft());
+                               Pointcut D = pullUpDisjunctions(((OrPointcut)right).getRight());
+                               Pointcut newLeft = new OrPointcut(
+                                                                               new AndPointcut(A,C),
+                                                                               new AndPointcut(A,D)
+                                                                       );
+                               Pointcut newRight = new OrPointcut(
+                                                              new AndPointcut(B,C),
+                                                              new AndPointcut(B,D)
+                                                          );                           
+                               return pullUpDisjunctions(new OrPointcut(newLeft,newRight));
+                       }       else {
+                               return new AndPointcut(left,right);
+                       }
+               } else if (isOr(pc)){
+                       OrPointcut opc = (OrPointcut) pc;
+                       return new OrPointcut(pullUpDisjunctions(opc.getLeft()),
+                                                     pullUpDisjunctions(opc.getRight()));
+               } else {
+                       return pc;
+               }
+       }
+       
+       /**
+        * Returns a NOTted form of the pointcut p - we cope with already NOTted pointcuts.
+        */
+       public Pointcut not(Pointcut p) {
+               if (isNot(p)) {
+                       return ((NotPointcut)p).getNegatedPointcut();
+               }
+               return new NotPointcut(p);
+       }
+       
+       /**
+        * Passed an array of pointcuts, returns an AND tree with them in.
+        */
+       public Pointcut createAndsFor(Pointcut[] ps) {
+               if (ps.length==1) return ps[0]; // dumb case
+               if (ps.length==2) { // recursion exit case
+                       return new AndPointcut(ps[0],ps[1]);
+               }
+               // otherwise ...
+               Pointcut[] subset = new Pointcut[ps.length-1];
+               for (int i = 1; i < ps.length; i++) {
+                       subset[i-1]=ps[i];
+               }
+               return new AndPointcut(ps[0],createAndsFor(subset));
+       }
+
+       
+       // NOT: execution(* TP.*(..)) => within(TP) && execution(* *(..))
+       //      since this breaks when the pattern matches an interface
+       // NOT: withincode(* TP.*(..)) => within(TP) && withincode(* *(..))
+       //      since this is not correct when an aspect makes an ITD
+//     private Pointcut splitOutWithins(Pointcut pc) {
+//             if (isExecution(pc)) {
+//                     KindedPointcut kpc = (KindedPointcut) pc;
+//                     SignaturePattern sp = kpc.signature;
+//                     TypePattern within = sp.getDeclaringType();
+//                     if (isAnyType(within)) return pc;
+//                     SignaturePattern simplified = removeDeclaringTypePattern(sp);
+//                     return new AndPointcut(new WithinPointcut(within),
+//                                                    new KindedPointcut(kpc.kind,simplified));
+//             } else if (isNot(pc)) {
+//                     return new NotPointcut(splitOutWithins(((NotPointcut)pc).getNegatedPointcut()));
+//             } else if (isAnd(pc)) {
+//                     AndPointcut apc = (AndPointcut) pc;
+//                     return new AndPointcut(splitOutWithins(apc.getLeft()),
+//                                                    splitOutWithins(apc.getRight()));
+//             } else if (isOr(pc)) {
+//                     OrPointcut opc = (OrPointcut) pc;
+//                     return new OrPointcut(splitOutWithins(opc.getLeft()),
+//                                                           splitOutWithins(opc.getRight()));
+//             } else {
+//                     return pc;
+//             }
+//     }
+       
+//     private SignaturePattern removeDeclaringTypePattern(SignaturePattern sp) {
+//             return new SignaturePattern(
+//               sp.getKind(),
+//               sp.getModifiers(),
+//               sp.getReturnType(),
+//               TypePattern.ANY,
+//               sp.getName(),
+//               sp.getParameterTypes(),
+//               sp.getThrowsPattern(),
+//               sp.getAnnotationPattern()
+//             );
+//     }
+
+       // this finds the root of each && tree and then aggregates all of the branches
+       // into a sorted set:
+       //   - duplicates are removed
+       //   - A && !A is replaced by a matchesNothingPointcut
+       //   - the kind(s) matched by the set are evaluated
+       //   - elements are sorted by evaluation complexity
+       //   - the result is written out with the least expensive branch leftmost
+       private Pointcut simplifyAnds(Pointcut pc) {
+               if (isNot(pc)) {
+                       NotPointcut npc = (NotPointcut) pc;
+                       Pointcut notBody = npc.getNegatedPointcut();
+                       if (isNot(notBody)) {
+                               // !!X => X
+                               return simplifyAnds(((NotPointcut)notBody).getNegatedPointcut());
+                       } else {
+                                                       return new NotPointcut(simplifyAnds(npc.getNegatedPointcut()));
+                       }
+               } else if (isOr(pc)) {
+                       OrPointcut opc = (OrPointcut) pc;
+                       return new OrPointcut(simplifyAnds(opc.getLeft()),simplifyAnds(opc.getRight()));
+               } else if (isAnd(pc)) {
+                       return simplifyAnd((AndPointcut)pc);
+               } else {
+                       return pc;
+               }
+       }
+       
+       private Pointcut simplifyAnd(AndPointcut apc) {
+               SortedSet nodes = new TreeSet(new PointcutEvaluationExpenseComparator());
+               collectAndNodes(apc,nodes);
+               // look for A and !A, or IfFalse
+               for (Iterator iter = nodes.iterator(); iter.hasNext();) {
+                       Pointcut element = (Pointcut) iter.next();
+                       if (element instanceof NotPointcut) {
+                               Pointcut body = ((NotPointcut)element).getNegatedPointcut();
+                               if (nodes.contains(body)) return Pointcut.makeMatchesNothing(body.state);
+                       }
+                       if (element instanceof IfPointcut) {
+                               if (((IfPointcut)element).alwaysFalse()) return Pointcut.makeMatchesNothing(element.state);
+                       }
+                       // If it can't match anything, the whole AND can't match anything
+                       if (element.couldMatchKinds()==Shadow.NO_SHADOW_KINDS_BITS) return element;
+               }
+               if (apc.couldMatchKinds()==Shadow.NO_SHADOW_KINDS_BITS) return Pointcut.makeMatchesNothing(apc.state);
+               // write out with cheapest on left
+               Iterator iter = nodes.iterator();
+               Pointcut result = (Pointcut) iter.next();
+               while(iter.hasNext()) {
+                       Pointcut right = (Pointcut) iter.next();
+                       result = new AndPointcut(result,right);
+               }
+               return result;
+       }
+       
+       private Pointcut sortOrs(Pointcut pc) {
+               SortedSet nodes = new TreeSet(new PointcutEvaluationExpenseComparator());
+               collectOrNodes(pc,nodes);               
+               // write out with cheapest on left
+               Iterator iter = nodes.iterator();
+               Pointcut result = (Pointcut) iter.next();
+               while(iter.hasNext()) {
+                       Pointcut right = (Pointcut) iter.next();
+                       result = new OrPointcut(result,right);
+               }
+               return result;
+       }
+       
+       /**
+        * Removes MATCHES_NOTHING pointcuts
+        */
+       private Pointcut removeNothings(Pointcut pc) {
+               if (isAnd(pc)) {
+                       AndPointcut apc = (AndPointcut)pc;
+                       Pointcut right = removeNothings(apc.getRight());
+                       Pointcut left  = removeNothings(apc.getLeft());
+                       if (left instanceof MatchesNothingPointcut || right instanceof MatchesNothingPointcut) return new MatchesNothingPointcut();
+                       return new AndPointcut(left,right);
+               } else if (isOr(pc)) {
+                       OrPointcut opc = (OrPointcut)pc;
+                       Pointcut right = removeNothings(opc.getRight());
+                       Pointcut left  = removeNothings(opc.getLeft());
+                       if (left instanceof MatchesNothingPointcut 
+                                       && !(right instanceof MatchesNothingPointcut)) {
+                               return right;
+                       } else if (right instanceof MatchesNothingPointcut 
+                                       && !(left instanceof MatchesNothingPointcut)) {
+                               return left;
+                       } else if (!(left instanceof MatchesNothingPointcut)
+                                       && !(right instanceof MatchesNothingPointcut)) {
+                               return new OrPointcut(left,right);
+                       } else if (left instanceof MatchesNothingPointcut
+                                       && right instanceof MatchesNothingPointcut) {
+                               return new MatchesNothingPointcut();    
+                       }                       
+               }
+               return pc;
+       }
+       
+       private void collectAndNodes(AndPointcut apc,Set nodesSoFar) {
+               Pointcut left = apc.getLeft();
+               Pointcut right = apc.getRight();
+               if (isAnd(left)) {
+                       collectAndNodes((AndPointcut)left,nodesSoFar);
+               } else {
+                       nodesSoFar.add(left);
+               }
+               if (isAnd(right)) {
+                       collectAndNodes((AndPointcut)right,nodesSoFar);
+               } else {
+                       nodesSoFar.add(right);
+               }               
+       }
+       
+       private void collectOrNodes(Pointcut pc, Set nodesSoFar) {
+               if (isOr(pc)) {
+                       OrPointcut opc = (OrPointcut) pc;
+                       collectOrNodes(opc.getLeft(),nodesSoFar);
+                       collectOrNodes(opc.getRight(),nodesSoFar);
+               } else {
+                       nodesSoFar.add(pc);
+               }
+       }
+       
+       private boolean isNot(Pointcut pc) {
+               return (pc instanceof NotPointcut);
+       }
+       
+       private boolean isAnd(Pointcut pc) {
+               return (pc instanceof AndPointcut);
+       }
+       
+       private boolean isOr(Pointcut pc) {
+               return (pc instanceof OrPointcut);
+       }
+       
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ReferencePointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ReferencePointcut.java
new file mode 100644 (file)
index 0000000..6ac7d0f
--- /dev/null
@@ -0,0 +1,407 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedPointcutDefinition;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.ShadowMunger;
+import org.aspectj.weaver.TypeVariable;
+import org.aspectj.weaver.TypeVariableReference;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Test;
+
+/**
+ */
+
+//XXX needs check that arguments contains no WildTypePatterns
+public class ReferencePointcut extends Pointcut {
+       public UnresolvedType onType; 
+       public TypePattern onTypeSymbolic; 
+       public String name;
+       public TypePatternList arguments;
+       
+       /**
+        * if this is non-null then when the pointcut is concretized the result will be parameterized too.
+        */
+       private Map typeVariableMap;
+       
+       //public ResolvedPointcut binding;
+       
+       public ReferencePointcut(TypePattern onTypeSymbolic, String name, TypePatternList arguments) {
+               this.onTypeSymbolic = onTypeSymbolic;
+               this.name = name;
+               this.arguments = arguments;
+               this.pointcutKind = REFERENCE;
+       }
+       
+       public ReferencePointcut(UnresolvedType onType, String name, TypePatternList arguments) {
+               this.onType = onType;
+               this.name = name;
+               this.arguments = arguments;
+               this.pointcutKind = REFERENCE;
+       }
+       
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;
+       }
+
+
+       //??? do either of these match methods make any sense???
+       public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               return FuzzyBoolean.MAYBE;
+       }
+               
+       /**
+        * Do I really match this shadow?
+        */
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               return FuzzyBoolean.NO;
+       }
+       
+       public String toString() {
+               StringBuffer buf = new StringBuffer();
+               if (onType != null) {
+                       buf.append(onType);
+                       buf.append(".");
+//                     for (int i=0, len=fromType.length; i < len; i++) {
+//                             buf.append(fromType[i]);
+//                             buf.append(".");
+//                     }
+               }
+               buf.append(name);
+               buf.append(arguments.toString());
+               return buf.toString();
+       }
+       
+
+       public void write(DataOutputStream s) throws IOException {
+               //XXX ignores onType
+               s.writeByte(Pointcut.REFERENCE);
+               if (onType != null) {
+                       s.writeBoolean(true);
+                       onType.write(s);
+               } else {
+                       s.writeBoolean(false);
+               }
+               
+               s.writeUTF(name);
+               arguments.write(s);
+               writeLocation(s);
+       }
+       
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               UnresolvedType onType = null;
+               if (s.readBoolean()) {
+                       onType = UnresolvedType.read(s);
+               }
+               ReferencePointcut ret = new ReferencePointcut(onType, s.readUTF(), 
+                                       TypePatternList.read(s, context));
+               ret.readLocation(context, s);
+               return ret;
+       }
+       
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               if (onTypeSymbolic != null) {
+                       onType = onTypeSymbolic.resolveExactType(scope, bindings);
+                       // in this case we've already signalled an error
+                       if (ResolvedType.isMissing(onType)) return;             
+               }
+               
+               ResolvedType searchType;
+               if (onType != null) {
+                       searchType = scope.getWorld().resolve(onType);
+               } else {
+                       searchType = scope.getEnclosingType();
+               }
+               if (searchType.isTypeVariableReference()) {
+                       searchType = ((TypeVariableReference)searchType).getTypeVariable().getUpperBound().resolve(scope.getWorld());
+               }
+               
+               
+               arguments.resolveBindings(scope, bindings, true, true);
+               //XXX ensure that arguments has no ..'s in it
+               
+               // check that I refer to a real pointcut declaration and that I match
+               
+               ResolvedPointcutDefinition pointcutDef = searchType.findPointcut(name);
+               // if we're not a static reference, then do a lookup of outers
+               if (pointcutDef == null && onType == null) {
+                       while (true) {
+                               UnresolvedType declaringType = searchType.getDeclaringType();
+                               if (declaringType == null) break;
+                               searchType = declaringType.resolve(scope.getWorld());
+                               pointcutDef = searchType.findPointcut(name);
+                               if (pointcutDef != null) {
+                                       // make this a static reference
+                                       onType = searchType;
+                                       break;
+                               }
+                       }
+               }
+               
+               if (pointcutDef == null) {
+                       scope.message(IMessage.ERROR, this, "can't find referenced pointcut " + name);
+                       return;
+               } 
+               
+               // check visibility
+               if (!pointcutDef.isVisible(scope.getEnclosingType())) {
+                       scope.message(IMessage.ERROR, this, "pointcut declaration " + pointcutDef + " is not accessible");
+                       return;
+               }
+               
+               if (Modifier.isAbstract(pointcutDef.getModifiers())) {
+                       if (onType != null  && !onType.isTypeVariableReference()) {
+                               scope.message(IMessage.ERROR, this, 
+                                                               "can't make static reference to abstract pointcut");
+                               return;
+                       } else if (!searchType.isAbstract()) {
+                               scope.message(IMessage.ERROR, this,
+                                                               "can't use abstract pointcut in concrete context");
+                               return;
+                       }
+               }
+               
+               
+               ResolvedType[] parameterTypes = 
+                       scope.getWorld().resolve(pointcutDef.getParameterTypes());
+               
+               if (parameterTypes.length != arguments.size()) {
+                       scope.message(IMessage.ERROR, this, "incompatible number of arguments to pointcut, expected " +
+                                               parameterTypes.length + " found " + arguments.size());
+                       return;
+               }
+                               
+               //if (onType == null) onType = pointcutDef.getDeclaringType();
+               if (onType != null) {
+                       if (onType.isParameterizedType()) {
+                               // build a type map mapping type variable names in the generic type to
+                               // the type parameters presented
+                               typeVariableMap = new HashMap();
+                               ResolvedType underlyingGenericType = ((ResolvedType) onType).getGenericType();
+                               TypeVariable[] tVars = underlyingGenericType.getTypeVariables();
+                               ResolvedType[] typeParams = ((ResolvedType)onType).getResolvedTypeParameters();
+                               for (int i = 0; i < tVars.length; i++) {
+                                       typeVariableMap.put(tVars[i].getName(),typeParams[i]);
+                               }
+                       } else if (onType.isGenericType()) {
+                               scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.CANT_REFERENCE_POINTCUT_IN_RAW_TYPE),
+                                               getSourceLocation()));
+                       } 
+               }
+               
+               for (int i=0,len=arguments.size(); i < len; i++) {
+                       TypePattern p = arguments.get(i);
+                       //we are allowed to bind to pointcuts which use subtypes as this is type safe
+                       if (typeVariableMap != null) {
+                               p = p.parameterizeWith(typeVariableMap,scope.getWorld());
+                       }
+                       if (p == TypePattern.NO) {
+                               scope.message(IMessage.ERROR, this,
+                                                               "bad parameter to pointcut reference");
+                               return;
+                       }
+                       
+                       boolean reportProblem = false;
+                       if (parameterTypes[i].isTypeVariableReference() && p.getExactType().isTypeVariableReference()) {
+                               UnresolvedType One = ((TypeVariableReference)parameterTypes[i]).getTypeVariable().getFirstBound();
+                               UnresolvedType Two = ((TypeVariableReference)p.getExactType()).getTypeVariable().getFirstBound();
+                               reportProblem = !One.resolve(scope.getWorld()).isAssignableFrom(Two.resolve(scope.getWorld()));
+                       } else {
+                               reportProblem = !p.matchesSubtypes(parameterTypes[i]) && 
+                           !p.getExactType().equals(UnresolvedType.OBJECT);
+                       }
+                       if (reportProblem) {
+                               scope.message(IMessage.ERROR, this, "incompatible type, expected " +
+                                               parameterTypes[i].getName() + " found " + p +".  Check the type specified in your pointcut");
+                               return;
+                       }
+               }
+
+       }
+       
+       public void postRead(ResolvedType enclosingType) {
+               arguments.postRead(enclosingType);
+       }
+
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               throw new RuntimeException("shouldn't happen");
+       }
+
+
+       //??? This is not thread safe, but this class is not designed for multi-threading
+       private boolean concretizing = false;
+       // declaring type is the type that declared the member referencing this pointcut.
+       // If it declares a matching private pointcut, then that pointcut should be used
+       // and not one in a subtype that happens to have the same name.
+       public Pointcut concretize1(ResolvedType searchStart, ResolvedType declaringType, IntMap bindings) {
+               if (concretizing) {
+                       //Thread.currentThread().dumpStack();
+                       searchStart.getWorld().getMessageHandler().handleMessage(
+                               MessageUtil.error(WeaverMessages.format(WeaverMessages.CIRCULAR_POINTCUT,this),
+                                                                       getSourceLocation()));
+                       return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+               }
+               
+               try {
+                       concretizing = true;
+               
+                       ResolvedPointcutDefinition pointcutDec;
+                       if (onType != null) {
+                               searchStart = onType.resolve(searchStart.getWorld());
+                               if (searchStart.isMissing()) {
+                                       return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+                               }
+                       
+                               if (onType.isTypeVariableReference()) {
+                                       // need to replace on type with the binding for the type variable
+                                       // in the declaring type
+                                       if (declaringType.isParameterizedType()) {
+                                               TypeVariable[] tvs = declaringType.getGenericType().getTypeVariables();
+                                               String typeVariableName = ((TypeVariableReference)onType).getTypeVariable().getName();
+                                               for (int i = 0; i < tvs.length; i++) {
+                                                       if (tvs[i].getName().equals(typeVariableName)) {
+                                                               ResolvedType realOnType = declaringType.getTypeParameters()[i].resolve(declaringType.getWorld());
+                                                               onType = realOnType;
+                                                               searchStart = realOnType;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                       }
+
+                       if (declaringType == null) declaringType = searchStart;
+                       pointcutDec = declaringType.findPointcut(name);
+                       boolean foundMatchingPointcut = (pointcutDec != null && pointcutDec.isPrivate());
+                       if (!foundMatchingPointcut) {                           
+                               pointcutDec = searchStart.findPointcut(name);
+                               if (pointcutDec == null) {
+                                       searchStart.getWorld().getMessageHandler().handleMessage(
+                                               MessageUtil.error(WeaverMessages.format(WeaverMessages.CANT_FIND_POINTCUT,name,searchStart.getName()), 
+                                                                               getSourceLocation())
+                                       );
+                                       return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+                               }
+                       }
+                       
+                       if (pointcutDec.isAbstract()) {
+                               //Thread.currentThread().dumpStack();
+                               ShadowMunger enclosingAdvice = bindings.getEnclosingAdvice();
+                               searchStart.getWorld().showMessage(IMessage.ERROR,
+                                               WeaverMessages.format(WeaverMessages.ABSTRACT_POINTCUT,pointcutDec), 
+                                               getSourceLocation(), 
+                                               (null == enclosingAdvice) ? null : enclosingAdvice.getSourceLocation());
+                               return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+                       }
+                                       
+                       //System.err.println("start: " + searchStart);
+//                     ResolvedType[] parameterTypes = searchStart.getWorld().resolve(pointcutDec.getParameterTypes());
+                       
+                       TypePatternList arguments = this.arguments.resolveReferences(bindings);
+                       
+                       IntMap newBindings = new IntMap();
+                       for (int i=0,len=arguments.size(); i < len; i++) {
+                               TypePattern p = arguments.get(i);
+                               if (p == TypePattern.NO) continue;
+                               // we are allowed to bind to pointcuts which use subtypes as this is type safe
+                               // this will be checked in ReferencePointcut.resolveBindings().  Can't check it here
+                               // as we don't know about any new parents added via decp.
+                           if (p instanceof BindingTypePattern) {
+                               newBindings.put(i, ((BindingTypePattern)p).getFormalIndex());
+                           }
+                       }
+
+                       if (searchStart.isParameterizedType()) {
+                               // build a type map mapping type variable names in the generic type to
+                               // the type parameters presented
+                               typeVariableMap = new HashMap();
+                               ResolvedType underlyingGenericType = searchStart.getGenericType();
+                               TypeVariable[] tVars = underlyingGenericType.getTypeVariables();
+                               ResolvedType[] typeParams = searchStart.getResolvedTypeParameters();
+                               for (int i = 0; i < tVars.length; i++) {
+                                       typeVariableMap.put(tVars[i].getName(),typeParams[i]);
+                               }
+                       }
+                       
+                       newBindings.copyContext(bindings);
+                       newBindings.pushEnclosingDefinition(pointcutDec);
+                       try {
+                               Pointcut ret = pointcutDec.getPointcut();
+                               if (typeVariableMap != null && !hasBeenParameterized) {                                 
+                                       ret = ret.parameterizeWith(typeVariableMap,searchStart.getWorld());
+                                       ret.hasBeenParameterized=true;
+                               }
+                               return ret.concretize(searchStart, declaringType, newBindings);
+                       } finally {
+                               newBindings.popEnclosingDefinitition();
+                       }
+                       
+               } finally {
+                       concretizing = false;
+               }
+       }
+
+       /**
+        * make a version of this pointcut with any refs to typeVariables replaced by their entry in the map.
+        * Tricky thing is, we can't do this at the point in time this method will be called, so we make a
+        * version that will parameterize the pointcut it ultimately resolves to.
+        */
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               ReferencePointcut ret = new ReferencePointcut(onType,name,arguments);
+               ret.onTypeSymbolic = onTypeSymbolic;
+               ret.typeVariableMap = typeVariableMap;
+               return ret;
+       }
+       
+    // We want to keep the original source location, not the reference location
+    protected boolean shouldCopyLocationForConcretize() {
+        return false;
+    }
+
+    public boolean equals(Object other) { 
+        if (!(other instanceof ReferencePointcut)) return false;
+        if (this == other) return true;
+        ReferencePointcut o = (ReferencePointcut)other;
+        return o.name.equals(name) && o.arguments.equals(arguments)
+            && ((o.onType == null) ? (onType == null) : o.onType.equals(onType));
+    }
+    public int hashCode() {
+        int result = 17;
+        result = 37*result + ((onType == null) ? 0 : onType.hashCode());
+        result = 37*result + arguments.hashCode();
+        result = 37*result + name.hashCode();
+        return result;
+    }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ScopeWithTypeVariables.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ScopeWithTypeVariables.java
new file mode 100644 (file)
index 0000000..537fb2c
--- /dev/null
@@ -0,0 +1,130 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.bridge.IMessage.Kind;
+import org.aspectj.weaver.IHasPosition;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.TypeVariable;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.UnresolvedTypeVariableReferenceType;
+import org.aspectj.weaver.World;
+
+/**
+ * A scope that also considers type variables when looking up a type.
+ *
+ */
+public class ScopeWithTypeVariables implements IScope {
+
+       private IScope delegateScope;
+       private String[] typeVariableNames;
+       private UnresolvedTypeVariableReferenceType[] typeVarTypeXs;
+       
+       public ScopeWithTypeVariables(String[] typeVarNames, IScope delegate) {
+               this.delegateScope = delegate;
+               this.typeVariableNames = typeVarNames;
+               this.typeVarTypeXs = new UnresolvedTypeVariableReferenceType[typeVarNames.length];
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#lookupType(java.lang.String, org.aspectj.weaver.IHasPosition)
+        */
+       public UnresolvedType lookupType(String name, IHasPosition location) {
+               for (int i = 0; i < typeVariableNames.length; i++) {
+                       if (typeVariableNames[i].equals(name)) {
+                               if (typeVarTypeXs[i] == null) {
+                                       typeVarTypeXs[i] = new UnresolvedTypeVariableReferenceType(new TypeVariable(name));
+                               }
+                               return typeVarTypeXs[i];
+                       }
+               }
+               return delegateScope.lookupType(name, location);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getWorld()
+        */
+       public World getWorld() {
+               return delegateScope.getWorld();
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getEnclosingType()
+        */
+       public ResolvedType getEnclosingType() {
+               return delegateScope.getEnclosingType();
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getMessageHandler()
+        */
+       public IMessageHandler getMessageHandler() {
+               return delegateScope.getMessageHandler();
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#lookupFormal(java.lang.String)
+        */
+       public FormalBinding lookupFormal(String name) {
+               return delegateScope.lookupFormal(name);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getFormal(int)
+        */
+       public FormalBinding getFormal(int i) {
+               return delegateScope.getFormal(i);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getFormalCount()
+        */
+       public int getFormalCount() {
+               return delegateScope.getFormalCount();
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getImportedPrefixes()
+        */
+       public String[] getImportedPrefixes() {
+               return delegateScope.getImportedPrefixes();
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getImportedNames()
+        */
+       public String[] getImportedNames() {
+               return delegateScope.getImportedNames();
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#message(org.aspectj.bridge.IMessage.Kind, org.aspectj.weaver.IHasPosition, java.lang.String)
+        */
+       public void message(Kind kind, IHasPosition location, String message) {
+               delegateScope.message(kind, location, message);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#message(org.aspectj.bridge.IMessage.Kind, org.aspectj.weaver.IHasPosition, org.aspectj.weaver.IHasPosition, java.lang.String)
+        */
+       public void message(Kind kind, IHasPosition location1,
+                       IHasPosition location2, String message) {
+               delegateScope.message(kind,location1,location2,message);
+       }
+
+       public void message(IMessage aMessage) {
+               delegateScope.message(aMessage);
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/SignaturePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/SignaturePattern.java
new file mode 100644 (file)
index 0000000..0643b48
--- /dev/null
@@ -0,0 +1,754 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AjAttribute; 
+import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.AnnotationTargetKind;
+import org.aspectj.weaver.ConcreteTypeMunger;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.JoinPointSignature;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.MemberKind;
+import org.aspectj.weaver.NewFieldTypeMunger;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+
+public class SignaturePattern extends PatternNode {
+       private MemberKind kind;
+       private ModifiersPattern modifiers;
+       private TypePattern returnType;
+    private TypePattern declaringType;
+       private NamePattern name;
+    private TypePatternList parameterTypes;
+    private ThrowsPattern throwsPattern;
+    private AnnotationTypePattern annotationPattern;
+    private transient int hashcode = -1;
+       
+       public SignaturePattern(MemberKind kind, ModifiersPattern modifiers,
+                                TypePattern returnType, TypePattern declaringType,
+                                NamePattern name, TypePatternList parameterTypes,
+                                ThrowsPattern throwsPattern,
+                                                        AnnotationTypePattern annotationPattern) {
+               this.kind = kind;
+               this.modifiers = modifiers;
+               this.returnType = returnType;
+               this.name = name;
+               this.declaringType = declaringType;
+               this.parameterTypes = parameterTypes;
+               this.throwsPattern = throwsPattern;
+               this.annotationPattern = annotationPattern;
+       }
+       
+       
+    public SignaturePattern resolveBindings(IScope scope, Bindings bindings) { 
+               if (returnType != null) {
+                       returnType = returnType.resolveBindings(scope, bindings, false, false);
+                       checkForIncorrectTargetKind(returnType,scope,false);
+               } 
+               if (declaringType != null) {
+                       declaringType = declaringType.resolveBindings(scope, bindings, false, false);
+                       checkForIncorrectTargetKind(declaringType,scope,false);
+               }
+               if (parameterTypes != null) {
+                       parameterTypes = parameterTypes.resolveBindings(scope, bindings, false, false);
+                       checkForIncorrectTargetKind(parameterTypes,scope,false,true);
+               }
+               if (throwsPattern != null) {
+                       throwsPattern = throwsPattern.resolveBindings(scope, bindings);
+                       if (throwsPattern.getForbidden().getTypePatterns().length > 0 
+                                       || throwsPattern.getRequired().getTypePatterns().length > 0) {
+                               checkForIncorrectTargetKind(throwsPattern,scope,false);                         
+                       }
+               }
+               if (annotationPattern != null) {
+                       annotationPattern = annotationPattern.resolveBindings(scope,bindings,false);
+                       checkForIncorrectTargetKind(annotationPattern,scope,true);
+               }
+               hashcode =-1;
+       return this;
+    }
+    private void checkForIncorrectTargetKind(PatternNode patternNode, IScope scope, boolean targetsOtherThanTypeAllowed) {
+       checkForIncorrectTargetKind(patternNode, scope, targetsOtherThanTypeAllowed, false);
+       
+    }
+    
+    // bug 115252 - adding an xlint warning if the annnotation target type is 
+    // wrong. This logic, or similar, may have to be applied elsewhere in the case
+    // of pointcuts which don't go through SignaturePattern.resolveBindings(..)
+    private void checkForIncorrectTargetKind(PatternNode patternNode, IScope scope, boolean targetsOtherThanTypeAllowed, boolean parameterTargettingAnnotationsAllowed) {
+       // return if we're not in java5 mode, if the unmatchedTargetKind Xlint
+       // warning has been turned off, or if the patternNode is *
+       if (!scope.getWorld().isInJava5Mode()
+                       || scope.getWorld().getLint().unmatchedTargetKind == null
+                       || (patternNode instanceof AnyTypePattern)) {
+                       return;
+               }
+               if (patternNode instanceof ExactAnnotationTypePattern) {
+                       ResolvedType resolvedType = ((ExactAnnotationTypePattern)patternNode).getAnnotationType().resolve(scope.getWorld());
+                       if (targetsOtherThanTypeAllowed) {
+                               AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds();
+                               if (targetKinds == null) return;
+                               reportUnmatchedTargetKindMessage(targetKinds,patternNode,scope,true);
+                       } else if (!targetsOtherThanTypeAllowed && !resolvedType.canAnnotationTargetType()) {
+                               // everything is incorrect since we've already checked whether we have the TYPE target annotation
+                               AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds();
+                               if (targetKinds == null) return;
+                               reportUnmatchedTargetKindMessage(targetKinds,patternNode,scope,false);
+                       }
+               } else {
+                       TypePatternVisitor visitor = new TypePatternVisitor(scope,targetsOtherThanTypeAllowed,parameterTargettingAnnotationsAllowed);
+                       patternNode.traverse(visitor,null);
+                       if (visitor.containedIncorrectTargetKind()) {
+                               Set keys = visitor.getIncorrectTargetKinds().keySet();                          
+                               for (Iterator iter = keys.iterator(); iter.hasNext();) {
+                                       PatternNode node = (PatternNode)iter.next();
+                                       AnnotationTargetKind[] targetKinds =  (AnnotationTargetKind[]) visitor.getIncorrectTargetKinds().get(node);
+                                       reportUnmatchedTargetKindMessage(targetKinds,node,scope,false);
+                               }
+                       }
+               }
+    }
+    
+    private void reportUnmatchedTargetKindMessage(
+               AnnotationTargetKind[] annotationTargetKinds,  
+               PatternNode node,
+               IScope scope,
+               boolean checkMatchesMemberKindName) {
+       StringBuffer targetNames = new StringBuffer("{");
+       for (int i = 0; i < annotationTargetKinds.length; i++) {
+                       AnnotationTargetKind targetKind = annotationTargetKinds[i];
+                       if (checkMatchesMemberKindName && kind.getName().equals(targetKind.getName())) {
+                               return;
+                       }
+                       if (i < (annotationTargetKinds.length - 1)) {
+                               targetNames.append("ElementType." + targetKind.getName() + ",");
+                       } else {
+                               targetNames.append("ElementType." + targetKind.getName() + "}");
+                       }
+               }
+               scope.getWorld().getLint().unmatchedTargetKind.signal(new String[] {node.toString(),targetNames.toString()}, getSourceLocation(), new ISourceLocation[0]);
+    }
+    
+    /**
+     * Class which visits the nodes in the TypePattern tree until an
+     * ExactTypePattern is found. Once this is found it creates a new
+     * ExactAnnotationTypePattern and checks whether the targetKind
+     * (created via the @Target annotation) matches ElementType.TYPE if
+     * this is the only target kind which is allowed, or matches the
+     * signature pattern kind if there is no restriction.
+     */
+    private class TypePatternVisitor extends AbstractPatternNodeVisitor {
+
+       private IScope scope;
+       private Map incorrectTargetKinds /* PatternNode -> AnnotationTargetKind[] */ = new HashMap();
+       private boolean targetsOtherThanTypeAllowed;
+               private boolean parameterTargettingAnnotationsAllowed;
+
+       /**
+        * @param requiredTarget - the signature pattern Kind
+        * @param scope
+        * @param parameterTargettingAnnotationsAllowed 
+        */
+       public TypePatternVisitor(IScope scope, boolean targetsOtherThanTypeAllowed, boolean parameterTargettingAnnotationsAllowed) {
+               this.scope = scope;
+               this.targetsOtherThanTypeAllowed = targetsOtherThanTypeAllowed;
+               this.parameterTargettingAnnotationsAllowed = parameterTargettingAnnotationsAllowed;
+       }
+       
+       public Object visit(WildAnnotationTypePattern node, Object data) {
+               node.getTypePattern().accept(this,data);
+               return node;
+       }
+       
+       /**
+        * Do the ExactAnnotationTypePatterns have the incorrect target?
+        */
+       public Object visit(ExactAnnotationTypePattern node, Object data) {
+               ResolvedType resolvedType = node.getAnnotationType().resolve(scope.getWorld());
+                       if (targetsOtherThanTypeAllowed) {
+                               AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds();
+                               if (targetKinds == null) return data;
+                               List incorrectTargets = new ArrayList();
+                               for (int i = 0; i < targetKinds.length; i++) {
+                                       if (targetKinds[i].getName().equals(kind.getName()) ||
+                                                       (targetKinds[i].getName().equals("PARAMETER") && node.isForParameterAnnotationMatch())
+                                                       ) {
+                                               return data;
+                                       }
+                                       incorrectTargets.add(targetKinds[i]);
+                               }
+                               if (incorrectTargets.isEmpty()) return data;
+                               AnnotationTargetKind[] kinds = new AnnotationTargetKind[incorrectTargets.size()];
+                               incorrectTargetKinds.put(node,(AnnotationTargetKind[]) incorrectTargets.toArray(kinds));        
+                       } else if (!targetsOtherThanTypeAllowed && !resolvedType.canAnnotationTargetType()) {
+                               AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds();
+                               if (targetKinds == null) return data;
+                               // exception here is if parameter annotations are allowed
+                               if (parameterTargettingAnnotationsAllowed) {
+                                       for (int i = 0; i < targetKinds.length; i++) {
+                                               AnnotationTargetKind annotationTargetKind = targetKinds[i];
+                                               if (annotationTargetKind.getName().equals("PARAMETER")  && node.isForParameterAnnotationMatch()) return data;
+                                       }
+                               }
+                               incorrectTargetKinds.put(node,targetKinds);
+                       }
+               return data;
+       }
+       
+       public Object visit(ExactTypePattern node, Object data) {
+               ExactAnnotationTypePattern eatp =  new ExactAnnotationTypePattern(node.getExactType().resolve(scope.getWorld()),null);
+               eatp.accept(this,data);         
+               return data;
+       }
+       
+       public Object visit(AndTypePattern node, Object data) {
+               node.getLeft().accept(this,data);
+               node.getRight().accept(this,data);
+               return node;
+       }
+
+       public Object visit(OrTypePattern node, Object data) {
+               node.getLeft().accept(this,data);
+               node.getRight().accept(this,data);
+               return node;
+       }
+
+       public Object visit(AnyWithAnnotationTypePattern node, Object data) {
+               node.getAnnotationPattern().accept(this,data);
+               return node;
+       }
+       
+       public boolean containedIncorrectTargetKind() {
+               return (incorrectTargetKinds.size() != 0);
+       }
+       
+       public Map getIncorrectTargetKinds() {
+               return incorrectTargetKinds;
+       }
+    }
+    
+    
+       public void postRead(ResolvedType enclosingType) {
+               if (returnType != null) {
+                       returnType.postRead(enclosingType);
+               } 
+               if (declaringType != null) {
+                       declaringType.postRead(enclosingType);
+               }
+               if (parameterTypes != null) {
+                       parameterTypes.postRead(enclosingType);
+               }
+       }
+       
+       /**
+        * return a copy of this signature pattern in which every type variable reference
+        * is replaced by the corresponding entry in the map.
+        */
+       public SignaturePattern parameterizeWith(Map typeVariableMap,World w) {
+               SignaturePattern ret = new SignaturePattern(
+                                               kind,
+                                               modifiers,
+                                               returnType.parameterizeWith(typeVariableMap,w),
+                                               declaringType.parameterizeWith(typeVariableMap,w),
+                                               name,
+                                               parameterTypes.parameterizeWith(typeVariableMap,w),
+                                               throwsPattern.parameterizeWith(typeVariableMap,w),
+                                               annotationPattern.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public boolean matches(Member joinPointSignature, World world, boolean allowBridgeMethods) {
+               // fail (or succeed!) fast tests...
+               if (joinPointSignature == null) return false;
+               if (kind != joinPointSignature.getKind()) return false;
+               if (kind == Member.ADVICE) return true;
+               
+               // do the hard work then...
+               boolean subjectMatch = true;
+               Iterator candidateMatches = joinPointSignature.getJoinPointSignatures(world);
+               while(candidateMatches.hasNext()) {
+                       JoinPointSignature aSig = (JoinPointSignature) candidateMatches.next();
+                       FuzzyBoolean matchResult = matchesExactly(aSig,world,allowBridgeMethods,subjectMatch); 
+                       if (matchResult.alwaysTrue()) {
+                               return true;
+                       } else if (matchResult.alwaysFalse()) {
+                               return false;
+                       }
+                       // if we got a "MAYBE" it's worth looking at the other signatures
+                       subjectMatch = false;
+               }
+               return false;
+       }
+       
+       // Does this pattern match this exact signature (no declaring type mucking about
+       // or chasing up the hierarchy)
+       // return YES if it does, NO if it doesn't and no ancester member could match either,
+       // and MAYBE if it doesn't but an ancester member could.
+       private FuzzyBoolean matchesExactly(JoinPointSignature aMember, World inAWorld, boolean allowBridgeMethods,boolean subjectMatch) {
+               // Java5 introduces bridge methods, we match a call to them but nothing else...
+               if (aMember.isBridgeMethod() && !allowBridgeMethods) {
+                       return FuzzyBoolean.MAYBE;
+               }
+                       
+               // modifiers match on the *subject*
+               if (subjectMatch && !modifiers.matches(aMember.getModifiers())) {
+                       return FuzzyBoolean.NO;
+//                     if (aMember.isPrivate()) return FuzzyBoolean.NO;
+//                     else return FuzzyBoolean.MAYBE;
+               }
+               
+               
+               FuzzyBoolean matchesIgnoringAnnotations = FuzzyBoolean.YES;
+               if (kind == Member.STATIC_INITIALIZATION) {
+                       matchesIgnoringAnnotations = matchesExactlyStaticInitialization(aMember, inAWorld);
+               } else if (kind == Member.FIELD) {
+                       matchesIgnoringAnnotations = matchesExactlyField(aMember,inAWorld);
+               } else if (kind == Member.METHOD) {
+                       matchesIgnoringAnnotations = matchesExactlyMethod(aMember,inAWorld, subjectMatch);
+               } else if (kind == Member.CONSTRUCTOR) {
+                       matchesIgnoringAnnotations = matchesExactlyConstructor(aMember, inAWorld);
+               }
+               if (matchesIgnoringAnnotations.alwaysFalse()) return FuzzyBoolean.NO;
+               
+               // why did Adrian put this comment in:
+               // annotations match on the *subject* 
+               // surely you never want execution(@Something * *(..)) to match something just because
+               // it is a secondary join point signature for a join point and doesn't have the annotation?
+               // pr239441
+               if (matchesIgnoringAnnotations.alwaysTrue()) {
+                       return matchesAnnotations(aMember,inAWorld);
+               } else {
+                       return matchesIgnoringAnnotations;
+               }
+               
+       }
+       
+       /**
+        * Matches on declaring type
+        */
+       private FuzzyBoolean matchesExactlyStaticInitialization(JoinPointSignature aMember,World world) {
+               return FuzzyBoolean.fromBoolean(declaringType.matchesStatically(aMember.getDeclaringType().resolve(world)));
+       }
+       
+       /**
+        * Matches on name, declaring type, field type
+        */
+       private FuzzyBoolean matchesExactlyField(JoinPointSignature aField, World world) {
+               if (!name.matches(aField.getName())) return FuzzyBoolean.NO;
+               ResolvedType fieldDeclaringType = aField.getDeclaringType().resolve(world);
+               if (!declaringType.matchesStatically(fieldDeclaringType)) {
+                       return FuzzyBoolean.MAYBE;
+               }
+               if (!returnType.matchesStatically(aField.getReturnType().resolve(world))) {
+                       // looking bad, but there might be parameterization to consider...
+                       if (!returnType.matchesStatically(aField.getGenericReturnType().resolve(world))) {
+                               // ok, it's bad.
+                               return FuzzyBoolean.MAYBE;
+                       }
+               }
+               // passed all the guards...
+               return FuzzyBoolean.YES;
+       }
+       
+       /**
+        * Matches on name, declaring type, return type, parameter types, throws types
+        */
+       private FuzzyBoolean matchesExactlyMethod(JoinPointSignature aMethod, World world, boolean subjectMatch) {
+               if (!name.matches(aMethod.getName())) return FuzzyBoolean.NO;
+               // Check the throws pattern
+               if (subjectMatch && !throwsPattern.matches(aMethod.getExceptions(), world)) return FuzzyBoolean.NO;
+               
+               if (!declaringType.matchesStatically(aMethod.getDeclaringType().resolve(world))) return FuzzyBoolean.MAYBE;
+               if (!returnType.matchesStatically(aMethod.getReturnType().resolve(world))) {
+                       // looking bad, but there might be parameterization to consider...
+                       if (!returnType.matchesStatically(aMethod.getGenericReturnType().resolve(world))) {
+                               // ok, it's bad.
+                               return FuzzyBoolean.MAYBE;
+                       }
+               }
+               if (!parameterTypes.canMatchSignatureWithNParameters(aMethod.getParameterTypes().length)) return FuzzyBoolean.NO;
+               ResolvedType[] resolvedParameters = world.resolve(aMethod.getParameterTypes());
+               ResolvedType[][] parameterAnnotationTypes = aMethod.getParameterAnnotationTypes();
+               if (parameterAnnotationTypes==null || parameterAnnotationTypes.length==0) parameterAnnotationTypes=null;
+               if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC,parameterAnnotationTypes).alwaysTrue()) {
+                       // It could still be a match based on the generic sig parameter types of a parameterized type
+                       if (!parameterTypes.matches(world.resolve(aMethod.getGenericParameterTypes()),TypePattern.STATIC,parameterAnnotationTypes).alwaysTrue()) {
+                               return FuzzyBoolean.MAYBE;
+                               // It could STILL be a match based on the erasure of the parameter types??
+                               // to be determined via test cases...
+                       }
+               }
+               
+               // check that varargs specifications match
+               if (!matchesVarArgs(aMethod,world)) return FuzzyBoolean.MAYBE;
+               
+               // passed all the guards..
+               return FuzzyBoolean.YES;
+       }
+       
+
+
+       /**
+        * match on declaring type, parameter types, throws types
+        */
+       private FuzzyBoolean matchesExactlyConstructor(JoinPointSignature aConstructor, World world) {
+               if (!declaringType.matchesStatically(aConstructor.getDeclaringType().resolve(world))) return FuzzyBoolean.NO;
+
+               if (!parameterTypes.canMatchSignatureWithNParameters(aConstructor.getParameterTypes().length)) return FuzzyBoolean.NO;
+               ResolvedType[] resolvedParameters = world.resolve(aConstructor.getParameterTypes());
+               
+               ResolvedType[][] parameterAnnotationTypes = aConstructor.getParameterAnnotationTypes();
+
+               if (parameterAnnotationTypes==null || parameterAnnotationTypes.length==0) parameterAnnotationTypes=null;
+
+               if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC,parameterAnnotationTypes).alwaysTrue()) {
+                       // It could still be a match based on the generic sig parameter types of a parameterized type
+                       if (!parameterTypes.matches(world.resolve(aConstructor.getGenericParameterTypes()),TypePattern.STATIC).alwaysTrue()) {
+                               return FuzzyBoolean.MAYBE;
+                               // It could STILL be a match based on the erasure of the parameter types??
+                               // to be determined via test cases...
+                       }
+               }
+               
+               // check that varargs specifications match
+               if (!matchesVarArgs(aConstructor,world)) return FuzzyBoolean.NO;
+               
+               // Check the throws pattern
+               if (!throwsPattern.matches(aConstructor.getExceptions(), world)) return FuzzyBoolean.NO;
+               
+               // passed all the guards..
+               return FuzzyBoolean.YES;                
+       }
+       
+       /**
+        * We've matched against this method or constructor so far, but without considering
+        * varargs (which has been matched as a simple array thus far). Now we do the additional
+        * checks to see if the parties agree on whether the last parameter is varargs or a 
+        * straight array. 
+        */
+       private boolean matchesVarArgs(JoinPointSignature aMethodOrConstructor, World inAWorld) {
+               if (parameterTypes.size() == 0) return true;
+               
+               TypePattern lastPattern = parameterTypes.get(parameterTypes.size()-1);
+               boolean canMatchVarArgsSignature = lastPattern.isStar() || 
+                                                   lastPattern.isVarArgs() ||
+                                                   (lastPattern == TypePattern.ELLIPSIS);
+               
+               if (aMethodOrConstructor.isVarargsMethod()) {
+                       // we have at least one parameter in the pattern list, and the method has a varargs signature
+                       if (!canMatchVarArgsSignature) {
+                               // XXX - Ideally the shadow would be included in the msg but we don't know it...
+                               inAWorld.getLint().cantMatchArrayTypeOnVarargs.signal(aMethodOrConstructor.toString(),getSourceLocation());
+                               return false;
+                       }
+               } else {
+                       // the method ends with an array type, check that we don't *require* a varargs
+                       if (lastPattern.isVarArgs()) return false;
+               }
+
+               return true;
+       }
+               
+       private FuzzyBoolean matchesAnnotations(ResolvedMember member,World world) {
+         if (member == null) {
+            //                 world.getLint().unresolvableMember.signal(member.toString(), getSourceLocation());
+                       return FuzzyBoolean.NO;
+         }
+         annotationPattern.resolve(world);
+        
+         // optimization before we go digging around for annotations on ITDs
+         if (annotationPattern instanceof AnyAnnotationTypePattern) return FuzzyBoolean.YES;
+         
+         // fake members represent ITD'd fields - for their annotations we should go and look up the
+         // relevant member in the original aspect
+         if (member.isAnnotatedElsewhere() && member.getKind()==Member.FIELD) {
+           // FIXME asc duplicate of code in AnnotationPointcut.matchInternal()?  same fixmes apply here.
+//         ResolvedMember [] mems = member.getDeclaringType().resolve(world).getDeclaredFields(); // FIXME asc should include supers with getInterTypeMungersIncludingSupers?
+           List mungers = member.getDeclaringType().resolve(world).getInterTypeMungers(); 
+               for (Iterator iter = mungers.iterator(); iter.hasNext();) {
+               ConcreteTypeMunger typeMunger = (ConcreteTypeMunger) iter.next();
+                       if (typeMunger.getMunger() instanceof NewFieldTypeMunger) {
+                         ResolvedMember fakerm = typeMunger.getSignature();
+                         ResolvedMember ajcMethod = AjcMemberMaker.interFieldInitializer(fakerm,typeMunger.getAspectType());
+                         ResolvedMember rmm       = findMethod(typeMunger.getAspectType(),ajcMethod);
+                         if (fakerm.equals(member)) {
+                               member = rmm;
+                         }
+                       }
+               }
+         }
+         
+         if (annotationPattern.matches(member).alwaysTrue()) {
+                 return FuzzyBoolean.YES;
+         } else {
+                 return FuzzyBoolean.NO;  // do NOT look at ancestor members...
+         }
+       }
+       
+       private ResolvedMember findMethod(ResolvedType aspectType, ResolvedMember ajcMethod) {
+              ResolvedMember decMethods[] = aspectType.getDeclaredMethods();
+              for (int i = 0; i < decMethods.length; i++) {
+                       ResolvedMember member = decMethods[i];
+                       if (member.equals(ajcMethod)) return member;
+          }
+                       return null;
+       }
+       
+       public boolean declaringTypeMatchAllowingForCovariance(Member member, UnresolvedType shadowDeclaringType, World world,TypePattern returnTypePattern,ResolvedType sigReturn) {
+               
+               ResolvedType onType = shadowDeclaringType.resolve(world);
+                       
+               // fastmatch
+               if (declaringType.matchesStatically(onType) && returnTypePattern.matchesStatically(sigReturn)) 
+                       return true;
+                       
+               Collection declaringTypes = member.getDeclaringTypes(world);
+               
+               boolean checkReturnType = true;
+               // XXX Possible enhancement?  Doesn't seem to speed things up
+               //      if (returnTypePattern.isStar()) {
+               //              if (returnTypePattern instanceof WildTypePattern) {
+               //                      if (((WildTypePattern)returnTypePattern).getDimensions()==0) checkReturnType = false;
+               //              }
+               //      }
+                       
+               // Sometimes that list includes types that don't explicitly declare the member we are after -
+               // they are on the list because their supertype is on the list, that's why we use
+               // lookupMethod rather than lookupMemberNoSupers()
+               for (Iterator i = declaringTypes.iterator(); i.hasNext(); ) {
+                       ResolvedType type = (ResolvedType)i.next();
+                       if (declaringType.matchesStatically(type)) {
+                         if (!checkReturnType) return true;
+                         ResolvedMember rm = type.lookupMethod(member);
+                         if (rm==null)  rm = type.lookupMethodInITDs(member); // It must be in here, or we have *real* problems
+                         if (rm==null) continue; // might be currently looking at the generic type and we need to continue searching in case we hit a parameterized version of this same type...
+                         UnresolvedType returnTypeX = rm.getReturnType();
+                         ResolvedType returnType = returnTypeX.resolve(world);
+                         if (returnTypePattern.matchesStatically(returnType)) return true;
+                       }
+               }
+               return false;
+       }
+       
+//     private Collection getDeclaringTypes(Signature sig) {
+//             List l = new ArrayList();
+//             Class onType = sig.getDeclaringType();
+//             String memberName = sig.getName();
+//             if (sig instanceof FieldSignature) {
+//                     Class fieldType = ((FieldSignature)sig).getFieldType();
+//                     Class superType = onType;
+//                     while(superType != null) {
+//                             try {
+//                                     Field f =  (superType.getDeclaredField(memberName));
+//                                     if (f.getType() == fieldType) {
+//                                             l.add(superType);
+//                                     }
+//                             } catch (NoSuchFieldException nsf) {}
+//                             superType = superType.getSuperclass();
+//                     }
+//             } else if (sig instanceof MethodSignature) {
+//                     Class[] paramTypes = ((MethodSignature)sig).getParameterTypes();
+//                     Class superType = onType;
+//                     while(superType != null) {
+//                             try {
+//                                     superType.getDeclaredMethod(memberName,paramTypes);
+//                                     l.add(superType);
+//                             } catch (NoSuchMethodException nsm) {}
+//                             superType = superType.getSuperclass();
+//                     }
+//             }
+//             return l;
+//     }
+       
+    public NamePattern getName() { return name; }
+    public TypePattern getDeclaringType() { return declaringType; }
+    
+    public MemberKind getKind() {
+       return kind;
+    }
+    
+    public String toString() {
+       StringBuffer buf = new StringBuffer();
+       
+       if (annotationPattern != AnnotationTypePattern.ANY) {
+                       buf.append(annotationPattern.toString());
+                       buf.append(' ');
+       }
+       
+       if (modifiers != ModifiersPattern.ANY) {
+               buf.append(modifiers.toString());
+               buf.append(' ');
+       }
+       
+       if (kind == Member.STATIC_INITIALIZATION) {
+               buf.append(declaringType.toString());
+               buf.append(".<clinit>()");//FIXME AV - bad, cannot be parsed again
+       } else if (kind == Member.HANDLER) {
+               buf.append("handler(");
+               buf.append(parameterTypes.get(0));
+               buf.append(")");
+       } else {
+               if (!(kind == Member.CONSTRUCTOR)) {
+                       buf.append(returnType.toString());
+                   buf.append(' ');
+               }
+               if (declaringType != TypePattern.ANY) {
+                       buf.append(declaringType.toString());
+                       buf.append('.');
+               }
+               if (kind == Member.CONSTRUCTOR) {
+                       buf.append("new");
+               } else {
+                   buf.append(name.toString());
+               }
+               if (kind == Member.METHOD || kind == Member.CONSTRUCTOR) {
+                       buf.append(parameterTypes.toString());
+               }
+            //FIXME AV - throws is not printed here, weird
+       }
+       return buf.toString();
+    }
+    
+    public boolean equals(Object other) {
+       if (!(other instanceof SignaturePattern)) return false;
+       SignaturePattern o = (SignaturePattern)other;
+       return o.kind.equals(this.kind)
+               && o.modifiers.equals(this.modifiers)
+               && o.returnType.equals(this.returnType)
+               && o.declaringType.equals(this.declaringType)
+               && o.name.equals(this.name)
+               && o.parameterTypes.equals(this.parameterTypes)
+                       && o.throwsPattern.equals(this.throwsPattern)
+                       && o.annotationPattern.equals(this.annotationPattern);
+    }
+    public int hashCode() {
+       if (hashcode==-1) {
+          hashcode = 17;
+          hashcode = 37*hashcode + kind.hashCode();
+          hashcode = 37*hashcode + modifiers.hashCode();
+          hashcode = 37*hashcode + returnType.hashCode();
+          hashcode = 37*hashcode + declaringType.hashCode();
+          hashcode = 37*hashcode + name.hashCode();
+          hashcode = 37*hashcode + parameterTypes.hashCode();
+          hashcode = 37*hashcode + throwsPattern.hashCode();
+          hashcode = 37*hashcode + annotationPattern.hashCode();
+       }
+        return hashcode;
+    }
+    
+       public void write(DataOutputStream s) throws IOException {
+               kind.write(s);
+               modifiers.write(s);
+               returnType.write(s);
+               declaringType.write(s);
+               name.write(s);
+               parameterTypes.write(s);
+               throwsPattern.write(s);
+               annotationPattern.write(s);
+               writeLocation(s);
+       }
+
+       public static SignaturePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               MemberKind kind = MemberKind.read(s);
+               ModifiersPattern modifiers = ModifiersPattern.read(s);
+               TypePattern returnType = TypePattern.read(s, context);
+               TypePattern declaringType = TypePattern.read(s, context);
+               NamePattern name = NamePattern.read(s);
+               TypePatternList parameterTypes = TypePatternList.read(s, context);
+               ThrowsPattern throwsPattern = ThrowsPattern.read(s, context);
+               
+               AnnotationTypePattern annotationPattern = AnnotationTypePattern.ANY;
+               
+               if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
+                 annotationPattern = AnnotationTypePattern.read(s,context);
+               }
+
+               SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType,
+                                       name, parameterTypes, throwsPattern,annotationPattern);
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       /**
+        * @return
+        */
+       public ModifiersPattern getModifiers() {
+               return modifiers;
+       }
+
+       /**
+        * @return
+        */
+       public TypePatternList getParameterTypes() {
+               return parameterTypes;
+       }
+
+       /**
+        * @return
+        */
+       public TypePattern getReturnType() {
+               return returnType;
+       }
+
+       /**
+        * @return
+        */
+       public ThrowsPattern getThrowsPattern() {
+               return throwsPattern;
+       }
+       
+       /**
+        * return true if last argument in params is an Object[] but the modifiers say this method
+        * was declared with varargs (Object...).  We shouldn't be matching if this is the case.
+        */
+//     private boolean matchedArrayAgainstVarArgs(TypePatternList params,int modifiers) {
+//             if (params.size()>0 && (modifiers & Constants.ACC_VARARGS)!=0) {
+//                     // we have at least one parameter in the pattern list, and the method has a varargs signature
+//                     TypePattern lastPattern = params.get(params.size()-1);
+//                     if (lastPattern.isArray() && !lastPattern.isVarArgs) return true;
+//             }
+//         return false;
+//     }
+       
+       public AnnotationTypePattern getAnnotationPattern() {
+               return annotationPattern;
+       }
+
+
+       public boolean isStarAnnotation() {
+               return annotationPattern == AnnotationTypePattern.ANY;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/SimpleScope.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/SimpleScope.java
new file mode 100644 (file)
index 0000000..08e3e70
--- /dev/null
@@ -0,0 +1,151 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.Message;
+import org.aspectj.bridge.SourceLocation;
+import org.aspectj.weaver.IHasPosition;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.World;
+
+public class SimpleScope implements IScope {
+
+    private World world;
+    private ResolvedType enclosingType;
+    protected FormalBinding[] bindings;
+
+       private String[] importedPrefixes = javaLangPrefixArray;
+       private String[] importedNames = ZERO_STRINGS;
+       private static final String[] ZERO_STRINGS = new String[0];
+       
+       private static final String[] javaLangPrefixArray =
+               new String[] { "java.lang.", };
+
+
+       
+    public SimpleScope(World world, FormalBinding[] bindings) {
+        super();
+        this.world = world;
+        this.bindings = bindings;
+    }
+
+       // ---- impl
+
+       //XXX doesn't report any problems
+       public UnresolvedType lookupType(String name, IHasPosition location) {
+               for (int i=0; i<importedNames.length; i++) {
+                       String importedName = importedNames[i];
+//                     // make sure we're matching against the
+//                     // type name rather than part of it
+//                     if (importedName.endsWith("." + name)) {
+                       if (importedName.endsWith(name)) {
+                               return world.resolve(importedName);
+                       }
+               }
+               
+               for (int i=0; i<importedPrefixes.length; i++) {
+                       String importedPrefix = importedPrefixes[i];
+                       ResolvedType tryType = world.resolve(UnresolvedType.forName(importedPrefix + name), true);
+                       if (!tryType.isMissing()) {
+                               return tryType;
+                       }
+               }
+
+               return world.resolve(UnresolvedType.forName(name), true);
+       }
+
+
+    public IMessageHandler getMessageHandler() {
+        return world.getMessageHandler();
+    }
+    public FormalBinding lookupFormal(String name) {
+        for (int i = 0, len = bindings.length; i < len; i++) {
+            if (bindings[i].getName().equals(name)) return bindings[i];
+        }
+        return null;
+    }
+    public FormalBinding getFormal(int i) {
+        return bindings[i];
+    }
+    
+    public int getFormalCount() {
+       return bindings.length;
+    }
+
+       public String[] getImportedNames() {
+               return importedNames;
+       }
+       public String[] getImportedPrefixes() {
+               return importedPrefixes;
+       }
+       
+       public void setImportedNames(String[] importedNames) {
+               this.importedNames = importedNames;
+       }
+       public void setImportedPrefixes(String[] importedPrefixes) {
+               this.importedPrefixes = importedPrefixes;
+       }
+       
+       public static FormalBinding[] makeFormalBindings(UnresolvedType[] types, String[] names) {
+        int len = types.length;
+        FormalBinding[] bindings = new FormalBinding[len];
+        for (int i = 0; i < len; i++) {
+            bindings[i] = new FormalBinding(types[i], names[i], i);
+        }
+        return bindings;
+       }
+       
+       // ---- fields
+       
+
+
+       public ISourceLocation makeSourceLocation(IHasPosition location) {
+               return new SourceLocation(ISourceLocation.NO_FILE, 0);
+       }
+
+       public void message(
+               IMessage.Kind kind,
+               IHasPosition location1,
+               IHasPosition location2,
+               String message) {
+                       message(kind, location1, message);
+                       message(kind, location2, message);
+       }
+
+       public void message(
+               IMessage.Kind kind,
+               IHasPosition location,
+               String message) {
+                       getMessageHandler()
+                       .handleMessage(new Message(message, kind, null, makeSourceLocation(location)));
+
+       }
+       
+       public void message(IMessage aMessage) {
+               getMessageHandler().handleMessage(aMessage);
+       }
+       
+       public World getWorld() {
+               return world;
+       }
+
+       public ResolvedType getEnclosingType() {
+               return enclosingType;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java
new file mode 100644 (file)
index 0000000..350a192
--- /dev/null
@@ -0,0 +1,287 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.ShadowMunger;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.ast.Var;
+
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
+
+       private boolean isThis;
+       private boolean alreadyWarnedAboutDEoW = false;
+       private ExactAnnotationTypePattern annotationTypePattern;
+       private String declarationText;
+       
+       private static final int thisKindSet;
+       private static final int targetKindSet;
+       
+       static {
+               int thisFlags = Shadow.ALL_SHADOW_KINDS_BITS;
+               int targFlags = Shadow.ALL_SHADOW_KINDS_BITS;
+               for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
+                       Shadow.Kind kind = Shadow.SHADOW_KINDS[i];
+                       if (kind.neverHasThis()) thisFlags-=kind.bit;
+                       if (kind.neverHasTarget()) targFlags-=kind.bit;
+               }
+               thisKindSet = thisFlags;
+               targetKindSet=targFlags;
+       }
+       
+       /**
+        * 
+        */
+       public ThisOrTargetAnnotationPointcut(boolean isThis, ExactAnnotationTypePattern type) {
+               super();
+               this.isThis = isThis;
+               this.annotationTypePattern = type;
+               this.pointcutKind = ATTHIS_OR_TARGET;
+               buildDeclarationText();
+       }
+
+       public ThisOrTargetAnnotationPointcut(boolean isThis, ExactAnnotationTypePattern type, ShadowMunger munger) {
+           this(isThis,type);
+       }
+
+    public ExactAnnotationTypePattern getAnnotationTypePattern() {
+        return annotationTypePattern;
+    }
+
+       public int couldMatchKinds() {
+               return isThis ? thisKindSet : targetKindSet;
+       }
+       
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               ExactAnnotationTypePattern newPattern = (ExactAnnotationTypePattern) this.annotationTypePattern.parameterizeWith(typeVariableMap,w);
+               if (newPattern.getAnnotationType() instanceof ResolvedType) {
+                       verifyRuntimeRetention(newPattern.getResolvedAnnotationType());
+               }
+               ThisOrTargetAnnotationPointcut ret = new ThisOrTargetAnnotationPointcut(isThis,(ExactAnnotationTypePattern)annotationTypePattern.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
+        */
+       public FuzzyBoolean fastMatch(FastMatchInfo info) {
+               return FuzzyBoolean.MAYBE;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
+        */
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               if (!couldMatch(shadow)) return FuzzyBoolean.NO;
+           ResolvedType toMatchAgainst = 
+               (isThis ? shadow.getThisType() : shadow.getTargetType() ).resolve(shadow.getIWorld());
+           annotationTypePattern.resolve(shadow.getIWorld());
+           if (annotationTypePattern.matchesRuntimeType(toMatchAgainst).alwaysTrue()) {
+               return FuzzyBoolean.YES;
+           } else {
+               // a subtype may match at runtime
+               return FuzzyBoolean.MAYBE;
+           }
+       }
+
+       public boolean isThis() { return isThis; }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings)
+        */
+       protected void resolveBindings(IScope scope, Bindings bindings) {
+               if (!scope.getWorld().isInJava5Mode()) {
+                       scope.message(MessageUtil.error(WeaverMessages.format(
+                                       isThis ? WeaverMessages.ATTHIS_ONLY_SUPPORTED_AT_JAVA5_LEVEL : WeaverMessages.ATTARGET_ONLY_SUPPORTED_AT_JAVA5_LEVEL),
+                                       getSourceLocation()));
+                       return;
+               }
+               annotationTypePattern = (ExactAnnotationTypePattern) annotationTypePattern.resolveBindings(scope,bindings,true);
+               // must be either a Var, or an annotation type pattern
+               // if annotationType does not have runtime retention, this is an error
+               if (annotationTypePattern.annotationType == null) {
+                       // it's a formal with a binding error
+                       return;
+               }
+               ResolvedType rAnnotationType = (ResolvedType) annotationTypePattern.annotationType;
+               if (rAnnotationType.isTypeVariableReference()) return;  // we'll deal with this next check when the type var is actually bound...
+               verifyRuntimeRetention(rAnnotationType);
+               
+       }
+
+       private void verifyRuntimeRetention(ResolvedType rAnnotationType) {
+               if (!(rAnnotationType.isAnnotationWithRuntimeRetention())) {
+                   IMessage m = MessageUtil.error(
+                                       WeaverMessages.format(WeaverMessages.BINDING_NON_RUNTIME_RETENTION_ANNOTATION,rAnnotationType.getName()),
+                                       getSourceLocation());
+                       rAnnotationType.getWorld().getMessageHandler().handleMessage(m);
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedType, org.aspectj.weaver.IntMap)
+        */
+       protected Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               if (isDeclare(bindings.getEnclosingAdvice())) {
+                         // Enforce rule about which designators are supported in declare
+                         if (!alreadyWarnedAboutDEoW) {
+                                 inAspect.getWorld().showMessage(IMessage.ERROR,
+                                               WeaverMessages.format(WeaverMessages.THIS_OR_TARGET_IN_DECLARE,isThis?"this":"target"),
+                                               bindings.getEnclosingAdvice().getSourceLocation(), null);
+                                 alreadyWarnedAboutDEoW = true;
+                         }
+                         return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+               }
+
+               ExactAnnotationTypePattern newType = (ExactAnnotationTypePattern) annotationTypePattern.remapAdviceFormals(bindings);           
+               ThisOrTargetAnnotationPointcut ret = 
+                       new ThisOrTargetAnnotationPointcut(isThis, newType, bindings.getEnclosingAdvice());
+               ret.alreadyWarnedAboutDEoW = alreadyWarnedAboutDEoW;
+        ret.copyLocationFrom(this);
+        return ret;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
+        */
+       /**
+        * The guard here is going to be the hasAnnotation() test - if it gets through (which we cannot determine until runtime) then
+        * we must have a TypeAnnotationAccessVar in place - this means we must *always* have one in place.
+        */
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+           if (!couldMatch(shadow)) return Literal.FALSE;
+           boolean alwaysMatches = match(shadow).alwaysTrue();
+           Var var = isThis ? shadow.getThisVar() : shadow.getTargetVar();
+           Var annVar = null;
+           
+           // Are annotations being bound?
+           UnresolvedType annotationType = annotationTypePattern.annotationType;
+               if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
+                       BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern;
+                       annotationType = btp.annotationType;
+                       
+                       annVar = isThis ? shadow.getThisAnnotationVar(annotationType) :
+                               shadow.getTargetAnnotationVar(annotationType);
+                       if (annVar == null)
+                               throw new RuntimeException("Impossible!");
+
+                       state.set(btp.getFormalIndex(),annVar);
+               }
+
+               if (alwaysMatches && (annVar == null)) {//change check to verify if its the 'generic' annVar that is being used
+                   return Literal.TRUE;
+               } else {
+               ResolvedType rType = annotationType.resolve(shadow.getIWorld());
+               return Test.makeHasAnnotation(var,rType);
+               }
+       }
+
+       
+       private boolean couldMatch(Shadow shadow) {
+               return isThis ? shadow.hasThis() : shadow.hasTarget();
+       }
+       
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
+        */
+       public List getBindingAnnotationTypePatterns() {
+               if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
+                       List l = new ArrayList();
+                       l.add(annotationTypePattern);
+                       return l;
+               } else return Collections.EMPTY_LIST;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
+        */
+       public List getBindingTypePatterns() {
+               return Collections.EMPTY_LIST;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+           s.writeByte(Pointcut.ATTHIS_OR_TARGET);
+           s.writeBoolean(isThis);
+               annotationTypePattern.write(s);
+               writeLocation(s);
+       }
+       
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+           boolean isThis = s.readBoolean();
+               AnnotationTypePattern type = AnnotationTypePattern.read(s, context);
+               ThisOrTargetAnnotationPointcut ret = new ThisOrTargetAnnotationPointcut(isThis,(ExactAnnotationTypePattern)type);
+               ret.readLocation(context, s);
+               return ret;
+       }
+       
+       /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(Object obj) {
+        if (!(obj instanceof ThisOrTargetAnnotationPointcut)) return false;
+        ThisOrTargetAnnotationPointcut other = (ThisOrTargetAnnotationPointcut) obj;
+        return ( other.annotationTypePattern.equals(this.annotationTypePattern) &&
+                 (other.isThis == this.isThis) );
+    }
+    
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode() {
+        return 17 + 37*annotationTypePattern.hashCode() + (isThis ? 49 : 13);
+    }
+    
+       /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    private void buildDeclarationText() {
+               StringBuffer buf = new StringBuffer();
+               buf.append(isThis ? "@this(" : "@target(");
+               String annPatt = annotationTypePattern.toString();
+               buf.append(annPatt.startsWith("@") ? annPatt.substring(1) : annPatt);
+               buf.append(")");
+               this.declarationText = buf.toString();   
+       }
+    
+    public String toString() { return this.declarationText; }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java
new file mode 100644 (file)
index 0000000..1739837
--- /dev/null
@@ -0,0 +1,220 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.ast.Var;
+
+// 
+
+/**
+ * Corresponds to target or this pcd.
+ * 
+ * <p>type is initially a WildTypePattern.  If it stays that way, it's a this(Foo) 
+ * type deal.
+ * however, the resolveBindings method may convert it to a BindingTypePattern, 
+ * in which
+ * case, it's a this(foo) type deal.
+ * 
+ * @author Erik Hilsdale
+ * @author Jim Hugunin
+ */
+public class ThisOrTargetPointcut extends NameBindingPointcut {
+       private boolean isThis;
+       private TypePattern type;
+       private String declarationText;
+
+       private static final int thisKindSet;
+       private static final int targetKindSet;
+       
+       static {
+               int thisFlags = Shadow.ALL_SHADOW_KINDS_BITS;
+               int targFlags = Shadow.ALL_SHADOW_KINDS_BITS;
+               for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
+                       Shadow.Kind kind = Shadow.SHADOW_KINDS[i];
+                       if (kind.neverHasThis()) thisFlags-=kind.bit;
+                       if (kind.neverHasTarget()) targFlags-=kind.bit;
+               }
+               thisKindSet = thisFlags;
+               targetKindSet=targFlags;
+       }
+       
+       
+       public boolean isBinding() {
+               return (type instanceof BindingTypePattern);
+       }
+
+       public ThisOrTargetPointcut(boolean isThis, TypePattern type) {
+               this.isThis = isThis;
+               this.type = type;
+               this.pointcutKind = THIS_OR_TARGET;
+               this.declarationText = (isThis ? "this(" : "target(") + type + ")";
+       }
+
+    public TypePattern getType() {
+        return type;
+    }
+
+       public boolean isThis() { return isThis; }
+
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               ThisOrTargetPointcut ret = new ThisOrTargetPointcut(isThis,type.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public int couldMatchKinds() {
+               return isThis ? thisKindSet : targetKindSet;
+       }
+
+       public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               return FuzzyBoolean.MAYBE;
+       }
+
+       private boolean couldMatch(Shadow shadow) {
+               return isThis ? shadow.hasThis() : shadow.hasTarget();
+       }
+    
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               if (!couldMatch(shadow)) return FuzzyBoolean.NO;
+               UnresolvedType typeToMatch = isThis ? shadow.getThisType() : shadow.getTargetType(); 
+               //if (typeToMatch == ResolvedType.MISSING) return FuzzyBoolean.NO;
+               
+               return type.matches(typeToMatch.resolve(shadow.getIWorld()), TypePattern.DYNAMIC);//AVPT was DYNAMIC
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.THIS_OR_TARGET);
+               s.writeBoolean(isThis);
+               type.write(s);
+               writeLocation(s);
+       }
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               boolean isThis = s.readBoolean();
+               TypePattern type = TypePattern.read(s, context);
+               ThisOrTargetPointcut ret = new ThisOrTargetPointcut(isThis, type);
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               type = type.resolveBindings(scope, bindings, true, true);
+               
+               // look for parameterized type patterns which are not supported...
+               HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor 
+                       visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
+               type.traverse(visitor, null);
+               if (visitor.wellHasItThen/*?*/()) {
+                       scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.THIS_AND_TARGET_DONT_SUPPORT_PARAMETERS),
+                               getSourceLocation()));
+               }               
+               // ??? handle non-formal
+       }
+       
+       public void postRead(ResolvedType enclosingType) {
+               type.postRead(enclosingType);
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
+        */
+       public List getBindingAnnotationTypePatterns() {
+               return Collections.EMPTY_LIST;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
+        */
+       public List getBindingTypePatterns() {
+               if (type instanceof BindingTypePattern) {
+                       List l = new ArrayList();
+                       l.add(type);
+                       return l;
+               } else return Collections.EMPTY_LIST;
+       }
+
+       
+       public boolean equals(Object other) {
+               if (!(other instanceof ThisOrTargetPointcut)) return false;
+               ThisOrTargetPointcut o = (ThisOrTargetPointcut)other;
+               return o.isThis == this.isThis && o.type.equals(this.type);
+       }
+    public int hashCode() {
+        int result = 17;
+        result = 37*result + (isThis ? 0 : 1);
+        result = 37*result + type.hashCode();
+        return result;
+    }
+       public String toString() {
+               return declarationText;
+       }
+
+       /** 
+        * Residue is the remainder of the pointcut match that couldn't be
+        * performed with the purely static information at compile time and
+        * this method returns the residue of a pointcut at a particular shadow.
+        */
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               if (!couldMatch(shadow)) return Literal.FALSE;
+               
+               // if no preference is specified, just say TRUE which means no residue
+               if (type == TypePattern.ANY) return Literal.TRUE;
+               
+               Var var = isThis ? shadow.getThisVar() : shadow.getTargetVar(); 
+
+               return exposeStateForVar(var, type, state, shadow.getIWorld());
+       }
+
+       public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               if (isDeclare(bindings.getEnclosingAdvice())) {
+                 // Enforce rule about which designators are supported in declare
+                 inAspect.getWorld().showMessage(IMessage.ERROR,
+                               WeaverMessages.format(WeaverMessages.THIS_OR_TARGET_IN_DECLARE,isThis?"this":"target"),
+                               bindings.getEnclosingAdvice().getSourceLocation(), null);
+                 return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+               }
+               
+               TypePattern newType = type.remapAdviceFormals(bindings);
+               if (inAspect.crosscuttingMembers != null) {
+                       inAspect.crosscuttingMembers.exposeType(newType.getExactType());
+               }
+               
+               Pointcut ret = new ThisOrTargetPointcut(isThis, newType);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ThrowsPattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ThrowsPattern.java
new file mode 100644 (file)
index 0000000..04dd0c2
--- /dev/null
@@ -0,0 +1,142 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+
+public class ThrowsPattern extends PatternNode {
+       private TypePatternList required;
+       private TypePatternList forbidden;
+       
+       public static final ThrowsPattern ANY =
+               new ThrowsPattern(TypePatternList.EMPTY, TypePatternList.EMPTY);
+       
+       public ThrowsPattern(TypePatternList required, TypePatternList forbidden) {
+               this.required = required;
+               this.forbidden = forbidden;
+       }
+
+    public TypePatternList getRequired() {
+        return required;
+    }
+
+    public TypePatternList getForbidden() {
+        return forbidden;
+    }
+
+       public String toString() {
+               if (this == ANY) return "";
+               
+               
+               String ret = "throws " + required.toString();
+               if (forbidden.size() > 0) {
+                       ret = ret + " !(" + forbidden.toString() + ")";
+               }
+               return ret;
+       }
+    
+       public boolean equals(Object other) {
+               if (!(other instanceof ThrowsPattern)) return false;
+               ThrowsPattern o = (ThrowsPattern)other;
+               boolean ret = o.required.equals(this.required) &&
+                               o.forbidden.equals(this.forbidden);
+               return ret;
+       }
+    public int hashCode() {
+        int result = 17;
+        result = 37*result + required.hashCode();
+        result = 37*result + forbidden.hashCode();
+        return result;
+    }  
+    
+    public ThrowsPattern resolveBindings(IScope scope, Bindings bindings) {
+       if (this == ANY) return this;
+       required = required.resolveBindings(scope, bindings, false, false);
+       forbidden = forbidden.resolveBindings(scope, bindings, false, false);
+       return this;
+    }
+       
+    public ThrowsPattern parameterizeWith(Map/*name -> resolved type*/ typeVariableMap,World w) {
+       ThrowsPattern ret = new ThrowsPattern(
+                       required.parameterizeWith(typeVariableMap,w),
+                       forbidden.parameterizeWith(typeVariableMap,w));
+       ret.copyLocationFrom(this);
+       return ret;
+    }
+    
+       public boolean matches(UnresolvedType[] tys, World world) {
+               if (this == ANY) return true;
+               
+               //System.out.println("matching: " + this + " with " + Arrays.asList(tys));
+               
+               ResolvedType[] types = world.resolve(tys);
+               // int len = types.length;
+               for (int j=0, lenj = required.size(); j < lenj; j++) {
+                       if (! matchesAny(required.get(j), types)) {
+                               return false;
+                       }
+               }
+               for (int j=0, lenj = forbidden.size(); j < lenj; j++) {
+                       if (matchesAny(forbidden.get(j), types)) {
+                               return false;
+                       }
+               }
+               return true;
+       }
+       
+       private boolean matchesAny(
+               TypePattern typePattern,
+               ResolvedType[] types) 
+       {
+               for (int i = types.length - 1; i >= 0; i--) {
+                       if (typePattern.matchesStatically(types[i])) return true;       
+               }
+               return false;
+       }
+       
+       public static ThrowsPattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               TypePatternList required = TypePatternList.read(s, context);
+               TypePatternList forbidden = TypePatternList.read(s, context);
+               if (required.size() == 0 && forbidden.size() == 0) return ANY;
+               ThrowsPattern ret = new ThrowsPattern(required, forbidden);
+               //XXXret.readLocation(context, s);
+               return ret;
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               required.write(s);
+               forbidden.write(s);
+               //XXXwriteLocation(s);
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+    
+    public Object traverse(PatternNodeVisitor visitor, Object data) {
+       Object ret = accept(visitor,data);
+       forbidden.traverse(visitor, data);
+       required.traverse(visitor, data);
+       return ret;
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePattern.java
new file mode 100644 (file)
index 0000000..ed4f1dd
--- /dev/null
@@ -0,0 +1,624 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.TypeVariableReference;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+/**
+ *  On creation, type pattern only contains WildTypePattern nodes, not BindingType or ExactType. 
+ * 
+ * <p>Then we call resolveBindings() during compilation
+ * During concretization of enclosing pointcuts, we call remapAdviceFormals
+  * 
+ * @author Erik Hilsdale
+ * @author Jim Hugunin
+ */
+public abstract class TypePattern extends PatternNode {
+       public static class MatchKind {
+               private String name;
+               public MatchKind(String name) { this.name = name; }
+               public String toString() { return name; }
+       }
+       
+       public static final MatchKind STATIC = new MatchKind("STATIC");
+       public static final MatchKind DYNAMIC = new MatchKind("DYNAMIC");
+       
+       public static final TypePattern ELLIPSIS = new EllipsisTypePattern();
+       public static final TypePattern ANY = new AnyTypePattern();
+       public static final TypePattern NO = new NoTypePattern();
+       
+       
+       protected boolean includeSubtypes;
+       protected boolean isVarArgs = false;
+       protected AnnotationTypePattern annotationPattern = AnnotationTypePattern.ANY;
+       protected TypePatternList typeParameters = TypePatternList.EMPTY;
+       
+       protected TypePattern(boolean includeSubtypes,boolean isVarArgs,TypePatternList typeParams) {
+               this.includeSubtypes = includeSubtypes;
+               this.isVarArgs = isVarArgs;
+               this.typeParameters = (typeParams == null ? TypePatternList.EMPTY : typeParams);
+       }
+       
+       protected TypePattern(boolean includeSubtypes, boolean isVarArgs) {
+               this(includeSubtypes,isVarArgs,null);
+       }
+
+    public AnnotationTypePattern getAnnotationPattern() {
+        return annotationPattern;
+    }
+
+    public boolean isVarArgs() {
+        return isVarArgs;
+    }
+
+       public boolean isStarAnnotation() {
+               return annotationPattern == AnnotationTypePattern.ANY;
+       }
+       
+       public boolean isArray() {
+               return false;
+       }
+       
+       protected TypePattern(boolean includeSubtypes) {
+               this(includeSubtypes,false);
+       }
+       
+       public void setAnnotationTypePattern(AnnotationTypePattern annPatt) {
+               this.annotationPattern = annPatt;
+       }
+       
+       public void setTypeParameters(TypePatternList typeParams) {
+               this.typeParameters = typeParams;
+       }
+       
+       public TypePatternList getTypeParameters() {
+               return this.typeParameters;
+       }
+       
+       public void setIsVarArgs(boolean isVarArgs) {
+               this.isVarArgs = isVarArgs;
+       }
+       
+       // answer conservatively...
+       protected boolean couldEverMatchSameTypesAs(TypePattern other) {
+               if (this.includeSubtypes || other.includeSubtypes) return true;
+               if (this.annotationPattern != AnnotationTypePattern.ANY) return true;
+               if (other.annotationPattern != AnnotationTypePattern.ANY) return true;
+               return false;
+       }
+       
+       //XXX non-final for Not, && and ||
+       public boolean matchesStatically(ResolvedType type) {
+               if (includeSubtypes) {
+                       return matchesSubtypes(type);
+               } else {
+                       return matchesExactly(type);
+               }
+       }
+       public abstract FuzzyBoolean matchesInstanceof(ResolvedType type);      
+       
+       public final FuzzyBoolean matches(ResolvedType type, MatchKind kind) {
+//             FuzzyBoolean typeMatch = null;
+               //??? This is part of gracefully handling missing references
+               if (type.isMissing()) return FuzzyBoolean.NO;
+               
+               if (kind == STATIC) {
+//                     typeMatch = FuzzyBoolean.fromBoolean(matchesStatically(type));
+//                     return typeMatch.and(annotationPattern.matches(type));
+                   return FuzzyBoolean.fromBoolean(matchesStatically(type));
+               } else if (kind == DYNAMIC) {
+                       //System.err.println("matching: " + this + " with " + type);
+//                     typeMatch = matchesInstanceof(type);
+                       //System.err.println("    got: " + ret);
+//                     return typeMatch.and(annotationPattern.matches(type));
+                   return matchesInstanceof(type);
+               } else {
+                       throw new IllegalArgumentException("kind must be DYNAMIC or STATIC");
+               }
+       }
+               
+       protected abstract boolean matchesExactly(ResolvedType type);
+       
+       protected abstract boolean matchesExactly(ResolvedType type, ResolvedType annotatedType);
+
+       protected boolean matchesSubtypes(ResolvedType type) {
+               //System.out.println("matching: " + this + " to " + type);
+               if (matchesExactly(type)) {
+                       //System.out.println("    true");
+                       return true;
+               }
+               // pr124808
+               Iterator typesIterator = null;
+               if (type.isTypeVariableReference()) {
+                       typesIterator = ((TypeVariableReference)type).getTypeVariable().getFirstBound().resolve(type.getWorld()).getDirectSupertypes();
+               } else {
+            // pr223605
+            if (type.isRawType()) {
+                type = type.getGenericType();
+            }
+            typesIterator = type.getDirectSupertypes();
+               }
+               
+               // FuzzyBoolean ret = FuzzyBoolean.NO; // ??? -eh
+               for (Iterator i = typesIterator; i.hasNext(); ) {
+                       ResolvedType superType = (ResolvedType)i.next();
+                       // TODO asc generics, temporary whilst matching isnt aware..
+                       //if (superType.isParameterizedType()) superType = superType.getRawType().resolve(superType.getWorld());
+                       if (matchesSubtypes(superType,type)) return true;
+               }
+               return false;
+       }
+       
+       protected boolean matchesSubtypes(ResolvedType superType, ResolvedType annotatedType) {
+               //System.out.println("matching: " + this + " to " + type);
+               if (matchesExactly(superType,annotatedType)) {
+                       //System.out.println("    true");
+                       return true;
+               }
+               // If an ITD is applied, it will be put onto the generic type, not the parameterized or raw form
+               if (superType.isParameterizedType() || superType.isRawType()) {
+                       superType = superType.getGenericType();
+               }
+               // FuzzyBoolean ret = FuzzyBoolean.NO; // ??? -eh
+               for (Iterator i = superType.getDirectSupertypes(); i.hasNext(); ) {
+                       ResolvedType superSuperType = (ResolvedType)i.next();
+                       if (matchesSubtypes(superSuperType,annotatedType)) return true;
+               }
+               return false;
+       }
+       
+       public UnresolvedType resolveExactType(IScope scope, Bindings bindings) {
+               TypePattern p = resolveBindings(scope, bindings, false, true);
+               if (!(p instanceof ExactTypePattern)) return ResolvedType.MISSING;
+               return ((ExactTypePattern)p).getType();
+       }
+       
+       public UnresolvedType getExactType() {
+               if (this instanceof ExactTypePattern) return ((ExactTypePattern)this).getType();
+               else return ResolvedType.MISSING;
+       }
+       
+       protected TypePattern notExactType(IScope s) {
+               s.getMessageHandler().handleMessage(MessageUtil.error(
+                               WeaverMessages.format(WeaverMessages.EXACT_TYPE_PATTERN_REQD), getSourceLocation()));
+               return NO;
+       }
+       
+//     public boolean assertExactType(IMessageHandler m) {
+//             if (this instanceof ExactTypePattern) return true;
+//             
+//             //XXX should try harder to avoid multiple errors for one problem
+//             m.handleMessage(MessageUtil.error("exact type pattern required", getSourceLocation()));
+//             return false;
+//     }
+
+       /**
+        * This can modify in place, or return a new TypePattern if the type changes.
+        */
+    public TypePattern resolveBindings(IScope scope, Bindings bindings, 
+                                                               boolean allowBinding, boolean requireExactType)
+    { 
+       annotationPattern = annotationPattern.resolveBindings(scope,bindings,allowBinding);
+       return this;
+    }
+    
+    public void resolve(World world) {
+        annotationPattern.resolve(world);
+    }
+    
+    /**
+     * return a version of this type pattern in which all type variable references have been
+     * replaced by their corresponding entry in the map.
+     */
+    public abstract TypePattern parameterizeWith(Map typeVariableMap,World w);
+    
+       public void postRead(ResolvedType enclosingType) {
+       }
+       
+       public boolean isStar() {
+               return false;
+       }
+
+    
+    
+    /**
+     * This is called during concretization of pointcuts, it is used by BindingTypePattern
+     * to return a new BindingTypePattern with a formal index appropiate for the advice,
+     * rather than for the lexical declaration, i.e. this handles transforamtions through
+     * named pointcuts.
+     * <pre>
+     * pointcut foo(String name): args(name);
+     * --&gt; This makes a BindingTypePattern(0) pointing to the 0th formal
+     * 
+     * before(Foo f, String n): this(f) && foo(n) { ... }
+     * --&gt; when resolveReferences is called on the args from the above, it
+     *     will return a BindingTypePattern(1)
+     * 
+     * before(Foo f): this(f) && foo(*) { ... }
+     * --&gt; when resolveReferences is called on the args from the above, it
+     *     will return an ExactTypePattern(String)
+     * </pre>
+     */
+       public TypePattern remapAdviceFormals(IntMap bindings) {
+               return this;
+       }
+
+
+       public static final byte WILD = 1;
+       public static final byte EXACT = 2;
+       public static final byte BINDING = 3;
+       public static final byte ELLIPSIS_KEY = 4; 
+       public static final byte ANY_KEY = 5; 
+       public static final byte NOT = 6;
+       public static final byte OR = 7;
+       public static final byte AND = 8;
+       public static final byte NO_KEY = 9;
+       public static final byte ANY_WITH_ANNO = 10;
+       public static final byte HAS_MEMBER = 11;
+
+       public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               byte key = s.readByte();
+               switch(key) {
+                       case WILD: return WildTypePattern.read(s, context);
+                       case EXACT: return ExactTypePattern.read(s, context);
+                       case BINDING: return BindingTypePattern.read(s, context);
+                       case ELLIPSIS_KEY: return ELLIPSIS;
+                       case ANY_KEY: return ANY;
+                       case NO_KEY: return NO;
+                       case NOT: return NotTypePattern.read(s, context);
+                       case OR: return OrTypePattern.read(s, context);
+                       case AND: return AndTypePattern.read(s, context);
+                       case ANY_WITH_ANNO: return AnyWithAnnotationTypePattern.read(s,context);
+                       case HAS_MEMBER: return HasMemberTypePattern.read(s,context);
+               }
+               throw new BCException("unknown TypePattern kind: " + key);
+       }
+
+       public boolean isIncludeSubtypes() {
+               return includeSubtypes;
+       }
+
+}
+
+class EllipsisTypePattern extends TypePattern {
+       
+       /**
+        * Constructor for EllipsisTypePattern.
+        * @param includeSubtypes
+        */
+       public EllipsisTypePattern() {
+               super(false,false,new TypePatternList());
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
+        */
+       protected boolean couldEverMatchSameTypesAs(TypePattern other) {
+               return true;
+       }
+       /**
+        * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
+        */
+       protected boolean matchesExactly(ResolvedType type) {
+               return false;
+       }
+       
+       protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
+               return false;
+       }
+
+       /**
+        * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
+        */
+       public FuzzyBoolean matchesInstanceof(ResolvedType type) {
+               return FuzzyBoolean.NO;
+       }
+
+       /**
+        * @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(ELLIPSIS_KEY);
+       }
+       
+       public String toString() { return ".."; }
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       public boolean equals(Object obj) {
+               return (obj instanceof EllipsisTypePattern);
+       }
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       public int hashCode() {
+               return 17 * 37;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+    
+    public TypePattern parameterizeWith(Map typeVariableMap,World w) {
+       return this;
+    }
+
+
+}
+
+class AnyTypePattern extends TypePattern {
+       
+       /**
+        * Constructor for EllipsisTypePattern.
+        * @param includeSubtypes
+        */
+       public AnyTypePattern() {
+               super(false,false,new TypePatternList());
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
+        */
+       protected boolean couldEverMatchSameTypesAs(TypePattern other) {
+               return true;
+       }
+       /**
+        * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
+        */
+       protected boolean matchesExactly(ResolvedType type) {
+               return true;
+       }
+
+       protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
+               return true;
+       }
+       
+       /**
+        * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
+        */
+       public FuzzyBoolean matchesInstanceof(ResolvedType type) {
+               return FuzzyBoolean.YES;
+       }
+
+       /**
+        * @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(ANY_KEY);
+       }
+
+       /**
+        * @see org.aspectj.weaver.patterns.TypePattern#matches(IType, MatchKind)
+        */
+//     public FuzzyBoolean matches(IType type, MatchKind kind) {
+//             return FuzzyBoolean.YES;
+//     }
+
+       /**
+        * @see org.aspectj.weaver.patterns.TypePattern#matchesSubtypes(IType)
+        */
+       protected boolean matchesSubtypes(ResolvedType type) {
+               return true;
+       }
+       
+       
+       public boolean isStar() {
+               return true;
+       }
+       
+       public String toString() { return "*"; }
+       
+       public boolean equals(Object obj) {
+               return (obj instanceof AnyTypePattern);
+       }
+       
+       public int hashCode() {
+               return 37;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+    
+    public TypePattern parameterizeWith(Map arg0,World w) {
+       return this;
+    }
+}
+
+/**
+ * This type represents a type pattern of '*' but with an annotation specified,
+ * e.g. '@Color *'
+ */
+class AnyWithAnnotationTypePattern extends TypePattern {
+       
+       public AnyWithAnnotationTypePattern(AnnotationTypePattern atp) {
+               super(false,false);
+               annotationPattern = atp;
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
+       protected boolean couldEverMatchSameTypesAs(TypePattern other) {
+               return true;
+       }
+
+       protected boolean matchesExactly(ResolvedType type) {
+               annotationPattern.resolve(type.getWorld());
+               boolean b = false;
+               if (type.temporaryAnnotationTypes!=null) {
+                       b = annotationPattern.matches(type,type.temporaryAnnotationTypes).alwaysTrue();
+               } else {
+                       b = annotationPattern.matches(type).alwaysTrue();
+               }
+               return b;
+       }
+       
+       
+       protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
+               annotationPattern.resolve(type.getWorld());
+               return annotationPattern.matches(annotatedType).alwaysTrue();           
+       }
+
+       public FuzzyBoolean matchesInstanceof(ResolvedType type) {
+               if (Modifier.isFinal(type.getModifiers())) {
+                       return FuzzyBoolean.fromBoolean(matchesExactly(type));
+               }
+               return FuzzyBoolean.MAYBE;
+       }
+
+       public TypePattern parameterizeWith(Map typeVariableMap,World w) {
+               AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(this.annotationPattern.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(TypePattern.ANY_WITH_ANNO);
+               annotationPattern.write(s);
+               writeLocation(s);
+       }
+       
+       public static TypePattern read(VersionedDataInputStream s,ISourceContext c) throws IOException {
+                AnnotationTypePattern annPatt = AnnotationTypePattern.read(s,c);
+                AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(annPatt);
+                ret.readLocation(c, s);
+                return ret;
+       }
+
+//     public FuzzyBoolean matches(IType type, MatchKind kind) {
+//             return FuzzyBoolean.YES;
+//     }
+
+       protected boolean matchesSubtypes(ResolvedType type) {
+               return true;
+       }
+       
+       public boolean isStar() {
+               return false;
+       }
+       
+       public String toString() { return annotationPattern+" *"; }
+       
+       public boolean equals(Object obj) {
+               if  (!(obj instanceof AnyWithAnnotationTypePattern)) return false;
+               AnyWithAnnotationTypePattern awatp = (AnyWithAnnotationTypePattern) obj;
+               return (annotationPattern.equals(awatp.annotationPattern));
+       }
+       
+       public int hashCode() {
+               return annotationPattern.hashCode();
+       }
+}
+
+class NoTypePattern extends TypePattern {
+       
+       public NoTypePattern() {
+               super(false,false,new TypePatternList());
+       }
+
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
+        */
+       protected boolean couldEverMatchSameTypesAs(TypePattern other) {
+               return false;
+       }
+       /**
+        * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
+        */
+       protected boolean matchesExactly(ResolvedType type) {
+               return false;
+       }
+       
+       protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
+               return false;
+       }
+
+       /**
+        * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
+        */
+       public FuzzyBoolean matchesInstanceof(ResolvedType type) {
+               return FuzzyBoolean.NO;
+       }
+
+       /**
+        * @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(NO_KEY);
+       }
+
+       /**
+        * @see org.aspectj.weaver.patterns.TypePattern#matches(IType, MatchKind)
+        */
+//     public FuzzyBoolean matches(IType type, MatchKind kind) {
+//             return FuzzyBoolean.YES;
+//     }
+
+       /**
+        * @see org.aspectj.weaver.patterns.TypePattern#matchesSubtypes(IType)
+        */
+       protected boolean matchesSubtypes(ResolvedType type) {
+               return false;
+       }
+       
+       
+       public boolean isStar() {
+               return false;
+       }
+       
+       public String toString() { return "<nothing>"; }//FIXME AV - bad! toString() cannot be parsed back (not idempotent)
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       public boolean equals(Object obj) {
+               return (obj instanceof NoTypePattern);
+       }
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       public int hashCode() {
+               return 17 * 37 * 37;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+    
+    public TypePattern parameterizeWith(Map arg0,World w) {
+       return this;
+    }
+}
+
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePatternList.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePatternList.java
new file mode 100644 (file)
index 0000000..d2b51d7
--- /dev/null
@@ -0,0 +1,333 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+public class TypePatternList extends PatternNode {
+       private TypePattern[] typePatterns;
+       int ellipsisCount = 0;
+       
+       public static final TypePatternList EMPTY =
+               new TypePatternList(new TypePattern[] {});
+       
+       public static final TypePatternList ANY =
+           new TypePatternList(new TypePattern[] {new EllipsisTypePattern()});  //can't use TypePattern.ELLIPSIS because of circular static dependency that introduces
+       
+       public TypePatternList() {
+               typePatterns = new TypePattern[0];
+               ellipsisCount = 0;
+       }
+
+       public TypePatternList(TypePattern[] arguments) {
+               this.typePatterns = arguments;
+               for (int i=0; i<arguments.length; i++) {
+                       if (arguments[i] == TypePattern.ELLIPSIS) ellipsisCount++;
+               }
+       }
+       
+       public TypePatternList(List l) {
+               this((TypePattern[]) l.toArray(new TypePattern[l.size()]));
+       }
+       
+       public int size() { return typePatterns.length; }
+       
+       public TypePattern get(int index) {
+               return typePatterns[index];
+       }
+
+    public String toString() {
+       StringBuffer buf = new StringBuffer();
+       buf.append("(");
+       for (int i=0, len=typePatterns.length; i < len; i++) {
+               TypePattern type = typePatterns[i];
+               if (i > 0) buf.append(", ");
+               if (type == TypePattern.ELLIPSIS) {
+                       buf.append("..");
+               } else {
+                       buf.append(type.toString());
+               }
+       }
+       buf.append(")");
+       return buf.toString();
+    }
+       
+    /*
+     * return true iff this pattern could ever match a signature with the
+     * given number of parameters
+     */
+    public boolean canMatchSignatureWithNParameters(int numParams) {
+       if (ellipsisCount == 0) {
+               return numParams == size();
+       } else {
+               return (size() -ellipsisCount) <= numParams;
+       }
+    }
+    public FuzzyBoolean matches(ResolvedType[] types, TypePattern.MatchKind kind) {
+       return matches(types,kind,null);
+    }
+    
+    //XXX shares much code with WildTypePattern and with NamePattern
+    /**
+     * When called with TypePattern.STATIC this will always return either
+     * FuzzyBoolean.YES or FuzzyBoolean.NO.
+     * 
+     * When called with TypePattern.DYNAMIC this could return MAYBE if
+     * at runtime it would be possible for arguments of the given static
+     * types to dynamically match this, but it is not known for certain.
+     * 
+     * This method will never return FuzzyBoolean.NEVER
+     */ 
+    public FuzzyBoolean matches(ResolvedType[] types, TypePattern.MatchKind kind, ResolvedType[][] parameterAnnotations) {
+       int nameLength = types.length;
+               int patternLength = typePatterns.length;
+               
+               int nameIndex = 0;
+               int patternIndex = 0;
+               
+               if (ellipsisCount == 0) {
+                       if (nameLength != patternLength) return FuzzyBoolean.NO;
+                       FuzzyBoolean finalReturn = FuzzyBoolean.YES;
+                       while (patternIndex < patternLength) {
+                               ResolvedType t = types[nameIndex];
+                               FuzzyBoolean ret = null;
+                               try {
+                                 if (parameterAnnotations!=null) t.temporaryAnnotationTypes = parameterAnnotations[nameIndex];
+                             ret = typePatterns[patternIndex].matches(t,kind);
+                               } finally {
+                                       t.temporaryAnnotationTypes=null;
+                               }
+                               patternIndex++;
+                               nameIndex++;
+                               if (ret == FuzzyBoolean.NO) return ret;
+                               if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
+                       }
+                       return finalReturn;
+               } else if (ellipsisCount == 1) {
+                       if (nameLength < patternLength-1) return FuzzyBoolean.NO;
+                       FuzzyBoolean finalReturn = FuzzyBoolean.YES;
+                       while (patternIndex < patternLength) {
+                               TypePattern p = typePatterns[patternIndex++];
+                               if (p == TypePattern.ELLIPSIS) {
+                                       nameIndex = nameLength - (patternLength-patternIndex);
+                               } else {
+                                       ResolvedType t = types[nameIndex];
+                                       FuzzyBoolean ret = null;
+                                       try {
+                                               if (parameterAnnotations!=null) t.temporaryAnnotationTypes = parameterAnnotations[nameIndex];
+                                           ret = p.matches(t, kind);
+                                       } finally {
+                                               t.temporaryAnnotationTypes=null;
+                                       }
+                                       nameIndex++;
+                                   if (ret == FuzzyBoolean.NO) return ret;
+                                   if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
+                               }
+                       }
+                       return finalReturn;
+               } else {
+//            System.err.print("match(" + arguments + ", " + types + ") -> ");
+            FuzzyBoolean b =  outOfStar(typePatterns, types, 0, 0, patternLength - ellipsisCount, nameLength, ellipsisCount, kind);
+//            System.err.println(b);
+            return b;
+       }
+    }
+    
+    private static FuzzyBoolean outOfStar(final TypePattern[] pattern, final ResolvedType[] target, 
+                                                  int           pi,            int    ti, 
+                                                  int           pLeft,         int    tLeft,
+                                           final int           starsLeft, TypePattern.MatchKind kind) {
+        if (pLeft > tLeft) return FuzzyBoolean.NO;
+        FuzzyBoolean finalReturn = FuzzyBoolean.YES;
+        while (true) {
+            // invariant: if (tLeft > 0) then (ti < target.length && pi < pattern.length) 
+            if (tLeft == 0) return finalReturn;
+            if (pLeft == 0) {
+                if (starsLeft > 0) {
+                    return finalReturn;
+                } else {
+                    return FuzzyBoolean.NO;
+                }
+            }
+            if (pattern[pi] == TypePattern.ELLIPSIS) {
+                return inStar(pattern, target, pi+1, ti, pLeft, tLeft, starsLeft-1, kind);
+            }
+            FuzzyBoolean ret = pattern[pi].matches(target[ti], kind);
+            if (ret == FuzzyBoolean.NO) return ret;
+            if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
+            pi++; ti++; pLeft--; tLeft--;
+        }
+    }    
+    private static FuzzyBoolean inStar(final TypePattern[] pattern, final ResolvedType[] target, 
+                                               int           pi,             int    ti, 
+                                         final int           pLeft,         int    tLeft,
+                                               int    starsLeft,     TypePattern.MatchKind kind) {
+        // invariant: pLeft > 0, so we know we'll run out of stars and find a real char in pattern
+        TypePattern patternChar = pattern[pi];
+        while (patternChar == TypePattern.ELLIPSIS) {
+            starsLeft--;
+            patternChar = pattern[++pi];
+        }
+        while (true) {
+            // invariant: if (tLeft > 0) then (ti < target.length)
+            if (pLeft > tLeft) return FuzzyBoolean.NO;
+            FuzzyBoolean ff = patternChar.matches(target[ti], kind);
+            if (ff.maybeTrue()) {
+                FuzzyBoolean xx = outOfStar(pattern, target, pi+1, ti+1, pLeft-1, tLeft-1, starsLeft, kind);
+                if (xx.maybeTrue()) return ff.and(xx);
+            } 
+            ti++; tLeft--;
+        }
+    }
+      
+    /**
+     * Return a version of this type pattern list in which all type variable references
+     * are replaced by their corresponding entry in the map
+     * @param typeVariableMap
+     * @return
+     */
+    public TypePatternList parameterizeWith(Map typeVariableMap,World w) {
+       TypePattern[] parameterizedPatterns = new TypePattern[typePatterns.length];
+       for (int i = 0; i < parameterizedPatterns.length; i++) {
+                       parameterizedPatterns[i] = typePatterns[i].parameterizeWith(typeVariableMap,w);
+               }
+       return new TypePatternList(parameterizedPatterns);
+    }
+    
+       public TypePatternList resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
+               for (int i=0; i<typePatterns.length; i++) {
+                       TypePattern p = typePatterns[i];
+                       if (p != null) {
+                               typePatterns[i] = typePatterns[i].resolveBindings(scope, bindings, allowBinding, requireExactType);
+                       }
+               }
+               return this;
+       }
+       
+       public TypePatternList resolveReferences(IntMap bindings) {
+               int len = typePatterns.length;
+               TypePattern[] ret = new TypePattern[len];
+               for (int i=0; i < len; i++) {
+                       ret[i] = typePatterns[i].remapAdviceFormals(bindings);
+               }
+               return new TypePatternList(ret);
+       }
+
+       public void postRead(ResolvedType enclosingType) {
+               for (int i=0; i<typePatterns.length; i++) {
+                       TypePattern p = typePatterns[i];
+                       p.postRead(enclosingType);
+               }
+       }
+       
+
+       public boolean equals(Object other) {
+               if (!(other instanceof TypePatternList)) return false;
+               TypePatternList o = (TypePatternList)other;
+               int len = o.typePatterns.length;
+               if (len != this.typePatterns.length) return false;
+               for (int i=0; i<len; i++) {
+                       if (!this.typePatterns[i].equals(o.typePatterns[i])) return false;
+               }
+               return true;
+       }
+    public int hashCode() {
+        int result = 41;
+        for (int i = 0, len = typePatterns.length; i < len; i++) {
+            result = 37*result + typePatterns[i].hashCode();
+        }
+        return result;
+    }
+    
+
+       public static TypePatternList read(VersionedDataInputStream s, ISourceContext context) throws IOException  {
+               short len = s.readShort();
+               TypePattern[] arguments = new TypePattern[len];
+               for (int i=0; i<len; i++) {
+                       arguments[i] = TypePattern.read(s, context);
+               }
+               TypePatternList ret = new TypePatternList(arguments);
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeShort(typePatterns.length);
+               for (int i=0; i<typePatterns.length; i++) {
+                       typePatterns[i].write(s);
+               }
+               writeLocation(s);
+       }
+    public TypePattern[] getTypePatterns() {
+        return typePatterns;
+    }
+
+       public Collection getExactTypes() {
+               ArrayList ret = new ArrayList();
+               for (int i=0; i<typePatterns.length; i++) {
+                       UnresolvedType t = typePatterns[i].getExactType();
+                       if (!ResolvedType.isMissing(t)) ret.add(t);
+               }
+               return ret;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               for (int i = 0; i < typePatterns.length; i++) {
+                       typePatterns[i].traverse(visitor,ret);
+               }
+               return ret;
+       }
+
+       public boolean areAllExactWithNoSubtypesAllowed() {
+               for (int i = 0; i < typePatterns.length; i++) {
+                       TypePattern array_element = typePatterns[i];
+                       if (!(array_element instanceof ExactTypePattern)) {
+                               return false;
+                       } else {
+                               ExactTypePattern etp = (ExactTypePattern) array_element;
+                               if (etp.isIncludeSubtypes()) return false;
+                       }
+               }
+               return true;
+       }
+
+       public String[] maybeGetCleanNames() {
+      String[] theParamNames = new String[typePatterns.length];
+         for (int i = 0; i < typePatterns.length; i++) {
+               TypePattern string = typePatterns[i];
+               if (!(string instanceof ExactTypePattern)) return null;
+               theParamNames[i] = ((ExactTypePattern)string).getExactType().getName();
+         }
+         return theParamNames;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePatternQuestions.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePatternQuestions.java
new file mode 100644 (file)
index 0000000..41aaf4b
--- /dev/null
@@ -0,0 +1,107 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ResolvedType;
+
+
+public class TypePatternQuestions {
+       private Map questionsAndAnswers = new HashMap();
+       
+       public FuzzyBoolean askQuestion(TypePattern pattern, ResolvedType type,
+                                                                       TypePattern.MatchKind kind)
+       {
+               Question question = new Question(pattern, type, kind);
+               //??? should we use this table to do caching or is that a pessimization
+               //??? if we do that optimization we can also do error checking that the result
+               //??? doesn't change
+               FuzzyBoolean answer = question.ask();
+               questionsAndAnswers.put(question, answer);
+               return answer;
+       }
+       
+       public Question anyChanges() {
+               for (Iterator i = questionsAndAnswers.entrySet().iterator(); i.hasNext(); ) {
+                       Map.Entry entry = (Map.Entry)i.next();
+                       Question question = (Question)entry.getKey();
+                       FuzzyBoolean expectedAnswer = (FuzzyBoolean)entry.getValue();
+                       
+                       FuzzyBoolean currentAnswer = question.ask();
+                       //System.out.println(question + ":" + currentAnswer);
+                       if (currentAnswer != expectedAnswer) {
+                               return question;
+                       }
+               }
+               
+               return null;
+       }
+       
+       public String toString() {
+               StringBuffer buf = new StringBuffer();
+               buf.append("TypePatternQuestions{");
+               for (Iterator i = questionsAndAnswers.entrySet().iterator(); i.hasNext(); ) {
+                       Map.Entry entry = (Map.Entry)i.next();
+                       Question question = (Question)entry.getKey();
+                       FuzzyBoolean expectedAnswer = (FuzzyBoolean)entry.getValue();
+                       buf.append(question);
+                       buf.append(":");
+                       buf.append(expectedAnswer);
+                       buf.append(", ");
+               }
+               buf.append("}");
+               return buf.toString();
+       }
+       
+       
+       public class Question {
+               TypePattern pattern;
+               ResolvedType type;
+               TypePattern.MatchKind kind;
+       
+               public Question(TypePattern pattern, ResolvedType type,
+                                                                       TypePattern.MatchKind kind) {
+                       super();
+                       this.pattern = pattern;
+                       this.type = type;
+                       this.kind = kind;
+               }
+               
+               public FuzzyBoolean ask() {
+                       return pattern.matches(type, kind);
+               }
+               
+               public boolean equals(Object other) {
+                       if (!(other instanceof Question)) return false;
+                       Question o = (Question)other;
+                       return o.pattern.equals(pattern) && o.type.equals(type) && o.kind == kind;
+               }
+       
+               public int hashCode() {
+               int result = 17;
+               result = 37*result + kind.hashCode();
+               result = 37*result + pattern.hashCode();
+               result = 37*result + type.hashCode();
+               return result;
+           }   
+       
+               public String toString() {
+                       return "?(" + pattern + ", " + type + ", " + kind + ")";
+               }
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypeVariablePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypeVariablePattern.java
new file mode 100644 (file)
index 0000000..7016b23
--- /dev/null
@@ -0,0 +1,209 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+
+/**
+ * @author colyer
+ * Represents a type variable as declared as part of a type declaration, parameter declaration,
+ * or type parameter specification.
+ * <p>For example:</p>
+ * <ul>
+ * <li>&lt;T&gt; T genericMethod(T t) {...}</li>
+ * <li>static &lt;T extends Foo&gt; T staticGenericMethod(T t) {...}</li>
+ * <li>Foo&lt;T extends Bar &amp; IGoo&gt;
+ * </ul>
+ */
+public class TypeVariablePattern extends PatternNode {
+
+       private static final String anything = "?";
+       
+       private String name;  // eg. "T"
+       private TypePattern upperBound; // default is object unless of the form T extends Bar
+       private TypePattern[] interfaceBounds; // additional upper bounds (must be interfaces) arising from
+                                                           // declarations of the form T extends Bar & IGoo, IDoo
+       private TypePattern lowerBound; // only set if type variable is of the form T super Bar
+       
+       /**
+        * Create a named type variable with upper bound Object and no lower bounds.
+        * Use this constructor for the simple "T" case
+        */
+       public TypeVariablePattern(String variableName) {
+               this.name = variableName;
+               this.upperBound = new ExactTypePattern(UnresolvedType.OBJECT,false,false);
+               this.lowerBound = null;
+               this.interfaceBounds = null;
+       }
+       
+       /**
+        * Create a named type variable with the given upper bound and no lower bounds
+        * Use this constructor for the T extends Foo case
+        * @param variableName
+        * @param upperBound
+        */
+       public TypeVariablePattern(String variableName, TypePattern upperBound) {
+               this.name = variableName;
+               this.upperBound = upperBound;
+               this.lowerBound = null;
+               this.interfaceBounds = null;
+       }
+       
+       public TypeVariablePattern(String variableName, TypePattern upperLimit, TypePattern[] interfaceBounds, TypePattern lowerBound) {
+               this.name = variableName;
+               this.upperBound = upperLimit;
+               if (upperBound == null) upperBound = new ExactTypePattern(UnresolvedType.OBJECT,false,false);
+               this.interfaceBounds = interfaceBounds;
+               this.lowerBound = lowerBound;
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
+       public String getName() {
+               return name;
+       }
+       
+       public boolean isAnythingPattern() {
+               return name.equals(anything);
+       }
+       
+       public TypePattern getRawTypePattern() {
+               return upperBound;
+       }
+       
+       public TypePattern getUpperBound() {
+               return upperBound;
+       }
+       
+       public boolean hasLowerBound() { return (lowerBound != null); }
+       
+       public TypePattern getLowerBound() {
+               return lowerBound;
+       }
+       
+       public boolean hasAdditionalInterfaceBounds() {
+               return (interfaceBounds != null);
+       }
+       
+       public TypePattern[] getAdditionalInterfaceBounds() {
+               if (interfaceBounds != null) {
+                       return interfaceBounds;
+               } else {
+                       return new TypePattern[0];
+               }
+       }
+       
+       public boolean equals(Object obj) {
+               if (!(obj instanceof TypeVariablePattern)) return false;
+               TypeVariablePattern other = (TypeVariablePattern) obj;
+               if (!name.equals(other.name)) return false;
+               if (!upperBound.equals(other.upperBound)) return false;
+               if (lowerBound != null) {
+                       if (other.lowerBound == null) return false;
+                       if (!lowerBound.equals(other.lowerBound)) return false;
+               } else {
+                       if (other.lowerBound != null) return false;
+               }
+               if (interfaceBounds != null) {
+                       if (other.interfaceBounds == null) return false;
+                       if (interfaceBounds.length != other.interfaceBounds.length) return false;
+                       for (int i = 0; i < interfaceBounds.length; i++) {
+                               if (!interfaceBounds[i].equals(other.interfaceBounds[i])) return false;
+                       }
+               } else {
+                       if (other.interfaceBounds != null) return false;
+               }
+               return true;
+       }
+       
+       public int hashCode() {
+               int hashCode = 17 + (37 * name.hashCode());
+               hashCode = hashCode * 37 + upperBound.hashCode();
+               if (lowerBound != null) hashCode = hashCode * 37 + lowerBound.hashCode();
+               if (interfaceBounds != null) {
+                       for (int i = 0; i < interfaceBounds.length; i++) {
+                               hashCode = 37*hashCode + interfaceBounds[i].hashCode();
+                       }
+               }
+               return hashCode;
+       }
+       
+       public String toString() {
+               StringBuffer sb = new StringBuffer();
+               sb.append(name);
+               sb.append(getExtendsClause());
+               if (interfaceBounds != null) {
+                       sb.append(" & ");
+                       for (int i = 0; i < interfaceBounds.length; i++) {
+                               sb.append(interfaceBounds[i].toString());
+                               if (i < interfaceBounds.length) sb.append(",");
+                       }
+               }
+               if (lowerBound != null) {
+                       sb.append(" super ");
+                       sb.append(lowerBound.toString());
+               }
+               return sb.toString();
+       }
+       
+       private String getExtendsClause() {
+               if (upperBound instanceof ExactTypePattern) {
+                       ExactTypePattern bound = (ExactTypePattern) upperBound;
+                       if (bound.type == UnresolvedType.OBJECT) return "";
+               }
+               return " extends " + upperBound.toString();
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeUTF(name);
+               upperBound.write(s);
+               if (interfaceBounds == null) {
+                       s.writeInt(0);
+               } else {
+                       s.writeInt(interfaceBounds.length);
+                       for (int i = 0; i < interfaceBounds.length; i++) {
+                               interfaceBounds[i].write(s);
+                       }
+               }
+               s.writeBoolean(hasLowerBound());
+               if (hasLowerBound()) lowerBound.write(s);
+               writeLocation(s);               
+       }
+       
+       public static TypeVariablePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               TypeVariablePattern tv = null;
+               String name = s.readUTF();
+               TypePattern upperBound = TypePattern.read(s, context);
+               TypePattern[] additionalInterfaceBounds = null;
+               int numInterfaceBounds = s.readInt();
+               if (numInterfaceBounds > 0) {
+                       additionalInterfaceBounds = new TypePattern[numInterfaceBounds];
+                       for (int i = 0; i < additionalInterfaceBounds.length; i++) {
+                               additionalInterfaceBounds[i] = TypePattern.read(s, context);
+                       }
+               }
+               boolean hasLowerBound = s.readBoolean();
+               TypePattern lowerBound = null;
+               if (hasLowerBound) lowerBound = TypePattern.read(s,context);
+               tv = new TypeVariablePattern(name,upperBound,additionalInterfaceBounds,lowerBound);
+               tv.readLocation(context, s);
+               return tv;
+       }
+       
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypeVariablePatternList.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypeVariablePatternList.java
new file mode 100644 (file)
index 0000000..8ede2a0
--- /dev/null
@@ -0,0 +1,85 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.VersionedDataInputStream;
+
+/**
+ * @author colyer
+ * A list of type variable specifications, eg. &lt;T,S&gt; 
+ */
+public class TypeVariablePatternList extends PatternNode {
+
+       public static final TypeVariablePatternList EMPTY = new TypeVariablePatternList(new TypeVariablePattern[0]);
+       
+       private TypeVariablePattern[] patterns;
+       
+       public TypeVariablePatternList(TypeVariablePattern[] typeVars) {
+               this.patterns = typeVars;
+       }
+       
+       public TypeVariablePattern[] getTypeVariablePatterns() {
+               return this.patterns;
+       }
+       
+       public TypeVariablePattern lookupTypeVariable(String name) {
+               for (int i = 0; i < patterns.length; i++) {
+                       if (patterns[i].getName().equals(name)) {
+                               return patterns[i];
+                       }
+               }
+               return null;
+       }
+       
+       public boolean isEmpty() {
+               return ((patterns == null) || (patterns.length == 0));
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeInt(patterns.length);
+               for (int i = 0; i < patterns.length; i++) {
+                       patterns[i].write(s);
+               }
+               writeLocation(s);
+       }
+
+       public static TypeVariablePatternList read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               TypeVariablePatternList ret = EMPTY;
+               int length = s.readInt();
+               if (length > 0) {
+                       TypeVariablePattern[] patterns = new TypeVariablePattern[length];
+                       for (int i = 0; i < patterns.length; i++) {
+                               patterns[i] = TypeVariablePattern.read(s,context);
+                       }
+                       ret = new TypeVariablePatternList(patterns);
+               }
+               ret.readLocation(context, s);  // redundant but safe to read location for EMPTY
+               return ret;
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               for (int i = 0; i < patterns.length; i++) {
+                       patterns[i].traverse(visitor,ret);
+               }
+               return ret;
+       }
+       
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildAnnotationTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildAnnotationTypePattern.java
new file mode 100644 (file)
index 0000000..4555df8
--- /dev/null
@@ -0,0 +1,369 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
+
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class WildAnnotationTypePattern extends AnnotationTypePattern {
+
+       private TypePattern typePattern;
+       private boolean resolved = false;
+       Map annotationValues;
+       
+       /**
+        * 
+        */
+       public WildAnnotationTypePattern(TypePattern typePattern) {
+               super();
+               this.typePattern = typePattern;
+               this.setLocation(typePattern.getSourceContext(), typePattern.start, typePattern.end);
+       }
+       
+       public WildAnnotationTypePattern(TypePattern typePattern, Map annotationValues) {
+               super();
+               this.typePattern = typePattern;
+               this.annotationValues = annotationValues;
+               // PVAL make the location be from start of type pattern to end of values
+               this.setLocation(typePattern.getSourceContext(), typePattern.start, typePattern.end);           
+       }
+
+    public TypePattern getTypePattern() {
+        return typePattern;
+    }
+    
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.AnnotationTypePattern#matches(org.aspectj.weaver.AnnotatedElement)
+        */
+       public FuzzyBoolean matches(AnnotatedElement annotated) {
+               return matches(annotated,null);
+       }
+
+       /**
+        * Resolve any annotation values specified, checking they are all well formed (valid names, valid values)
+        * @param annotationType the annotation type for which the values have been specified
+        * @param scope the scope within which to resolve type references (eg. Color.GREEN)
+        */
+       protected void resolveAnnotationValues(ResolvedType annotationType, IScope scope) {
+               if (annotationValues == null) return;
+               // Check any values specified are OK:
+               // - the value names are for valid annotation fields
+               // - the specified values are of the correct type
+               // - for enums, check the specified values can be resolved in the specified scope
+               Set keys = annotationValues.keySet();
+               ResolvedMember[] ms = annotationType.getDeclaredMethods();
+               for (Iterator kIter = keys.iterator(); kIter.hasNext();) {
+                       String k = (String) kIter.next();
+                       String v = (String) annotationValues.get(k);
+                       boolean validKey = false;
+                       for (int i = 0; i < ms.length; i++) {
+                               ResolvedMember resolvedMember = ms[i];
+                               if (resolvedMember.getName().equals(k) && resolvedMember.isAbstract()) {
+                                       validKey = true;
+                                       ResolvedType t = resolvedMember.getReturnType().resolve(scope.getWorld());
+                                       if (t.isEnum()) {
+                                               // value must be an enum reference X.Y
+                                               int pos = v.lastIndexOf(".");
+                                               if (pos == -1) {
+                                                       IMessage m = MessageUtil.error(
+                                                                       WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"enum"),
+                                                                       getSourceLocation());
+                                                       scope.getWorld().getMessageHandler().handleMessage(m);                                                  
+                                               } else {
+                                                       String typename = v.substring(0,pos);
+                                                       ResolvedType rt = scope.lookupType(typename, this).resolve(scope.getWorld());
+                                                       v = rt.getSignature()+v.substring(pos+1); // from 'Color.RED' to 'Lp/Color;RED'
+                                                       annotationValues.put(k,v);
+                                               }
+                                       } else if (t.isPrimitiveType()) {
+                                               if (t.getSignature()=="I") {
+                                                  try {
+                                                          int value = Integer.parseInt(v);
+                                                          annotationValues.put(k,Integer.toString(value));
+                                                  } catch (NumberFormatException nfe) {
+                                                          IMessage m = MessageUtil.error(
+                                                                               WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"int"),
+                                                                               getSourceLocation());
+                                                               scope.getWorld().getMessageHandler().handleMessage(m);  
+                                                  }
+                                               } else if (t.getSignature()=="F") {
+                                                          try {
+                                                                  float value = Float.parseFloat(v);
+                                                                  annotationValues.put(k,Float.toString(value));
+                                                          } catch (NumberFormatException nfe) {
+                                                                  IMessage m = MessageUtil.error(
+                                                                                       WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"float"),
+                                                                                       getSourceLocation());
+                                                                       scope.getWorld().getMessageHandler().handleMessage(m);  
+                                                          }    
+
+                                               } else if (t.getSignature()=="Z") {
+                                                       if (v.equalsIgnoreCase("true") || v.equalsIgnoreCase("false")) {
+                                                               // is it ok !
+                                                       } else {
+                                                                  IMessage m = MessageUtil.error(
+                                                                                       WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"boolean"),
+                                                                                       getSourceLocation());
+                                                                       scope.getWorld().getMessageHandler().handleMessage(m);  
+                                                  }    
+                                               } else if (t.getSignature()=="S") {
+                                                                  try {
+                                                                          short value = Short.parseShort(v);
+                                                                          annotationValues.put(k,Short.toString(value));
+                                                                  } catch (NumberFormatException nfe) {
+                                                                          IMessage m = MessageUtil.error(
+                                                                                               WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"short"),
+                                                                                               getSourceLocation());
+                                                                               scope.getWorld().getMessageHandler().handleMessage(m);  
+                                                                  }
+                                               } else if (t.getSignature()=="J") {
+                                                          try {
+                                                                  long value = Long.parseLong(v);
+                                                                  annotationValues.put(k,Long.toString(value));
+                                                          } catch (NumberFormatException nfe) {
+                                                                  IMessage m = MessageUtil.error(
+                                                                                       WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"long"),
+                                                                                       getSourceLocation());
+                                                                       scope.getWorld().getMessageHandler().handleMessage(m);  
+                                                          }
+                                               } else if (t.getSignature()=="D") {
+                                                          try {
+                                                                  double value = Double.parseDouble(v);
+                                                                  annotationValues.put(k,Double.toString(value));
+                                                          } catch (NumberFormatException nfe) {
+                                                                  IMessage m = MessageUtil.error(
+                                                                                       WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"double"),
+                                                                                       getSourceLocation());
+                                                                       scope.getWorld().getMessageHandler().handleMessage(m);  
+                                                          }
+                                               } else if (t.getSignature()=="B") {
+                                                          try {
+                                                                  byte value = Byte.parseByte(v);
+                                                                  annotationValues.put(k,Byte.toString(value));
+                                                          } catch (NumberFormatException nfe) {
+                                                                  IMessage m = MessageUtil.error(
+                                                                                       WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"byte"),
+                                                                                       getSourceLocation());
+                                                                       scope.getWorld().getMessageHandler().handleMessage(m);  
+                                                          }
+                                               } else if (t.getSignature()=="C") {
+                                                       if (v.length()!=3) {  // '?'
+                                                                 IMessage m = MessageUtil.error(
+                                                                                       WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"char"),
+                                                                                       getSourceLocation());
+                                                                       scope.getWorld().getMessageHandler().handleMessage(m);  
+                                                       } else {
+                                                               annotationValues.put(k,v.substring(1,2));
+                                                       }
+                                               } else {
+                                                       throw new RuntimeException("Not implemented for "+t);
+                                               }
+                                       } else if (t.equals(ResolvedType.JAVA_LANG_STRING)) {
+                                               // nothing to do, it will be OK
+                                       } else {
+                                               throw new RuntimeException("Compiler limitation: annotation value support not implemented for type "+t);
+                                       }
+                               }
+                       }
+                       if (!validKey) {
+                               IMessage m = MessageUtil.error(
+                                               WeaverMessages.format(WeaverMessages.UNKNOWN_ANNOTATION_VALUE,annotationType,k),
+                                               getSourceLocation());
+                               scope.getWorld().getMessageHandler().handleMessage(m);  
+                       }
+               }
+       }
+
+
+
+
+       public FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations) {
+               if (!resolved) {
+                       throw new IllegalStateException("Can't match on an unresolved annotation type pattern");
+               }
+               if (annotationValues!=null) {
+                       // PVAL improve this restriction, would allow '*(value=Color.RED)'
+                       throw new IllegalStateException("Cannot use annotationvalues with a wild annotation pattern");
+               }
+               if (isForParameterAnnotationMatch()) {
+                       if (parameterAnnotations!=null && parameterAnnotations.length!=0) {
+                               for (int i = 0; i < parameterAnnotations.length; i++) {
+                                       if (typePattern.matches(parameterAnnotations[i],TypePattern.STATIC).alwaysTrue()) {
+                                               return FuzzyBoolean.YES;
+                                       }
+                               }
+                       }
+               } else {
+                       // matches if the type of any of the annotations on the AnnotatedElement is
+                       // matched by the typePattern.
+                       ResolvedType[] annTypes = annotated.getAnnotationTypes();
+                       if (annTypes!=null && annTypes.length!=0) {
+                               for (int i = 0; i < annTypes.length; i++) {
+                                       if (typePattern.matches(annTypes[i],TypePattern.STATIC).alwaysTrue()) {
+                                               return FuzzyBoolean.YES;
+                                       }
+                               }
+                       }
+               }
+               return FuzzyBoolean.NO;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.AnnotationTypePattern#resolve(org.aspectj.weaver.World)
+        */
+       public void resolve(World world) {
+               // nothing to do...
+           resolved = true;
+       }
+       
+       /**
+        * This can modify in place, or return a new TypePattern if the type changes.
+        */
+    public AnnotationTypePattern resolveBindings(IScope scope, Bindings bindings, 
+                                                                            boolean allowBinding)
+    { 
+       if (!scope.getWorld().isInJava5Mode()) {
+               scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.ANNOTATIONS_NEED_JAVA5),
+                               getSourceLocation()));
+               return this;
+       }
+       if (resolved) return this;
+       this.typePattern = typePattern.resolveBindings(scope,bindings,false,false);
+       resolved = true;
+       if (typePattern instanceof ExactTypePattern) {
+               ExactTypePattern et = (ExactTypePattern)typePattern;
+                       if (!et.getExactType().resolve(scope.getWorld()).isAnnotation()) {
+                               IMessage m = MessageUtil.error(
+                                               WeaverMessages.format(WeaverMessages.REFERENCE_TO_NON_ANNOTATION_TYPE,et.getExactType().getName()),
+                                               getSourceLocation());
+                               scope.getWorld().getMessageHandler().handleMessage(m);
+                               resolved = false;
+                       }
+                       ResolvedType annotationType = et.getExactType().resolve(scope.getWorld());
+               resolveAnnotationValues(annotationType,scope);
+               ExactAnnotationTypePattern eatp = new ExactAnnotationTypePattern(annotationType,annotationValues);
+               eatp.copyLocationFrom(this);
+           if (isForParameterAnnotationMatch()) eatp.setForParameterAnnotationMatch();
+               return eatp;
+       } else {
+               return this;
+       }
+    }
+    
+    public AnnotationTypePattern parameterizeWith(Map typeVariableMap,World w) {
+       WildAnnotationTypePattern ret = new WildAnnotationTypePattern(typePattern.parameterizeWith(typeVariableMap,w));
+       ret.copyLocationFrom(this);
+       ret.resolved = resolved;
+       return ret;
+    }
+
+       private static final byte VERSION = 1; // rev if ser. form changes
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(AnnotationTypePattern.WILD);
+               s.writeByte(VERSION);
+               typePattern.write(s);
+               writeLocation(s);
+               s.writeBoolean(isForParameterAnnotationMatch());
+               // PVAL
+               if (annotationValues==null) {
+                       s.writeInt(0);
+               } else {
+                       s.writeInt(annotationValues.size());
+                       Set key = annotationValues.keySet();
+                       for (Iterator keys = key.iterator(); keys.hasNext();) {
+                               String k = (String) keys.next();
+                               s.writeUTF(k);
+                               s.writeUTF((String)annotationValues.get(k));
+                       }
+               }
+       }
+
+       public static AnnotationTypePattern read(VersionedDataInputStream s,ISourceContext context) throws IOException {
+               WildAnnotationTypePattern ret;
+               byte version = s.readByte();
+               if (version > VERSION) {
+                       throw new BCException("ExactAnnotationTypePattern was written by a newer version of AspectJ");
+               }
+               TypePattern t = TypePattern.read(s,context);
+               ret = new WildAnnotationTypePattern(t);
+               ret.readLocation(context,s);
+               if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160) {
+                       if (s.readBoolean()) ret.setForParameterAnnotationMatch();
+               }
+               if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160M2) {
+                       int annotationValueCount = s.readInt();
+                       if (annotationValueCount>0) {
+                               Map aValues = new HashMap();
+                               for (int i=0;i<annotationValueCount;i++) {
+                                       String key = s.readUTF();
+                                       String val = s.readUTF();
+                                       aValues.put(key,val);
+                               }
+                               ret.annotationValues = aValues;
+                       }
+               }
+               return ret;             
+       }
+
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       public boolean equals(Object obj) {
+               if (!(obj instanceof WildAnnotationTypePattern)) return false;
+               WildAnnotationTypePattern other = (WildAnnotationTypePattern) obj;
+               return other.typePattern.equals(typePattern) && 
+                   this.isForParameterAnnotationMatch()==other.isForParameterAnnotationMatch() &&
+                   (annotationValues==null?other.annotationValues==null:annotationValues.equals(other.annotationValues));
+       }
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       public int hashCode() {
+               return (((17 + 37*typePattern.hashCode())*37+(isForParameterAnnotationMatch()?0:1))*37)+(annotationValues==null?0:annotationValues.hashCode());
+       }
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       public String toString() {
+               return "@(" + typePattern.toString() + ")";
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildTypePattern.java
new file mode 100644 (file)
index 0000000..73e3617
--- /dev/null
@@ -0,0 +1,1289 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.Message;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FileUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.BoundedReferenceType;
+import org.aspectj.weaver.IHasPosition;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ReferenceType;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.TypeFactory;
+import org.aspectj.weaver.TypeVariable;
+import org.aspectj.weaver.TypeVariableReference;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.UnresolvedTypeVariableReferenceType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+
+/**
+ * The PatternParser always creates WildTypePatterns for type patterns in pointcut
+ * expressions (apart from *, which is sometimes directly turned into TypePattern.ANY).
+ * resolveBindings() tries to work out what we've really got and turn it into a type
+ * pattern that we can use for matching. This will normally be either an ExactTypePattern
+ * or a WildTypePattern.
+ * 
+ * Here's how the process pans out for various generic and parameterized patterns:
+ * (see GenericsWildTypePatternResolvingTestCase)
+ * 
+ * Foo where Foo exists and is generic
+ *    Parser creates WildTypePattern namePatterns={Foo}
+ *    resolveBindings resolves Foo to RT(Foo - raw)
+ *                    return ExactTypePattern(LFoo;)
+ * 
+ * Foo<String> where Foo exists and String meets the bounds
+ *    Parser creates WildTypePattern namePatterns = {Foo}, typeParameters=WTP{String}
+ *    resolveBindings resolves typeParameters to ExactTypePattern(String)
+ *                    resolves Foo to RT(Foo)
+ *                    returns ExactTypePattern(PFoo<String>; - parameterized)
+ *                    
+ * Foo<Str*> where Foo exists and takes one bound
+ *    Parser creates WildTypePattern namePatterns = {Foo}, typeParameters=WTP{Str*}
+ *    resolveBindings resolves typeParameters to WTP{Str*}
+ *                    resolves Foo to RT(Foo)
+ *                    returns WildTypePattern(name = Foo, typeParameters = WTP{Str*} isGeneric=false)                    
+ * 
+ * Fo*<String> 
+ *    Parser creates WildTypePattern namePatterns = {Fo*}, typeParameters=WTP{String}
+ *    resolveBindings resolves typeParameters to ETP{String}
+ *                    returns WildTypePattern(name = Fo*, typeParameters = ETP{String} isGeneric=false)                    
+ *
+ * 
+ * Foo<?>
+ * 
+ * Foo<? extends Number>
+ * 
+ * Foo<? extends Number+>
+ * 
+ * Foo<? super Number>
+ * 
+ */
+public class WildTypePattern extends TypePattern {
+       private static final String GENERIC_WILDCARD_CHARACTER = "?"; // signature of ? is *
+       private static final String GENERIC_WILDCARD_SIGNATURE_CHARACTER = "*"; // signature of ? is *
+       private NamePattern[] namePatterns;
+       int ellipsisCount;
+       String[] importedPrefixes;
+       String[] knownMatches;
+       int dim;
+       
+       // SECRETAPI - just for testing, turns off boundschecking temporarily...
+       public static boolean boundscheckingoff = false;
+       
+       // these next three are set if the type pattern is constrained by extends or super clauses, in which case the
+       // namePatterns must have length 1
+       // TODO AMC: read/write/resolve of these fields
+       TypePattern upperBound;  //  extends Foo 
+       TypePattern[] additionalInterfaceBounds;  // extends Foo & A,B,C
+       TypePattern lowerBound;  // super Foo
+
+       // if we have type parameters, these fields indicate whether we should be a generic type pattern or a parameterized
+       // type pattern. We can only tell during resolve bindings.
+       private boolean isGeneric = true;
+       
+       WildTypePattern(NamePattern[] namePatterns, boolean includeSubtypes, int dim, boolean isVarArgs, TypePatternList typeParams) {
+               super(includeSubtypes,isVarArgs,typeParams);
+               this.namePatterns = namePatterns;
+               this.dim = dim;
+               ellipsisCount = 0;
+               for (int i=0; i<namePatterns.length; i++) {
+                       if (namePatterns[i] == NamePattern.ELLIPSIS) ellipsisCount++;
+               }
+               setLocation(namePatterns[0].getSourceContext(), namePatterns[0].getStart(), namePatterns[namePatterns.length-1].getEnd());
+       }
+
+       public WildTypePattern(List names, boolean includeSubtypes, int dim) {
+               this((NamePattern[])names.toArray(new NamePattern[names.size()]), includeSubtypes, dim,false,TypePatternList.EMPTY);
+
+       }
+       
+       public WildTypePattern(List names, boolean includeSubtypes, int dim, int endPos) {
+               this(names, includeSubtypes, dim);
+               this.end = endPos;
+       }
+
+       public WildTypePattern(List names, boolean includeSubtypes, int dim, int endPos, boolean isVarArg) {
+               this(names, includeSubtypes, dim);
+               this.end = endPos;
+               this.isVarArgs = isVarArg;
+       }
+       
+       public WildTypePattern(
+                       List names, 
+                       boolean includeSubtypes, 
+                       int dim, 
+                       int endPos, 
+                       boolean isVarArg, 
+                       TypePatternList typeParams,
+                       TypePattern upperBound,
+                       TypePattern[] additionalInterfaceBounds,
+                       TypePattern lowerBound) {
+               this((NamePattern[])names.toArray(new NamePattern[names.size()]),includeSubtypes,dim,isVarArg,typeParams);
+               this.end = endPos;
+               this.upperBound = upperBound;
+               this.lowerBound = lowerBound;
+               this.additionalInterfaceBounds = additionalInterfaceBounds;
+       }
+       
+       public WildTypePattern(
+                       List names, 
+                       boolean includeSubtypes, 
+                       int dim, 
+                       int endPos, 
+                       boolean isVarArg, 
+                       TypePatternList typeParams)
+       {
+               this((NamePattern[])names.toArray(new NamePattern[names.size()]),includeSubtypes,dim,isVarArg,typeParams);
+               this.end = endPos;              
+       }
+       
+    public NamePattern[] getNamePatterns() {
+        return namePatterns;
+    }
+       
+       public TypePattern getUpperBound() { return upperBound; }
+       public TypePattern getLowerBound() { return lowerBound; }
+       public TypePattern[] getAdditionalIntefaceBounds() { return additionalInterfaceBounds; }
+
+       // called by parser after parsing a type pattern, must bump dim as well as setting flag
+       public void setIsVarArgs(boolean isVarArgs) {
+               this.isVarArgs = isVarArgs;
+               if (isVarArgs) this.dim += 1;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
+        */
+       protected boolean couldEverMatchSameTypesAs(TypePattern other) {
+               if (super.couldEverMatchSameTypesAs(other)) return true;
+               // false is necessary but not sufficient
+               UnresolvedType otherType = other.getExactType();
+               if (!ResolvedType.isMissing(otherType)) {
+                       if (namePatterns.length > 0) {
+                               if (!namePatterns[0].matches(otherType.getName())) return false;
+                       }
+               } 
+               if (other instanceof WildTypePattern) {
+                       WildTypePattern owtp = (WildTypePattern) other;
+                       String mySimpleName = namePatterns[0].maybeGetSimpleName();
+                       String yourSimpleName = owtp.namePatterns[0].maybeGetSimpleName();
+                       if (mySimpleName != null && yourSimpleName != null) {
+                               return (mySimpleName.startsWith(yourSimpleName) ||
+                                               yourSimpleName.startsWith(mySimpleName));
+                       }
+               }
+               return true;
+       }
+       
+       //XXX inefficient implementation
+       // we don't know whether $ characters are from nested types, or were
+       // part of the declared type name (generated code often uses $s in type
+       // names). More work required on our part to get this right...
+       public static char[][] splitNames(String s, boolean convertDollar) {
+               List ret = new ArrayList();
+               int startIndex = 0;
+               while (true) {
+                   int breakIndex = s.indexOf('.', startIndex);  // what about /
+                   if (convertDollar && (breakIndex == -1)) breakIndex = s.indexOf('$', startIndex);  // we treat $ like . here
+                   if (breakIndex == -1) break;
+                   char[] name = s.substring(startIndex, breakIndex).toCharArray();
+                   ret.add(name);
+                   startIndex = breakIndex+1;
+               }
+               ret.add(s.substring(startIndex).toCharArray());
+               return (char[][])ret.toArray(new char[ret.size()][]);
+       }       
+       
+
+       /**
+        * @see org.aspectj.weaver.TypePattern#matchesExactly(IType)
+        */
+       protected boolean matchesExactly(ResolvedType type) {
+               return matchesExactly(type,type);
+       }
+
+       protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
+               String targetTypeName = type.getName();
+               
+               //System.err.println("match: " + targetTypeName + ", " + knownMatches); //Arrays.asList(importedPrefixes));
+               // Ensure the annotation pattern is resolved
+               annotationPattern.resolve(type.getWorld());
+               
+               return matchesExactlyByName(targetTypeName,type.isAnonymous(),type.isNested()) &&
+                       matchesParameters(type,STATIC) &&
+                       matchesBounds(type,STATIC) && 
+                      annotationPattern.matches(annotatedType,type.temporaryAnnotationTypes).alwaysTrue();
+       }
+       
+       
+       // we've matched against the base (or raw) type, but if this type pattern specifies parameters or
+       // type variables we need to make sure we match against them too
+       private boolean matchesParameters(ResolvedType aType, MatchKind staticOrDynamic) {
+               if (!isGeneric && typeParameters.size() > 0) {
+                       if(!aType.isParameterizedType()) return false;
+                       // we have to match type parameters
+                       return typeParameters.matches(aType.getResolvedTypeParameters(), staticOrDynamic).alwaysTrue();
+               }
+               return true;
+       }
+       
+       // we've matched against the base (or raw) type, but if this type pattern specifies bounds because
+       // it is a ? extends or ? super deal then we have to match them too.
+       private boolean matchesBounds(ResolvedType aType, MatchKind staticOrDynamic) {
+           if (!(aType instanceof BoundedReferenceType)) return true;
+           BoundedReferenceType boundedRT = (BoundedReferenceType) aType;
+               if (upperBound == null && boundedRT.getUpperBound() != null) {
+                       // for upper bound, null can also match against Object - but anything else and we're out.
+                       if (!boundedRT.getUpperBound().getName().equals(UnresolvedType.OBJECT.getName())) {
+                               return false;
+                       }
+               }
+               if (lowerBound == null && boundedRT.getLowerBound() != null) return false;
+               if (upperBound != null) {
+                       // match ? extends
+                       if (aType.isGenericWildcard() && boundedRT.isSuper()) return false;
+            if (boundedRT.getUpperBound() == null) return false;
+            return upperBound.matches((ResolvedType) boundedRT.getUpperBound(), staticOrDynamic).alwaysTrue();
+               }
+               if (lowerBound != null) {
+                       // match ? super
+                       if (!(boundedRT.isGenericWildcard() && boundedRT.isSuper())) return false;
+            return lowerBound.matches((ResolvedType) boundedRT.getLowerBound(), staticOrDynamic).alwaysTrue();
+               }
+               return true;
+       }
+       
+       /**
+        * Used in conjunction with checks on 'isStar()' to tell you if this pattern represents '*' or '*[]' which are 
+        * different !
+        */
+       public int getDimensions() {
+               return dim;
+       }
+       
+       public boolean isArray() {
+               return dim > 1;
+       }
+       
+    /**
+        * @param targetTypeName
+        * @return
+        */
+       private boolean matchesExactlyByName(String targetTypeName, boolean isAnonymous, boolean isNested) {
+               // we deal with parameter matching separately...
+               if (targetTypeName.indexOf('<') != -1) {
+                       targetTypeName = targetTypeName.substring(0,targetTypeName.indexOf('<'));
+               }
+               // we deal with bounds matching separately too...
+               if (targetTypeName.startsWith(GENERIC_WILDCARD_CHARACTER)) {
+                       targetTypeName = GENERIC_WILDCARD_CHARACTER;
+               }
+               //XXX hack
+               if (knownMatches == null && importedPrefixes == null) {
+                       return innerMatchesExactly(targetTypeName, isAnonymous, isNested);
+               }
+               
+               if (isNamePatternStar()) {
+                       // we match if the dimensions match
+                       int numDimensionsInTargetType = 0;
+                       if (dim > 0) {
+                               int index;
+                               while((index = targetTypeName.indexOf('[')) != -1) {
+                                       numDimensionsInTargetType++;
+                                       targetTypeName = targetTypeName.substring(index+1);
+                               }
+                               if (numDimensionsInTargetType == dim) {
+                                       return true;
+                               } else {
+                                       return false;
+                               }
+                       }
+               }
+               
+               // if our pattern is length 1, then known matches are exact matches
+               // if it's longer than that, then known matches are prefixes of a sort
+               if (namePatterns.length == 1) {
+                       if (isAnonymous) {
+                               // we've already ruled out "*", and no other name pattern should match an anonymous type
+                               return false;
+                       }
+                       for (int i=0, len=knownMatches.length; i < len; i++) {
+                               if (knownMatches[i].equals(targetTypeName)) return true;
+                       }
+               } else {
+                       for (int i=0, len=knownMatches.length; i < len; i++) {
+                               String knownPrefix = knownMatches[i] + "$";
+                               if (targetTypeName.startsWith(knownPrefix)) {
+                                       int pos = lastIndexOfDotOrDollar(knownMatches[i]);
+                                       if (innerMatchesExactly(targetTypeName.substring(pos+1),isAnonymous,isNested)) {
+                                               return true;
+                                       }
+                               }
+                       }
+               }
+
+
+               // if any prefixes match, strip the prefix and check that the rest matches
+               // assumes that prefixes have a dot at the end
+               for (int i=0, len=importedPrefixes.length; i < len; i++) {
+                       String prefix = importedPrefixes[i];
+                       //System.err.println("prefix match? " + prefix + " to " + targetTypeName);
+                       if (targetTypeName.startsWith(prefix)) {
+                               
+                               if (innerMatchesExactly(targetTypeName.substring(prefix.length()),isAnonymous,isNested)) {
+                                       return true;
+                               }
+                       }
+               }
+               
+               return innerMatchesExactly(targetTypeName,isAnonymous,isNested);
+       }
+
+       private int lastIndexOfDotOrDollar(String string) {
+       int dot = string.lastIndexOf('.');
+       int dollar = string.lastIndexOf('$');
+       return Math.max(dot, dollar);
+    }
+
+       
+
+    private boolean innerMatchesExactly(String s, boolean isAnonymous, boolean convertDollar /*isNested*/) {
+                       
+               List ret = new ArrayList();
+               int startIndex = 0;
+               while (true) {
+                   int breakIndex = s.indexOf('.', startIndex);  // what about /
+                   if (convertDollar && (breakIndex == -1)) breakIndex = s.indexOf('$', startIndex);  // we treat $ like . here
+                   if (breakIndex == -1) break;
+                   char[] name = s.substring(startIndex, breakIndex).toCharArray();
+                   ret.add(name);
+                   startIndex = breakIndex+1;
+               }
+               ret.add(s.substring(startIndex).toCharArray());
+       
+               int namesLength = ret.size();
+               int patternsLength = namePatterns.length;
+               
+               int namesIndex = 0;
+               int patternsIndex = 0;
+                       if ((!namePatterns[patternsLength-1].isAny()) && isAnonymous) return false;
+                        
+                       if (ellipsisCount == 0) {
+                               if (namesLength != patternsLength) return false;
+                               while (patternsIndex < patternsLength) {
+                                       if (!namePatterns[patternsIndex++].matches((char[])ret.get(namesIndex++))) {
+                                               return false;
+                                       }
+                               }
+                               return true;
+                       } else if (ellipsisCount == 1) {
+                               if (namesLength < patternsLength-1) return false;
+                               while (patternsIndex < patternsLength) {
+                                       NamePattern p = namePatterns[patternsIndex++];
+                                       if (p == NamePattern.ELLIPSIS) {
+                                               namesIndex = namesLength - (patternsLength-patternsIndex);
+                                       } else {
+                                           if (!p.matches((char[])ret.get(namesIndex++))) {
+                                                   return false;
+                                           }
+                                       }
+                               }
+                               return true;
+                       } else {
+        //            System.err.print("match(\"" + Arrays.asList(namePatterns) + "\", \"" + Arrays.asList(names) + "\") -> ");
+                    boolean b = outOfStar(namePatterns, (char[][])ret.toArray(new char[ret.size()][]), 0, 0, patternsLength - ellipsisCount, namesLength, ellipsisCount);
+        //            System.err.println(b);
+                    return b;
+                       }
+    }
+    private static boolean outOfStar(final NamePattern[] pattern, final char[][] target, 
+                                              int           pi,            int       ti, 
+                                              int           pLeft,         int       tLeft,
+                                       final int            starsLeft) {
+        if (pLeft > tLeft) return false;
+        while (true) {
+            // invariant: if (tLeft > 0) then (ti < target.length && pi < pattern.length) 
+            if (tLeft == 0) return true;
+            if (pLeft == 0) {
+                return (starsLeft > 0);  
+            }
+            if (pattern[pi] == NamePattern.ELLIPSIS) {
+                return inStar(pattern, target, pi+1, ti, pLeft, tLeft, starsLeft-1);
+            }
+            if (! pattern[pi].matches(target[ti])) {
+                return false;
+            }
+            pi++; ti++; pLeft--; tLeft--;
+        }
+    }    
+    private static boolean inStar(final NamePattern[] pattern, final char[][] target, 
+                                            int          pi,            int      ti, 
+                                     final int          pLeft,          int      tLeft,
+                                            int         starsLeft) {
+        // invariant: pLeft > 0, so we know we'll run out of stars and find a real char in pattern
+        // of course, we probably can't parse multiple ..'s in a row, but this keeps the algorithm
+        // exactly parallel with that in NamePattern
+        NamePattern patternChar = pattern[pi];
+        while (patternChar == NamePattern.ELLIPSIS) {
+            starsLeft--;
+            patternChar = pattern[++pi];
+        }
+        while (true) {
+            // invariant: if (tLeft > 0) then (ti < target.length)
+            if (pLeft > tLeft) return false;
+            if (patternChar.matches(target[ti])) {
+                if (outOfStar(pattern, target, pi+1, ti+1, pLeft-1, tLeft-1, starsLeft)) return true;
+            }
+            ti++; tLeft--;
+        }
+    }
+       
+       /**
+        * @see org.aspectj.weaver.TypePattern#matchesInstanceof(IType)
+        */
+       public FuzzyBoolean matchesInstanceof(ResolvedType type) {
+               //XXX hack to let unmatched types just silently remain so
+               if (maybeGetSimpleName() != null) return
+                FuzzyBoolean.NO;
+               
+               type.getWorld().getMessageHandler().handleMessage(
+                       new Message("can't do instanceof matching on patterns with wildcards",
+                               IMessage.ERROR, null, getSourceLocation()));
+               return FuzzyBoolean.NO;
+       }
+
+       public NamePattern extractName() {
+               if (isIncludeSubtypes() || isVarArgs() || isArray() || (typeParameters.size() > 0)) {
+                       // we can't extract a name, the pattern is something like Foo+ and therefore
+                       // it is not ok to treat Foo as a method name!
+                       return null;
+               }
+               //System.err.println("extract from : " + Arrays.asList(namePatterns));
+               int len = namePatterns.length;
+               if (len ==1 && !annotationPattern.isAny()) return null; // can't extract
+               NamePattern ret = namePatterns[len-1];
+               NamePattern[] newNames = new NamePattern[len-1];
+               System.arraycopy(namePatterns, 0, newNames, 0, len-1);
+               namePatterns = newNames;
+               //System.err.println("    left : " + Arrays.asList(namePatterns));
+               return ret;
+       }
+       
+       /**
+        * Method maybeExtractName.
+        * @param string
+        * @return boolean
+        */
+       public boolean maybeExtractName(String string) {
+               int len = namePatterns.length;
+               NamePattern ret = namePatterns[len-1];
+               String simple = ret.maybeGetSimpleName();
+               if (simple != null && simple.equals(string)) {
+                       extractName();
+                       return true;
+               }
+               return false;
+       }
+       
+       /**
+        * If this type pattern has no '.' or '*' in it, then
+        * return a simple string
+        * 
+        * otherwise, this will return null;
+        */
+       public String maybeGetSimpleName() {
+               if (namePatterns.length == 1) {
+                       return namePatterns[0].maybeGetSimpleName();
+               }
+               return null;
+       }
+       
+       /**
+        * If this type pattern has no '*' or '..' in it
+        */
+       public String maybeGetCleanName() {
+               if (namePatterns.length == 0) {
+                       throw new RuntimeException("bad name: " + namePatterns);
+               }
+               //System.out.println("get clean: " + this);
+               StringBuffer buf = new StringBuffer();
+               for (int i=0, len=namePatterns.length; i < len; i++) {
+                       NamePattern p = namePatterns[i];
+                       String simpleName = p.maybeGetSimpleName();
+                       if (simpleName == null) return null;
+                       if (i > 0) buf.append(".");
+                       buf.append(simpleName);
+               }
+               //System.out.println(buf);
+               return buf.toString();
+       }               
+
+       public TypePattern parameterizeWith(Map typeVariableMap,World w) {
+               NamePattern[] newNamePatterns = new NamePattern[namePatterns.length];
+               for(int i=0; i<namePatterns.length;i++) { newNamePatterns[i] = namePatterns[i]; }
+               if (newNamePatterns.length == 1) {
+                       String simpleName = newNamePatterns[0].maybeGetSimpleName();
+                       if (simpleName != null) {
+                               if (typeVariableMap.containsKey(simpleName)) {
+                                       String newName = ((ReferenceType)typeVariableMap.get(simpleName)).getName().replace('$','.');
+                                       StringTokenizer strTok = new StringTokenizer(newName,".");
+                                       newNamePatterns = new NamePattern[strTok.countTokens()];
+                                       int index = 0;
+                                       while(strTok.hasMoreTokens()) {
+                                               newNamePatterns[index++] = new NamePattern(strTok.nextToken());
+                                       }
+                               }
+                       }
+               }
+               WildTypePattern ret = new WildTypePattern(
+                               newNamePatterns,
+                               includeSubtypes,
+                               dim,
+                               isVarArgs,
+                               typeParameters.parameterizeWith(typeVariableMap,w)
+                       );
+               ret.annotationPattern = this.annotationPattern.parameterizeWith(typeVariableMap,w);
+               if (additionalInterfaceBounds == null) {
+                       ret.additionalInterfaceBounds = null;
+               } else {
+                       ret.additionalInterfaceBounds = new TypePattern[additionalInterfaceBounds.length];
+                       for (int i = 0; i < additionalInterfaceBounds.length; i++) {
+                               ret.additionalInterfaceBounds[i] = additionalInterfaceBounds[i].parameterizeWith(typeVariableMap,w);
+                       }
+               }
+               ret.upperBound = upperBound != null ? upperBound.parameterizeWith(typeVariableMap,w) : null;
+               ret.lowerBound = lowerBound != null ? lowerBound.parameterizeWith(typeVariableMap,w) : null;
+               ret.isGeneric = isGeneric;
+               ret.knownMatches = knownMatches;
+               ret.importedPrefixes = importedPrefixes;
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       /**
+        * Need to determine if I'm really a pattern or a reference to a formal
+        * 
+        * We may wish to further optimize the case of pattern vs. non-pattern
+        * 
+        * We will be replaced by what we return
+        */
+       public TypePattern resolveBindings(IScope scope, Bindings bindings, 
+                                                               boolean allowBinding, boolean requireExactType)
+    {          
+       if (isNamePatternStar()) {
+               TypePattern anyPattern = maybeResolveToAnyPattern(scope, bindings, allowBinding, requireExactType);
+               if (anyPattern != null) {
+                       if (requireExactType) {
+                               scope.getWorld().getMessageHandler().handleMessage(
+                                               MessageUtil.error(WeaverMessages.format(WeaverMessages.WILDCARD_NOT_ALLOWED),
+                                                                                       getSourceLocation()));
+                                       return NO;
+                       } else {
+                               return anyPattern;
+                       }
+               }
+               }
+
+       TypePattern bindingTypePattern = maybeResolveToBindingTypePattern(scope, bindings, allowBinding, requireExactType);
+       if (bindingTypePattern != null) return bindingTypePattern;
+       
+       annotationPattern = annotationPattern.resolveBindings(scope,bindings,allowBinding);
+       
+               // resolve any type parameters
+               if (typeParameters!=null && typeParameters.size()>0) {
+                       typeParameters.resolveBindings(scope,bindings,allowBinding,requireExactType);
+                       isGeneric = false;
+               }
+               
+               // resolve any bounds
+               if (upperBound != null) upperBound = upperBound.resolveBindings(scope, bindings, allowBinding, requireExactType);
+               if (lowerBound != null) lowerBound = lowerBound.resolveBindings(scope, bindings, allowBinding, requireExactType);
+               // amc - additional interface bounds only needed if we support type vars again.
+               
+               String fullyQualifiedName = maybeGetCleanName();
+               if (fullyQualifiedName != null) {
+                       return resolveBindingsFromFullyQualifiedTypeName(fullyQualifiedName, scope, bindings, allowBinding, requireExactType);
+               } else {
+                       if (requireExactType) {
+                               scope.getWorld().getMessageHandler().handleMessage(
+                                       MessageUtil.error(WeaverMessages.format(WeaverMessages.WILDCARD_NOT_ALLOWED),
+                                                                               getSourceLocation()));
+                               return NO;
+                       }
+                       importedPrefixes = scope.getImportedPrefixes();
+                       knownMatches = preMatch(scope.getImportedNames());                      
+                       return this;  // pattern contains wildcards so can't be resolved to an ExactTypePattern...
+                       //XXX need to implement behavior for Lint.invalidWildcardTypeName
+               }               
+       }
+       
+       private TypePattern maybeResolveToAnyPattern(IScope scope, Bindings bindings, 
+                       boolean allowBinding, boolean requireExactType) {
+           // If there is an annotation specified we have to
+           // use a special variant of Any TypePattern called
+           // AnyWithAnnotation
+               if (annotationPattern == AnnotationTypePattern.ANY) {
+                 if (dim == 0 && !isVarArgs && upperBound == null && lowerBound == null && (additionalInterfaceBounds == null || additionalInterfaceBounds.length==0)) { // pr72531
+                       return TypePattern.ANY;  //??? loses source location
+                 } 
+               } else if (!isVarArgs){
+               annotationPattern = annotationPattern.resolveBindings(scope,bindings,allowBinding);
+                       AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(annotationPattern);                         
+                       ret.setLocation(sourceContext,start,end);
+                       return ret;
+               }
+               return null; // can't resolve to a simple "any" pattern
+       }
+       
+       private TypePattern maybeResolveToBindingTypePattern(IScope scope, Bindings bindings, 
+                       boolean allowBinding, boolean requireExactType) {
+               String simpleName = maybeGetSimpleName();
+               if (simpleName != null) {
+                       FormalBinding formalBinding = scope.lookupFormal(simpleName);
+                       if (formalBinding != null) {
+                               if (bindings == null) {
+                                       scope.message(IMessage.ERROR, this, "negation doesn't allow binding");
+                                       return this;
+                               }
+                               if (!allowBinding) {
+                                       scope.message(IMessage.ERROR, this, 
+                                               "name binding only allowed in target, this, and args pcds");
+                                       return this;
+                               }
+                               
+                               BindingTypePattern binding = new BindingTypePattern(formalBinding,isVarArgs);
+                               binding.copyLocationFrom(this);
+                               bindings.register(binding, scope);
+                               
+                               return binding;
+                       }
+               }
+               return null; // not possible to resolve to a binding type pattern
+       }
+       
+       private TypePattern resolveBindingsFromFullyQualifiedTypeName(String fullyQualifiedName, IScope scope, Bindings bindings, 
+                       boolean allowBinding, boolean requireExactType) {
+               String originalName = fullyQualifiedName;
+               ResolvedType resolvedTypeInTheWorld = null;
+               UnresolvedType type;
+               
+               //System.out.println("resolve: " + cleanName);
+               //??? this loop has too many inefficiencies to count
+               resolvedTypeInTheWorld = lookupTypeInWorldIncludingPrefixes(scope.getWorld(), fullyQualifiedName, scope.getImportedPrefixes());
+
+               if (resolvedTypeInTheWorld.isGenericWildcard()) {
+                       type = resolvedTypeInTheWorld;
+               } else {
+                       type = lookupTypeInScope(scope, fullyQualifiedName, this);
+               }
+               if ((type instanceof ResolvedType) && ((ResolvedType)type).isMissing()) {
+                       return resolveBindingsForMissingType(resolvedTypeInTheWorld, originalName, scope, bindings, allowBinding, requireExactType);
+               } else {
+                       return resolveBindingsForExactType(scope,type,fullyQualifiedName,requireExactType);
+               }
+       }
+       
+       
+       
+       private UnresolvedType lookupTypeInScope(IScope scope, String typeName, IHasPosition location) {
+               UnresolvedType type = null;
+               while (ResolvedType.isMissing(type = scope.lookupType(typeName, location))) {
+                       int lastDot = typeName.lastIndexOf('.');
+                       if (lastDot == -1) break;
+                       typeName = typeName.substring(0, lastDot) + '$' + typeName.substring(lastDot+1);
+               }
+               return type;
+       }
+       
+       /**
+        * Searches the world for the ResolvedType with the given typeName. If one 
+        * isn't found then for each of the supplied prefixes, it prepends the typeName
+        * with the prefix and searches the world for the ResolvedType with this new name.
+        * If one still isn't found then a MissingResolvedTypeWithKnownSignature is 
+        * returned with the originally requested typeName (this ensures the typeName
+        * makes sense).
+        */
+       private ResolvedType lookupTypeInWorldIncludingPrefixes(World world, String typeName, String[] prefixes) {
+               ResolvedType ret = lookupTypeInWorld(world, typeName);
+               if (!ret.isMissing()) return ret; 
+               ResolvedType retWithPrefix = ret;
+               int counter = 0;
+               while (retWithPrefix.isMissing() && (counter < prefixes.length)) {
+                       retWithPrefix = lookupTypeInWorld(world,prefixes[counter] + typeName);
+                       counter++;
+               }
+               if (!retWithPrefix.isMissing()) return retWithPrefix;
+               return ret;
+       }
+       
+       private ResolvedType lookupTypeInWorld(World world, String typeName) {
+               UnresolvedType ut = UnresolvedType.forName(typeName);
+               ResolvedType ret = world.resolve(ut,true);
+               while (ret.isMissing()) {
+                       int lastDot = typeName.lastIndexOf('.');
+                       if (lastDot == -1) break;
+                       typeName = typeName.substring(0, lastDot) + '$' + typeName.substring(lastDot+1);
+                       ret = world.resolve(UnresolvedType.forName(typeName),true);
+               }
+               return ret;
+       }
+       
+       private TypePattern resolveBindingsForExactType(IScope scope, UnresolvedType aType, String fullyQualifiedName,boolean requireExactType) {
+               TypePattern ret = null;
+               if (aType.isTypeVariableReference()) {
+                       // we have to set the bounds on it based on the bounds of this pattern
+                       ret = resolveBindingsForTypeVariable(scope, (UnresolvedTypeVariableReferenceType) aType);
+               } else if (typeParameters.size()>0) {
+                       ret = resolveParameterizedType(scope, aType, requireExactType);
+               } else if (upperBound != null || lowerBound != null) {
+                       // this must be a generic wildcard with bounds
+                       ret = resolveGenericWildcard(scope, aType);                     
+               } else {
+                       if (dim != 0) aType = UnresolvedType.makeArray(aType, dim);
+                       ret = new ExactTypePattern(aType,includeSubtypes,isVarArgs);                                    
+               }
+               ret.setAnnotationTypePattern(annotationPattern);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       private TypePattern resolveGenericWildcard(IScope scope, UnresolvedType aType) {
+               if (!aType.getSignature().equals(GENERIC_WILDCARD_SIGNATURE_CHARACTER)) throw new IllegalStateException("Can only have bounds for a generic wildcard");
+               boolean canBeExact = true;
+               if ((upperBound != null) && ResolvedType.isMissing(upperBound.getExactType())) canBeExact = false;
+               if ((lowerBound != null) && ResolvedType.isMissing(lowerBound.getExactType())) canBeExact = false;
+               if (canBeExact) {
+                       ResolvedType type = null;
+                       if (upperBound != null) {
+                               if (upperBound.isIncludeSubtypes()) { 
+                                       canBeExact = false;
+                               } else {
+                                       ReferenceType upper = (ReferenceType) upperBound.getExactType().resolve(scope.getWorld());
+                                       type = new BoundedReferenceType(upper,true,scope.getWorld());
+                               }
+                       } else {
+                               if (lowerBound.isIncludeSubtypes()) {
+                                       canBeExact = false;
+                               } else {
+                                       ReferenceType lower = (ReferenceType) lowerBound.getExactType().resolve(scope.getWorld());
+                                       type = new BoundedReferenceType(lower,false,scope.getWorld());
+                               }
+                       }
+                       if (canBeExact) {
+                               // might have changed if we find out include subtypes is set on one of the bounds...
+                               return new ExactTypePattern(type,includeSubtypes,isVarArgs);
+                       }
+               } 
+       
+               // we weren't able to resolve to an exact type pattern...
+               // leave as wild type pattern
+               importedPrefixes = scope.getImportedPrefixes();
+               knownMatches = preMatch(scope.getImportedNames());
+               return this;    
+       }
+
+       private TypePattern resolveParameterizedType(IScope scope, UnresolvedType aType, boolean requireExactType) {
+               ResolvedType rt = aType.resolve(scope.getWorld());
+               if (!verifyTypeParameters(rt,scope,requireExactType)) return TypePattern.NO; // messages already isued
+               // Only if the type is exact *and* the type parameters are exact should we create an 
+               // ExactTypePattern for this WildTypePattern                                    
+               if (typeParameters.areAllExactWithNoSubtypesAllowed()) {
+                       TypePattern[] typePats = typeParameters.getTypePatterns();
+                       UnresolvedType[] typeParameterTypes = new UnresolvedType[typePats.length];
+                       for (int i = 0; i < typeParameterTypes.length; i++) {
+                               typeParameterTypes[i] = ((ExactTypePattern)typePats[i]).getExactType();
+                       }
+                       // rt could be a parameterized type 156058
+                       if (rt.isParameterizedType()) {
+                               rt = rt.getGenericType();
+                       }
+                       ResolvedType type = TypeFactory.createParameterizedType(rt, typeParameterTypes, scope.getWorld());
+                       if (isGeneric) type = type.getGenericType();
+//                             UnresolvedType tx = UnresolvedType.forParameterizedTypes(aType,typeParameterTypes);
+//                             UnresolvedType type = scope.getWorld().resolve(tx,true); 
+                       if (dim != 0) type = ResolvedType.makeArray(type, dim);
+                       return new ExactTypePattern(type,includeSubtypes,isVarArgs);
+               } else {
+                       // AMC... just leave it as a wild type pattern then?
+                       importedPrefixes = scope.getImportedPrefixes();
+                       knownMatches = preMatch(scope.getImportedNames());
+                       return this;
+               }
+       }
+       
+       private TypePattern resolveBindingsForMissingType(ResolvedType typeFoundInWholeWorldSearch, String nameWeLookedFor, IScope scope, Bindings bindings, 
+                       boolean allowBinding, boolean requireExactType) {
+               if (requireExactType) {
+                       if (!allowBinding) {
+                               scope.getWorld().getMessageHandler().handleMessage(
+                                       MessageUtil.error(WeaverMessages.format(WeaverMessages.CANT_BIND_TYPE,nameWeLookedFor),
+                                                                       getSourceLocation()));
+                       } else if (scope.getWorld().getLint().invalidAbsoluteTypeName.isEnabled()) {
+                               scope.getWorld().getLint().invalidAbsoluteTypeName.signal(nameWeLookedFor, getSourceLocation());
+                       }
+                       return NO;
+               } else if (scope.getWorld().getLint().invalidAbsoluteTypeName.isEnabled()) {
+                       // Only put the lint warning out if we can't find it in the world
+                       if (typeFoundInWholeWorldSearch.isMissing()) {
+                         scope.getWorld().getLint().invalidAbsoluteTypeName.signal(nameWeLookedFor, getSourceLocation());
+                       }
+               }
+               importedPrefixes = scope.getImportedPrefixes();
+               knownMatches = preMatch(scope.getImportedNames());
+               return this;            
+       }
+       
+       /**
+        * We resolved the type to a type variable declared in the pointcut designator.
+        * Now we have to create either an exact type pattern or a wild type pattern for it,
+        * with upper and lower bounds set accordingly.
+        * XXX none of this stuff gets serialized yet
+        * @param scope
+        * @param tvrType
+        * @return
+        */
+       private TypePattern resolveBindingsForTypeVariable(IScope scope, UnresolvedTypeVariableReferenceType tvrType) {
+               Bindings emptyBindings = new Bindings(0);
+               if (upperBound != null) {
+                       upperBound = upperBound.resolveBindings(scope, emptyBindings, false, false);
+               }
+               if (lowerBound != null) {
+                       lowerBound = lowerBound.resolveBindings(scope, emptyBindings, false, false);
+               }
+               if (additionalInterfaceBounds != null) {
+                       TypePattern[] resolvedIfBounds = new TypePattern[additionalInterfaceBounds.length];
+                       for (int i = 0; i < resolvedIfBounds.length; i++) {
+                               resolvedIfBounds[i] = additionalInterfaceBounds[i].resolveBindings(scope, emptyBindings, false, false);                         
+                       }
+                       additionalInterfaceBounds = resolvedIfBounds;
+               }
+               if ( upperBound == null && lowerBound == null && additionalInterfaceBounds == null) {
+                       // no bounds to worry about...
+                       ResolvedType rType = tvrType.resolve(scope.getWorld());
+                       if (dim != 0) rType = ResolvedType.makeArray(rType, dim);
+                       return new ExactTypePattern(rType,includeSubtypes,isVarArgs);                                                           
+               } else {
+                       // we have to set bounds on the TypeVariable held by tvrType before resolving it
+                       boolean canCreateExactTypePattern = true;
+                       if (upperBound != null && ResolvedType.isMissing(upperBound.getExactType())) canCreateExactTypePattern = false;
+                       if (lowerBound != null && ResolvedType.isMissing(lowerBound.getExactType())) canCreateExactTypePattern = false;
+                       if (additionalInterfaceBounds != null) {
+                               for (int i = 0; i < additionalInterfaceBounds.length; i++) {
+                                       if (ResolvedType.isMissing(additionalInterfaceBounds[i].getExactType())) canCreateExactTypePattern = false;
+                               }
+                       }
+                       if (canCreateExactTypePattern) {
+                               TypeVariable tv = tvrType.getTypeVariable();
+                               if (upperBound != null) tv.setUpperBound(upperBound.getExactType());
+                               if (lowerBound != null) tv.setLowerBound(lowerBound.getExactType());
+                               if (additionalInterfaceBounds != null) {
+                                       UnresolvedType[] ifBounds = new UnresolvedType[additionalInterfaceBounds.length];
+                                       for (int i = 0; i < ifBounds.length; i++) {
+                                               ifBounds[i] = additionalInterfaceBounds[i].getExactType();
+                                       }
+                                       tv.setAdditionalInterfaceBounds(ifBounds);
+                               }
+                               ResolvedType rType = tvrType.resolve(scope.getWorld());
+                               if (dim != 0) rType = ResolvedType.makeArray(rType, dim);
+                               return new ExactTypePattern(rType,includeSubtypes,isVarArgs);                                                           
+                       }
+                       return this;  // leave as wild type pattern then
+               }
+       }
+       
+       /**
+        * When this method is called, we have resolved the base type to an exact type.
+        * We also have a set of type patterns for the parameters.
+        * Time to perform some basic checks:
+        *  - can the base type be parameterized? (is it generic)
+        *  - can the type parameter pattern list match the number of parameters on the base type
+        *  - do all parameter patterns meet the bounds of the respective type variables
+        *  If any of these checks fail, a warning message is issued and we return false.
+        * @return
+        */
+       private boolean verifyTypeParameters(ResolvedType baseType,IScope scope, boolean requireExactType) {
+               ResolvedType genericType = baseType.getGenericType();
+               if (genericType == null) {
+                       // issue message "does not match because baseType.getName() is not generic"
+                       scope.message(MessageUtil.warn(
+                                       WeaverMessages.format(WeaverMessages.NOT_A_GENERIC_TYPE,baseType.getName()),
+                                       getSourceLocation()));
+                       return false;
+               }
+               int minRequiredTypeParameters = typeParameters.size();
+               boolean foundEllipsis = false;
+               TypePattern[] typeParamPatterns = typeParameters.getTypePatterns();
+               for (int i = 0; i < typeParamPatterns.length; i++) {
+                       if (typeParamPatterns[i] instanceof WildTypePattern) {
+                               WildTypePattern wtp = (WildTypePattern) typeParamPatterns[i];
+                               if (wtp.ellipsisCount > 0) {
+                                       foundEllipsis = true;
+                                       minRequiredTypeParameters--;
+                               }
+                       }
+               }
+               TypeVariable[] tvs = genericType.getTypeVariables();
+               if ((tvs.length < minRequiredTypeParameters) ||
+                       (!foundEllipsis && minRequiredTypeParameters != tvs.length))
+               {
+                       // issue message "does not match because wrong no of type params"
+                       String msg = WeaverMessages.format(WeaverMessages.INCORRECT_NUMBER_OF_TYPE_ARGUMENTS,
+                                                                  genericType.getName(),new Integer(tvs.length));
+                       if (requireExactType)   scope.message(MessageUtil.error(msg,getSourceLocation()));
+                       else                                    scope.message(MessageUtil.warn(msg,getSourceLocation()));
+                       return false;
+               } 
+               
+               // now check that each typeParameter pattern, if exact, matches the bounds
+               // of the type variable.
+               
+               // pr133307 - delay verification until type binding completion, these next few lines replace
+               // the call to checkBoundsOK
+               if (!boundscheckingoff) {
+                       VerifyBoundsForTypePattern verification = 
+                               new VerifyBoundsForTypePattern(scope,genericType,requireExactType,typeParameters,getSourceLocation());
+                       scope.getWorld().getCrosscuttingMembersSet().recordNecessaryCheck(verification);
+               }
+//             return checkBoundsOK(scope,genericType,requireExactType);
+               
+                return true;
+       }
+       
+       /**
+        * By capturing the verification in this class, rather than performing it in verifyTypeParameters(),
+        * we can cope with situations where the interactions between generics and declare parents would
+        * otherwise cause us problems.  For example, if verifying as we go along we may report a problem
+        * which would have been fixed by a declare parents that we haven't looked at yet.  If we
+        * create and store a verification object, we can verify this later when the type system is
+        * considered 'complete'
+        */
+       static class VerifyBoundsForTypePattern implements IVerificationRequired {
+               
+               private IScope scope;
+               private ResolvedType genericType;
+               private boolean requireExactType;
+               private TypePatternList typeParameters = TypePatternList.EMPTY;
+               private ISourceLocation sLoc;
+               
+               public VerifyBoundsForTypePattern(IScope scope, ResolvedType genericType, boolean requireExactType,
+                               TypePatternList typeParameters, ISourceLocation sLoc) {
+                       this.scope = scope;
+                       this.genericType = genericType;
+                       this.requireExactType = requireExactType;
+                       this.typeParameters = typeParameters;
+                       this.sLoc = sLoc;
+               }
+               
+               public void verify() {
+                       TypeVariable[] tvs = genericType.getTypeVariables();
+                       TypePattern[] typeParamPatterns = typeParameters.getTypePatterns();
+                       if (typeParameters.areAllExactWithNoSubtypesAllowed()) {
+                               for (int i = 0; i < tvs.length; i++) {
+                                       UnresolvedType ut = typeParamPatterns[i].getExactType();
+                                       boolean continueCheck = true;
+                                       // FIXME asc dont like this but ok temporary measure.  If the type parameter 
+                                       // is itself a type variable (from the generic aspect) then assume it'll be
+                                       // ok... (see pr112105)  Want to break this? Run GenericAspectK test.
+                                       if (ut.isTypeVariableReference()) {
+                                               continueCheck = false;
+                                       }
+                                       
+                                       //System.err.println("Verifying "+ut.getName()+" meets bounds for "+tvs[i]);
+                                       if (continueCheck &&    
+                                                       !tvs[i].canBeBoundTo(ut.resolve(scope.getWorld()))) {
+                                               // issue message that type parameter does not meet specification
+                                               String parameterName = ut.getName();
+                                               if (ut.isTypeVariableReference()) parameterName = ((TypeVariableReference)ut).getTypeVariable().getDisplayName();
+                                               String msg = 
+                                                       WeaverMessages.format(
+                                                               WeaverMessages.VIOLATES_TYPE_VARIABLE_BOUNDS,
+                                                               parameterName,
+                                                               new Integer(i+1),
+                                                               tvs[i].getDisplayName(),
+                                                               genericType.getName());
+                                               if (requireExactType)  scope.message(MessageUtil.error(msg,sLoc));      
+                                               else                               scope.message(MessageUtil.warn(msg,sLoc));   
+                                       }
+                               }
+                       }
+               }
+       }
+
+       // pr133307 - moved to verification object
+//     public boolean checkBoundsOK(IScope scope,ResolvedType genericType,boolean requireExactType) {
+//             if (boundscheckingoff) return true;
+//             TypeVariable[] tvs = genericType.getTypeVariables();
+//             TypePattern[] typeParamPatterns = typeParameters.getTypePatterns();
+//             if (typeParameters.areAllExactWithNoSubtypesAllowed()) {
+//                     for (int i = 0; i < tvs.length; i++) {
+//                             UnresolvedType ut = typeParamPatterns[i].getExactType();
+//                             boolean continueCheck = true;
+//                             // FIXME asc dont like this but ok temporary measure.  If the type parameter 
+//                             // is itself a type variable (from the generic aspect) then assume it'll be
+//                             // ok... (see pr112105)  Want to break this? Run GenericAspectK test.
+//                             if (ut.isTypeVariableReference()) {
+//                                     continueCheck = false;
+//                             }
+//                             
+//                             if (continueCheck &&    
+//                                             !tvs[i].canBeBoundTo(ut.resolve(scope.getWorld()))) {
+//                                     // issue message that type parameter does not meet specification
+//                                     String parameterName = ut.getName();
+//                                     if (ut.isTypeVariableReference()) parameterName = ((TypeVariableReference)ut).getTypeVariable().getDisplayName();
+//                                     String msg = 
+//                                             WeaverMessages.format(
+//                                                     WeaverMessages.VIOLATES_TYPE_VARIABLE_BOUNDS,
+//                                                     parameterName,
+//                                                     new Integer(i+1),
+//                                                     tvs[i].getDisplayName(),
+//                                                     genericType.getName());
+//                                     if (requireExactType)  scope.message(MessageUtil.error(msg,getSourceLocation()));       
+//                                     else                               scope.message(MessageUtil.warn(msg,getSourceLocation()));    
+//                                     return false;
+//                             }
+//                     }
+//             }
+//             return true;
+//     }
+       
+       public boolean isStar() {
+               boolean annPatternStar = annotationPattern == AnnotationTypePattern.ANY;
+               return (isNamePatternStar() && annPatternStar);
+       }
+       
+       private boolean isNamePatternStar() {
+               return namePatterns.length == 1 && namePatterns[0].isAny();
+       }
+
+       /**
+        * returns those possible matches which I match exactly the last element of
+        */
+       private String[] preMatch(String[] possibleMatches) {
+               //if (namePatterns.length != 1) return CollectionUtil.NO_STRINGS;
+               
+               List ret = new ArrayList();
+               for (int i=0, len=possibleMatches.length; i < len; i++) {
+                       char[][] names = splitNames(possibleMatches[i],true); //??? not most efficient
+                       if (namePatterns[0].matches(names[names.length-1])) {
+                               ret.add(possibleMatches[i]);
+                               continue;
+                       }
+                       if (possibleMatches[i].indexOf("$") != -1) {
+                               names = splitNames(possibleMatches[i],false); //??? not most efficient
+                               if (namePatterns[0].matches(names[names.length-1])) {
+                                       ret.add(possibleMatches[i]);
+                               }
+                       }
+               }
+               return (String[])ret.toArray(new String[ret.size()]);
+       }
+       
+    
+//     public void postRead(ResolvedType enclosingType) {
+//             this.importedPrefixes = enclosingType.getImportedPrefixes();
+//             this.knownNames = prematch(enclosingType.getImportedNames());
+//     }
+
+
+    public String toString() {
+       StringBuffer buf = new StringBuffer();
+       if (annotationPattern != AnnotationTypePattern.ANY) {
+               buf.append('(');
+               buf.append(annotationPattern.toString());
+               buf.append(' ');
+       }
+       for (int i=0, len=namePatterns.length; i < len; i++) {
+               NamePattern name = namePatterns[i];
+               if (name == null) {
+                       buf.append(".");
+               } else {
+                       if (i > 0) buf.append(".");
+                       buf.append(name.toString());
+               }
+       }
+       if (upperBound != null) {
+               buf.append(" extends ");
+               buf.append(upperBound.toString());
+       }
+       if (lowerBound != null) {
+               buf.append(" super ");
+               buf.append(lowerBound.toString());
+       }
+               if (typeParameters!=null && typeParameters.size()!=0) {
+                       buf.append("<");
+                       buf.append(typeParameters.toString());
+                       buf.append(">");
+               }
+       if (includeSubtypes) buf.append('+');
+               if (isVarArgs) buf.append("...");
+       if (annotationPattern != AnnotationTypePattern.ANY) {
+               buf.append(')');
+       }
+       return buf.toString();
+    }
+    
+    public boolean equals(Object other) {
+       if (!(other instanceof WildTypePattern)) return false;
+       WildTypePattern o = (WildTypePattern)other;
+       int len = o.namePatterns.length;
+       if (len != this.namePatterns.length) return false;
+       if (this.includeSubtypes != o.includeSubtypes) return false;
+       if (this.dim != o.dim) return false;
+       if (this.isVarArgs != o.isVarArgs) return false;
+       if (this.upperBound != null) {
+               if (o.upperBound == null) return false;
+               if (!this.upperBound.equals(o.upperBound)) return false;
+       } else {
+               if (o.upperBound != null) return false;
+       }
+       if (this.lowerBound != null) {
+               if (o.lowerBound == null) return false;
+               if (!this.lowerBound.equals(o.lowerBound)) return false;
+       } else {
+               if (o.lowerBound != null) return false;
+       }
+       if (!typeParameters.equals(o.typeParameters)) return false;
+       for (int i=0; i < len; i++) {
+               if (!o.namePatterns[i].equals(this.namePatterns[i])) return false;
+       }
+       return (o.annotationPattern.equals(this.annotationPattern));            
+       }
+
+    public int hashCode() {
+        int result = 17;
+        for (int i = 0, len = namePatterns.length; i < len; i++) {
+            result = 37*result + namePatterns[i].hashCode();
+        }
+        result = 37*result + annotationPattern.hashCode();
+        if (upperBound != null) result = 37*result + upperBound.hashCode();
+        if (lowerBound != null) result = 37*result + lowerBound.hashCode();
+        return result;
+    }
+    
+    private static final byte VERSION = 1; // rev on change
+       /**
+        * @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(TypePattern.WILD);
+               s.writeByte(VERSION);
+               s.writeShort(namePatterns.length);
+               for (int i = 0; i < namePatterns.length; i++) {
+                       namePatterns[i].write(s);
+               }
+               s.writeBoolean(includeSubtypes);
+               s.writeInt(dim);
+               s.writeBoolean(isVarArgs);
+               typeParameters.write(s);  // ! change from M2
+               //??? storing this information with every type pattern is wasteful of .class
+               //    file size. Storing it on enclosing types would be more efficient
+               FileUtil.writeStringArray(knownMatches, s);
+               FileUtil.writeStringArray(importedPrefixes, s);
+               writeLocation(s);
+               annotationPattern.write(s);
+               // generics info, new in M3
+               s.writeBoolean(isGeneric);
+               s.writeBoolean(upperBound != null);
+               if (upperBound != null) upperBound.write(s);
+               s.writeBoolean(lowerBound != null);
+               if (lowerBound != null) lowerBound.write(s);
+               s.writeInt(additionalInterfaceBounds == null ? 0 : additionalInterfaceBounds.length);
+               if (additionalInterfaceBounds != null) {
+                       for (int i = 0; i < additionalInterfaceBounds.length; i++) {
+                               additionalInterfaceBounds[i].write(s);
+                       }
+               }
+       }
+       
+       public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
+                       return readTypePattern150(s,context);
+               } else {
+                       return readTypePatternOldStyle(s,context);
+           }
+    }
+
+    public static TypePattern readTypePattern150(VersionedDataInputStream s, ISourceContext context) throws IOException {
+         byte version = s.readByte();
+         if (version > VERSION) {
+               throw new BCException("WildTypePattern was written by a more recent version of AspectJ, cannot read");
+         }
+         int len = s.readShort();
+         NamePattern[] namePatterns = new NamePattern[len];
+         for (int i=0; i < len; i++) {
+               namePatterns[i] = NamePattern.read(s);
+         }
+         boolean includeSubtypes = s.readBoolean();
+         int dim = s.readInt();
+         boolean varArg = s.readBoolean();
+         TypePatternList typeParams = TypePatternList.read(s, context);
+         WildTypePattern ret = new WildTypePattern(namePatterns, includeSubtypes, dim, varArg,typeParams);
+         ret.knownMatches = FileUtil.readStringArray(s);
+         ret.importedPrefixes = FileUtil.readStringArray(s);
+         ret.readLocation(context, s);
+         ret.setAnnotationTypePattern(AnnotationTypePattern.read(s,context));
+         // generics info, new in M3
+         ret.isGeneric = s.readBoolean();
+         if (s.readBoolean()) {
+                 ret.upperBound = TypePattern.read(s,context);
+         }
+         if (s.readBoolean()) {
+                 ret.lowerBound = TypePattern.read(s,context);
+         }
+         int numIfBounds = s.readInt();
+         if (numIfBounds > 0) {
+                 ret.additionalInterfaceBounds = new TypePattern[numIfBounds];
+                 for (int i = 0; i < numIfBounds; i++) {
+                       ret.additionalInterfaceBounds[i] = TypePattern.read(s,context);
+               }
+         }
+         return ret;
+       }
+    
+       public static TypePattern readTypePatternOldStyle(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               int len = s.readShort();
+               NamePattern[] namePatterns = new NamePattern[len];
+               for (int i=0; i < len; i++) {
+                       namePatterns[i] = NamePattern.read(s);
+               }
+               boolean includeSubtypes = s.readBoolean();
+               int dim = s.readInt();
+               WildTypePattern ret = new WildTypePattern(namePatterns, includeSubtypes, dim, false,null);
+               ret.knownMatches = FileUtil.readStringArray(s);
+               ret.importedPrefixes = FileUtil.readStringArray(s);
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java
new file mode 100644 (file)
index 0000000..ba9ce8b
--- /dev/null
@@ -0,0 +1,217 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.ShadowMunger;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.ast.Var;
+
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class WithinAnnotationPointcut extends NameBindingPointcut {
+
+       private AnnotationTypePattern annotationTypePattern;
+       private String declarationText;
+       
+       /**
+        * 
+        */
+       public WithinAnnotationPointcut(AnnotationTypePattern type) {
+               super();
+               this.annotationTypePattern = type;
+               this.pointcutKind = ATWITHIN;
+               buildDeclarationText();
+       }
+       
+       public WithinAnnotationPointcut(AnnotationTypePattern type, ShadowMunger munger) {
+           this(type);
+           this.pointcutKind = ATWITHIN;
+       }
+
+    public AnnotationTypePattern getAnnotationTypePattern() {
+        return annotationTypePattern;
+    }
+
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;
+       }
+       
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               WithinAnnotationPointcut ret = new WithinAnnotationPointcut(this.annotationTypePattern.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
+        */
+       public FuzzyBoolean fastMatch(FastMatchInfo info) {
+           return annotationTypePattern.fastMatches(info.getType());
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
+        */
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               ResolvedType enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(),true);
+               if (enclosingType.isMissing()) {
+                       shadow.getIWorld().getLint().cantFindType.signal(
+                                       new String[] {WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_WITHINPCD,
+                                                                                       shadow.getEnclosingType().getName())},
+                                   shadow.getSourceLocation(),
+                                   new ISourceLocation[]{getSourceLocation()});
+//                     IMessage msg = new Message(
+//                         WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_WITHINPCD,
+//                                                   shadow.getEnclosingType().getName()),
+//                             shadow.getSourceLocation(),true,new ISourceLocation[]{getSourceLocation()});
+//                     shadow.getIWorld().getMessageHandler().handleMessage(msg);
+               }
+               annotationTypePattern.resolve(shadow.getIWorld());
+               return annotationTypePattern.matches(enclosingType);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings)
+        */
+       protected void resolveBindings(IScope scope, Bindings bindings) {
+               if (!scope.getWorld().isInJava5Mode()) {
+                       scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.ATWITHIN_ONLY_SUPPORTED_AT_JAVA5_LEVEL),
+                                       getSourceLocation()));
+                       return;
+               }
+               annotationTypePattern = annotationTypePattern.resolveBindings(scope,bindings,true);
+               // must be either a Var, or an annotation type pattern
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedType, org.aspectj.weaver.IntMap)
+        */
+       protected Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               ExactAnnotationTypePattern newType = (ExactAnnotationTypePattern) annotationTypePattern.remapAdviceFormals(bindings);           
+               Pointcut ret = new WithinAnnotationPointcut(newType, bindings.getEnclosingAdvice());
+        ret.copyLocationFrom(this);
+        return ret;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
+        */
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
+                       BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern;
+                       UnresolvedType annotationType = btp.annotationType;
+                       Var var = shadow.getWithinAnnotationVar(annotationType);
+                       
+                       // This should not happen, we shouldn't have gotten this far 
+                       // if we weren't going to find the annotation
+                       if (var == null) 
+                               throw new BCException("Impossible! annotation=["+annotationType+
+                        "]  shadow=["+shadow+" at "+shadow.getSourceLocation()+
+                                                  "]    pointcut is at ["+getSourceLocation()+"]");
+                       
+                       state.set(btp.getFormalIndex(),var);
+               } 
+               return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
+        */
+       public List getBindingAnnotationTypePatterns() {
+               if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
+                       List l = new ArrayList();
+                       l.add(annotationTypePattern);
+                       return l;
+               } else return Collections.EMPTY_LIST;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
+        */
+       public List getBindingTypePatterns() {
+               return Collections.EMPTY_LIST;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.ATWITHIN);
+               annotationTypePattern.write(s);
+               writeLocation(s);
+       }
+
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               AnnotationTypePattern type = AnnotationTypePattern.read(s, context);
+               WithinAnnotationPointcut ret = new WithinAnnotationPointcut(type);
+               ret.readLocation(context, s);
+               return ret;
+       }
+       
+       /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(Object obj) {
+        if (!(obj instanceof WithinAnnotationPointcut)) return false;
+        WithinAnnotationPointcut other = (WithinAnnotationPointcut) obj;
+        return other.annotationTypePattern.equals(this.annotationTypePattern);
+    }
+    
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode() {
+        return 17 + 19*annotationTypePattern.hashCode();
+    }
+    
+       /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    private void buildDeclarationText() {
+               StringBuffer buf = new StringBuffer();
+               buf.append("@within(");
+               String annPatt = annotationTypePattern.toString();
+               buf.append(annPatt.startsWith("@") ? annPatt.substring(1) : annPatt);
+               buf.append(")");
+               this.declarationText = buf.toString();
+    }
+    
+    public String toString() {
+               return this.declarationText;
+    }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java
new file mode 100644 (file)
index 0000000..ed3e5f1
--- /dev/null
@@ -0,0 +1,219 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.ShadowMunger;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.ast.Var;
+
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class WithinCodeAnnotationPointcut extends NameBindingPointcut {
+
+       private ExactAnnotationTypePattern annotationTypePattern;
+    private String declarationText;
+    
+    private static final int matchedShadowKinds;
+    static {
+       int flags = Shadow.ALL_SHADOW_KINDS_BITS;
+       for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
+                       if (Shadow.SHADOW_KINDS[i].isEnclosingKind()) 
+                               flags -= Shadow.SHADOW_KINDS[i].bit;
+               }
+       matchedShadowKinds=flags;
+    }
+       
+       public WithinCodeAnnotationPointcut(ExactAnnotationTypePattern type) {
+               super();
+               this.annotationTypePattern =  type;
+               this.pointcutKind = Pointcut.ATWITHINCODE;
+               buildDeclarationText();
+       }
+
+       public WithinCodeAnnotationPointcut(ExactAnnotationTypePattern type, ShadowMunger munger) {
+               this(type);
+               this.pointcutKind = Pointcut.ATWITHINCODE;
+       }
+
+    public ExactAnnotationTypePattern getAnnotationTypePattern() {
+        return annotationTypePattern;
+    }
+
+       public int couldMatchKinds() {
+               return matchedShadowKinds;
+       }
+       
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               WithinCodeAnnotationPointcut ret = new WithinCodeAnnotationPointcut((ExactAnnotationTypePattern)this.annotationTypePattern.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
+        */
+       public FuzzyBoolean fastMatch(FastMatchInfo info) {
+               return FuzzyBoolean.MAYBE;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
+        */
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               Member member = shadow.getEnclosingCodeSignature();             
+               ResolvedMember rMember = member.resolve(shadow.getIWorld());
+
+               if (rMember == null) {
+                   if (member.getName().startsWith(NameMangler.PREFIX)) {
+                       return FuzzyBoolean.NO;
+                       }
+                       shadow.getIWorld().getLint().unresolvableMember.signal(member.toString(), getSourceLocation());
+                       return FuzzyBoolean.NO;
+               }
+
+               annotationTypePattern.resolve(shadow.getIWorld());
+               return annotationTypePattern.matches(rMember);
+       }
+       
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings)
+        */
+       protected void resolveBindings(IScope scope, Bindings bindings) {
+               if (!scope.getWorld().isInJava5Mode()) {
+                       scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.ATWITHINCODE_ONLY_SUPPORTED_AT_JAVA5_LEVEL),
+                                       getSourceLocation()));
+                       return;
+               }
+               annotationTypePattern = (ExactAnnotationTypePattern) annotationTypePattern.resolveBindings(scope,bindings,true);
+               // must be either a Var, or an annotation type pattern
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedType, org.aspectj.weaver.IntMap)
+        */
+       protected Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               ExactAnnotationTypePattern newType = (ExactAnnotationTypePattern) annotationTypePattern.remapAdviceFormals(bindings);           
+               Pointcut ret = new WithinCodeAnnotationPointcut(newType, bindings.getEnclosingAdvice());
+        ret.copyLocationFrom(this);
+        return ret;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
+        */
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               
+               if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
+                       BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern;
+                       UnresolvedType annotationType = btp.annotationType;
+                       Var var = shadow.getWithinCodeAnnotationVar(annotationType);
+       
+                       // This should not happen, we shouldn't have gotten this far 
+                       // if we weren't going to find the annotation
+                       if (var == null) 
+                               throw new BCException("Impossible! annotation=["+annotationType+
+                        "]  shadow=["+shadow+" at "+shadow.getSourceLocation()+
+                                                  "]    pointcut is at ["+getSourceLocation()+"]");
+                               
+                       state.set(btp.getFormalIndex(),var);
+               } 
+               if (matchInternal(shadow).alwaysTrue()) return Literal.TRUE;
+               else                                                              return Literal.FALSE;
+       }
+
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
+        */
+       public List getBindingAnnotationTypePatterns() {
+               if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
+                       List l = new ArrayList();
+                       l.add(annotationTypePattern);
+                       return l;
+               } else return Collections.EMPTY_LIST;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
+        */
+       public List getBindingTypePatterns() {
+               return Collections.EMPTY_LIST;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
+        */
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.ATWITHINCODE);
+               annotationTypePattern.write(s);
+               writeLocation(s);
+       }
+
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               AnnotationTypePattern type = AnnotationTypePattern.read(s, context);
+               WithinCodeAnnotationPointcut ret = new WithinCodeAnnotationPointcut((ExactAnnotationTypePattern)type);
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof WithinCodeAnnotationPointcut)) return false;
+               WithinCodeAnnotationPointcut o = (WithinCodeAnnotationPointcut)other;
+               return o.annotationTypePattern.equals(this.annotationTypePattern);
+       }
+    
+    public int hashCode() {
+        int result = 17;
+        result = 23*result + annotationTypePattern.hashCode();
+        return result;
+    }
+       
+       private void buildDeclarationText() {
+           StringBuffer buf = new StringBuffer();
+               buf.append("@withincode(");
+               String annPatt = annotationTypePattern.toString();
+               buf.append(annPatt.startsWith("@") ? annPatt.substring(1) : annPatt);
+               buf.append(")");
+               this.declarationText = buf.toString();
+       }
+       
+       public String toString() { return this.declarationText; }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WithinPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WithinPointcut.java
new file mode 100644 (file)
index 0000000..aaab835
--- /dev/null
@@ -0,0 +1,152 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+
+public class WithinPointcut extends Pointcut {
+       private TypePattern typePattern;
+       
+       public WithinPointcut(TypePattern type) {
+               this.typePattern = type;
+               this.pointcutKind = WITHIN;
+       }
+
+    public TypePattern getTypePattern() {
+        return typePattern;
+    }
+
+       private FuzzyBoolean isWithinType(ResolvedType type) {
+               while (type != null) {
+                       if (typePattern.matchesStatically(type)) {                          
+                               return FuzzyBoolean.YES;
+                       }
+                       type = type.getDeclaringType();
+               }
+               return FuzzyBoolean.NO;
+       }
+
+       public int couldMatchKinds() {
+               return Shadow.ALL_SHADOW_KINDS_BITS;
+       }
+       
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               WithinPointcut ret = new WithinPointcut(this.typePattern.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public FuzzyBoolean fastMatch(FastMatchInfo info) {
+           if (typePattern.annotationPattern instanceof AnyAnnotationTypePattern) {
+               return isWithinType(info.getType());
+           }
+           return FuzzyBoolean.MAYBE;
+       }
+          
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               ResolvedType enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(),true);
+               if (enclosingType.isMissing()) {
+                       shadow.getIWorld().getLint().cantFindType.signal(
+                                       new String[] {WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_WITHINPCD,
+                                                                                       shadow.getEnclosingType().getName())},
+                                   shadow.getSourceLocation(),
+                                   new ISourceLocation[]{getSourceLocation()});                        
+//                     IMessage msg = new Message(
+//                         WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_WITHINPCD,
+//                                                   shadow.getEnclosingType().getName()),
+//                             shadow.getSourceLocation(),true,new ISourceLocation[]{getSourceLocation()});
+//                     shadow.getIWorld().getMessageHandler().handleMessage(msg);
+               }
+               typePattern.resolve(shadow.getIWorld());
+               return isWithinType(enclosingType);
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.WITHIN);
+               typePattern.write(s);
+               writeLocation(s);
+       }
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               TypePattern type = TypePattern.read(s, context);
+               WithinPointcut ret = new WithinPointcut(type);
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               typePattern = typePattern.resolveBindings(scope, bindings, false, false);
+               
+               // look for parameterized type patterns which are not supported...
+               HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor 
+                       visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
+               typePattern.traverse(visitor, null);
+               if (visitor.wellHasItThen/*?*/()) {
+                       scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.WITHIN_PCD_DOESNT_SUPPORT_PARAMETERS),
+                               getSourceLocation()));
+               }               
+       }
+
+       public void postRead(ResolvedType enclosingType) {
+               typePattern.postRead(enclosingType);
+       }
+
+       public boolean couldEverMatchSameJoinPointsAs(WithinPointcut other) {
+               return typePattern.couldEverMatchSameTypesAs(other.typePattern);
+       }
+       
+       public boolean equals(Object other) {
+               if (!(other instanceof WithinPointcut)) return false;
+               WithinPointcut o = (WithinPointcut)other;
+               return o.typePattern.equals(this.typePattern);
+       }
+    public int hashCode() {
+        int result = 43;
+        result = 37*result + typePattern.hashCode();
+        return result;
+    }
+
+       public String toString() {
+               return "within(" + typePattern + ")";
+       }
+
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
+       }
+       
+       
+       public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType,  IntMap bindings) {
+               Pointcut ret = new WithinPointcut(typePattern);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WithincodePointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WithincodePointcut.java
new file mode 100644 (file)
index 0000000..91beeb8
--- /dev/null
@@ -0,0 +1,142 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     PARC     initial implementation 
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Test;
+
+public class WithincodePointcut extends Pointcut {
+       private SignaturePattern signature;
+    private static final int matchedShadowKinds;
+    static {
+       int flags = Shadow.ALL_SHADOW_KINDS_BITS;
+       for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
+                       if (Shadow.SHADOW_KINDS[i].isEnclosingKind()) 
+                               flags -= Shadow.SHADOW_KINDS[i].bit;
+               }
+       // these next two are needed for inlining of field initializers
+       flags|=Shadow.ConstructorExecution.bit;
+       flags|=Shadow.Initialization.bit;
+       matchedShadowKinds = flags;
+    }
+       
+       public WithincodePointcut(SignaturePattern signature) {
+               this.signature = signature;
+               this.pointcutKind = WITHINCODE;
+       }
+
+    public SignaturePattern getSignature() {
+        return signature;
+    }
+
+       public int couldMatchKinds() {
+               return matchedShadowKinds;
+       }
+       
+       public Pointcut parameterizeWith(Map typeVariableMap,World w) {
+               WithincodePointcut ret = new WithincodePointcut(signature.parameterizeWith(typeVariableMap,w));
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+       
+       public FuzzyBoolean fastMatch(FastMatchInfo type) {
+               return FuzzyBoolean.MAYBE;
+       }
+        
+       protected FuzzyBoolean matchInternal(Shadow shadow) {
+               //This will not match code in local or anonymous classes as if
+               //they were withincode of the outer signature
+               return FuzzyBoolean.fromBoolean(
+                       signature.matches(shadow.getEnclosingCodeSignature(), shadow.getIWorld(), false));
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeByte(Pointcut.WITHINCODE);
+               signature.write(s);
+               writeLocation(s);
+       }
+       
+       public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               WithincodePointcut ret = new WithincodePointcut(SignaturePattern.read(s, context));
+               ret.readLocation(context, s);
+               return ret;
+       }
+
+       public void resolveBindings(IScope scope, Bindings bindings) {
+               signature = signature.resolveBindings(scope, bindings);
+               
+               // look for inappropriate use of parameterized types and tell user...
+               HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor 
+                       visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
+               signature.getDeclaringType().traverse(visitor, null);
+               if (visitor.wellHasItThen/*?*/()) {
+                       scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.WITHINCODE_DOESNT_SUPPORT_PARAMETERIZED_DECLARING_TYPES),
+                                       getSourceLocation()));
+               }                                               
+               
+               visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
+               signature.getThrowsPattern().traverse(visitor, null);
+               if (visitor.wellHasItThen/*?*/()) {
+                       scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.NO_GENERIC_THROWABLES),
+                                       getSourceLocation()));
+               }                                       
+       }
+       
+       public void postRead(ResolvedType enclosingType) {
+               signature.postRead(enclosingType);
+       }
+
+       public boolean equals(Object other) {
+               if (!(other instanceof WithincodePointcut)) return false;
+               WithincodePointcut o = (WithincodePointcut)other;
+               return o.signature.equals(this.signature);
+       }
+    public int hashCode() {
+        int result = 43;
+        result = 37*result + signature.hashCode();
+        return result;
+    }
+
+       public String toString() {
+               return "withincode(" + signature + ")";
+       }
+
+       protected Test findResidueInternal(Shadow shadow, ExposedState state) {
+               return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
+       }
+       
+       
+       public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
+               Pointcut ret = new WithincodePointcut(signature);
+               ret.copyLocationFrom(this);
+               return ret;
+       }
+
+    public Object accept(PatternNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/AnnotationFinder.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/AnnotationFinder.java
new file mode 100644 (file)
index 0000000..7efeac9
--- /dev/null
@@ -0,0 +1,45 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import java.lang.reflect.Member;
+import java.util.Set;
+
+import org.aspectj.weaver.AnnotationAJ;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.World;
+
+/**
+ * @author colyer Used in 1.4 code to access annotations safely
+ */
+public interface AnnotationFinder {
+
+       void setClassLoader(ClassLoader annotationLoader);
+
+       void setWorld(World aWorld);
+
+       Object getAnnotation(ResolvedType annotationType, Object onObject);
+
+       Object getAnnotationFromMember(ResolvedType annotationType, Member aMember);
+
+       public AnnotationAJ getAnnotationOfType(UnresolvedType ofType,
+                       Member onMember);
+
+       public String getAnnotationDefaultValue(Member onMember);
+
+       Object getAnnotationFromClass(ResolvedType annotationType, Class aClass);
+
+       Set/* ResolvedType */getAnnotations(Member onMember);
+
+       ResolvedType[][] getParameterAnnotationTypes(Member onMember);
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/GenericSignatureInformationProvider.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/GenericSignatureInformationProvider.java
new file mode 100644 (file)
index 0000000..fce9723
--- /dev/null
@@ -0,0 +1,31 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import org.aspectj.weaver.UnresolvedType;
+
+/**
+ * This interface exists to support two different strategies for answering 
+ * generic signature related questions on Java 5 and pre-Java 5.
+ */
+public interface GenericSignatureInformationProvider {
+
+       UnresolvedType[]  getGenericParameterTypes(ReflectionBasedResolvedMemberImpl resolvedMember);
+       
+       UnresolvedType    getGenericReturnType(ReflectionBasedResolvedMemberImpl resolvedMember);
+
+       boolean isBridge(ReflectionBasedResolvedMemberImpl resolvedMember);
+       
+       boolean isVarArgs(ReflectionBasedResolvedMemberImpl resolvedMember);
+       
+       boolean isSynthetic(ReflectionBasedResolvedMemberImpl resolvedMember);
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/IReflectionWorld.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/IReflectionWorld.java
new file mode 100644 (file)
index 0000000..60d90d3
--- /dev/null
@@ -0,0 +1,19 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *    Ron Bodkin     initial implementation 
+ * ******************************************************************/
+ package org.aspectj.weaver.reflect;
+
+import org.aspectj.weaver.ResolvedType;
+
+public interface IReflectionWorld {
+       public AnnotationFinder getAnnotationFinder();
+       public ResolvedType resolve(Class aClass);
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/Java14GenericSignatureInformationProvider.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/Java14GenericSignatureInformationProvider.java
new file mode 100644 (file)
index 0000000..91b32ff
--- /dev/null
@@ -0,0 +1,60 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import org.aspectj.weaver.UnresolvedType;
+
+/**
+ * Under JDK 1.4 or lower, we can't give generic signature info...
+ */
+public class Java14GenericSignatureInformationProvider implements
+               GenericSignatureInformationProvider {
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.reflect.GenericSignatureInformationProvider#getGenericParameterTypes(org.aspectj.weaver.reflect.ReflectionBasedResolvedMemberImpl)
+        */
+       public UnresolvedType[] getGenericParameterTypes(
+                       ReflectionBasedResolvedMemberImpl resolvedMember) {
+               return resolvedMember.getParameterTypes();
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.reflect.GenericSignatureInformationProvider#getGenericReturnType(org.aspectj.weaver.reflect.ReflectionBasedResolvedMemberImpl)
+        */
+       public UnresolvedType getGenericReturnType(
+                       ReflectionBasedResolvedMemberImpl resolvedMember) {
+               return resolvedMember.getReturnType();
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.reflect.GenericSignatureInformationProvider#isBridge()
+        */
+       public boolean isBridge(ReflectionBasedResolvedMemberImpl resolvedMember) {
+               return false;
+       }
+       
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.reflect.GenericSignatureInformationProvider#isVarArgs()
+        */
+       public boolean isVarArgs(ReflectionBasedResolvedMemberImpl resolvedMember) {
+               return false;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.reflect.GenericSignatureInformationProvider#isSynthetic()
+        */
+       public boolean isSynthetic(ReflectionBasedResolvedMemberImpl resolvedMember) {
+               return false;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/JoinPointMatchImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/JoinPointMatchImpl.java
new file mode 100644 (file)
index 0000000..69a5f45
--- /dev/null
@@ -0,0 +1,53 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import org.aspectj.weaver.tools.JoinPointMatch;
+import org.aspectj.weaver.tools.PointcutParameter;
+
+/**
+ * @author colyer
+ * Implementation of JoinPointMatch for reflection based worlds.
+ */
+public class JoinPointMatchImpl implements JoinPointMatch {
+
+       public final static JoinPointMatch NO_MATCH = new JoinPointMatchImpl();
+       private final static PointcutParameter[] NO_BINDINGS = new PointcutParameter[0];
+       
+       private boolean match;
+       private PointcutParameter[] bindings;
+       
+       public JoinPointMatchImpl(PointcutParameter[] bindings) {
+               this.match = true;
+               this.bindings = bindings;
+       }
+       
+       private JoinPointMatchImpl() {
+               this.match = false;
+               this.bindings = NO_BINDINGS;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.tools.JoinPointMatch#matches()
+        */
+       public boolean matches() {
+               return match;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.tools.JoinPointMatch#getParameterBindings()
+        */
+       public PointcutParameter[] getParameterBindings() {
+               return bindings;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/PointcutParameterImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/PointcutParameterImpl.java
new file mode 100644 (file)
index 0000000..722d648
--- /dev/null
@@ -0,0 +1,43 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import org.aspectj.weaver.tools.PointcutParameter;
+
+public class PointcutParameterImpl implements PointcutParameter {
+
+       String name;
+       Class type;
+       Object binding;
+       
+       public PointcutParameterImpl(String name, Class type) {
+               this.name = name;
+               this.type = type;
+       }
+       
+       public String getName() {
+               return name;
+       }
+
+       public Class getType() {
+               return type;
+       }
+
+       public Object getBinding() {
+               return binding;
+       }
+       
+       void setBinding(Object boundValue) {
+               this.binding = boundValue;
+       }
+       
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegate.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegate.java
new file mode 100644 (file)
index 0000000..b96611a
--- /dev/null
@@ -0,0 +1,442 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.aspectj.weaver.AnnotationAJ;
+import org.aspectj.weaver.AnnotationTargetKind;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ReferenceType;
+import org.aspectj.weaver.ReferenceTypeDelegate;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.SourceContextImpl;
+import org.aspectj.weaver.TypeVariable;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.WeakClassLoaderReference;
+import org.aspectj.weaver.WeaverStateInfo;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.patterns.PerClause;
+
+/**
+ * @author colyer A delegate for a resolved type that uses runtime type information (java.lang.reflect) to answer questions. This
+ *         class uses only Java 1.4 features to answer questions. In a Java 1.5 environment use the
+ *         Java5ReflectionBasedReferenceTypeDelegate subtype.
+ */
+public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelegate {
+
+       private static final ClassLoader bootClassLoader = new URLClassLoader(new URL[0]);// ReflectionBasedReferenceTypeDelegate.class.
+       // getClassLoader();
+
+       protected Class myClass = null;
+       protected WeakClassLoaderReference classLoaderReference = null;
+       private World world;
+       private ReferenceType resolvedType;
+       private ResolvedMember[] fields = null;
+       private ResolvedMember[] methods = null;
+       private ResolvedType[] interfaces = null;
+
+       public ReflectionBasedReferenceTypeDelegate(Class forClass, ClassLoader aClassLoader, World inWorld, ReferenceType resolvedType) {
+               initialize(resolvedType, forClass, aClassLoader, inWorld);
+       }
+
+       /** for reflective construction only */
+       public ReflectionBasedReferenceTypeDelegate() {
+       }
+
+       public void initialize(ReferenceType aType, Class aClass, ClassLoader aClassLoader, World aWorld) {
+               this.myClass = aClass;
+               this.resolvedType = aType;
+               this.world = aWorld;
+               this.classLoaderReference = new WeakClassLoaderReference((aClassLoader != null) ? aClassLoader : bootClassLoader);
+       }
+
+       protected Class getBaseClass() {
+               return this.myClass;
+       }
+
+       protected World getWorld() {
+               return this.world;
+       }
+
+       public ReferenceType buildGenericType() {
+               throw new UnsupportedOperationException("Shouldn't be asking for generic type at 1.4 source level or lower");
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#addAnnotation(org.aspectj.weaver .AnnotationX)
+        */
+       public void addAnnotation(AnnotationAJ annotationX) {
+               throw new UnsupportedOperationException("Cannot add an annotation to a reflection based delegate");
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#isAspect()
+        */
+       public boolean isAspect() {
+               // we could do better than this in Java 5 by looking at the annotations
+               // on the type...
+               return false;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#isAnnotationStyleAspect()
+        */
+       public boolean isAnnotationStyleAspect() {
+               // we could do better than this in Java 5 by looking at the annotations
+               // on the type...
+               return false;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#isInterface()
+        */
+       public boolean isInterface() {
+               return this.myClass.isInterface();
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#isEnum()
+        */
+       public boolean isEnum() {
+               // cant be an enum in Java 1.4 or prior
+               return false;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#isAnnotation()
+        */
+       public boolean isAnnotation() {
+               // cant be an annotation in Java 1.4 or prior
+               return false;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#isAnnotationWithRuntimeRetention ()
+        */
+       public boolean isAnnotationWithRuntimeRetention() {
+               // cant be an annotation in Java 1.4 or prior
+               return false;
+       }
+
+       public String getRetentionPolicy() {
+               // cant be an annotation in Java 1.4 or prior
+               return null;
+       }
+
+       public boolean canAnnotationTargetType() {
+               return false;
+       }
+
+       public AnnotationTargetKind[] getAnnotationTargetKinds() {
+               return null;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#isClass()
+        */
+       public boolean isClass() {
+               return !this.myClass.isInterface() && !this.myClass.isPrimitive() && !this.myClass.isArray();
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#isGeneric()
+        */
+       public boolean isGeneric() {
+               // cant be generic in 1.4
+               return false;
+       }
+
+       public boolean isAnonymous() {
+               return false;
+       }
+
+       public boolean isNested() {
+               // FIXME this is *wrong* but isMemberClass() doesnt exist in pre-1.5...
+               // (same deal as isAnonymous above...)
+               return true;
+               // boolean member = this.myClass.isMemberClass();
+               // return member;
+       }
+
+       public ResolvedType getOuterClass() {
+               // FIXME getEnclosingClass() is Java5 ... dammit
+               // return
+               // ReflectionBasedReferenceTypeDelegateFactory.resolveTypeInWorld(
+               // myClass.getEnclosingClass(),world);
+               return null;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#isExposedToWeaver()
+        */
+       public boolean isExposedToWeaver() {
+               // reflection based types are never exposed to the weaver
+               return false;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#hasAnnotation(org.aspectj.weaver .UnresolvedType)
+        */
+       public boolean hasAnnotation(UnresolvedType ofType) {
+               // in Java 1.4 we cant have an annotation
+               return false;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getAnnotations()
+        */
+       public AnnotationAJ[] getAnnotations() {
+               // no annotations in Java 1.4
+               return AnnotationAJ.EMPTY_ARRAY;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getAnnotationTypes()
+        */
+       public ResolvedType[] getAnnotationTypes() {
+               // no annotations in Java 1.4
+               return new ResolvedType[0];
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getDeclaredFields()
+        */
+       public ResolvedMember[] getDeclaredFields() {
+               if (fields == null) {
+                       Field[] reflectFields = this.myClass.getDeclaredFields();
+                       ResolvedMember[] rFields = new ResolvedMember[reflectFields.length];
+                       for (int i = 0; i < reflectFields.length; i++) {
+                               rFields[i] = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(reflectFields[i], world);
+                       }
+                       this.fields = rFields;
+               }
+               return fields;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getDeclaredInterfaces()
+        */
+       public ResolvedType[] getDeclaredInterfaces() {
+               if (interfaces == null) {
+                       Class[] reflectInterfaces = this.myClass.getInterfaces();
+                       ResolvedType[] rInterfaces = new ResolvedType[reflectInterfaces.length];
+                       for (int i = 0; i < reflectInterfaces.length; i++) {
+                               rInterfaces[i] = ReflectionBasedReferenceTypeDelegateFactory.resolveTypeInWorld(reflectInterfaces[i], world);
+                       }
+                       this.interfaces = rInterfaces;
+               }
+               return interfaces;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getDeclaredMethods()
+        */
+       public ResolvedMember[] getDeclaredMethods() {
+               if (methods == null) {
+                       Method[] reflectMethods = this.myClass.getDeclaredMethods();
+                       Constructor[] reflectCons = this.myClass.getDeclaredConstructors();
+                       ResolvedMember[] rMethods = new ResolvedMember[reflectMethods.length + reflectCons.length];
+                       for (int i = 0; i < reflectMethods.length; i++) {
+                               rMethods[i] = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(reflectMethods[i], world);
+                       }
+                       for (int i = 0; i < reflectCons.length; i++) {
+                               rMethods[i + reflectMethods.length] = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(
+                                               reflectCons[i], world);
+                       }
+                       this.methods = rMethods;
+               }
+               return methods;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getDeclaredPointcuts()
+        */
+       public ResolvedMember[] getDeclaredPointcuts() {
+               return new ResolvedMember[0];
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getTypeVariables()
+        */
+       public TypeVariable[] getTypeVariables() {
+               // no type variables in Java 1.4
+               return new TypeVariable[0];
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getPerClause()
+        */
+       public PerClause getPerClause() {
+               // no per clause...
+               return null;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getDeclares()
+        */
+       public Collection getDeclares() {
+               // no declares
+               return Collections.EMPTY_SET;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getTypeMungers()
+        */
+       public Collection getTypeMungers() {
+               // no type mungers
+               return Collections.EMPTY_SET;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getPrivilegedAccesses()
+        */
+       public Collection getPrivilegedAccesses() {
+               // no aspect members..., not used for weaving
+               return Collections.EMPTY_SET;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getModifiers()
+        */
+       public int getModifiers() {
+               return this.myClass.getModifiers();
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getSuperclass()
+        */
+       public ResolvedType getSuperclass() {
+               if (this.myClass.getSuperclass() == null) {
+                       if (myClass == Object.class) {
+                               return null;
+                       }
+                       return world.resolve(UnresolvedType.OBJECT);
+               }
+               return ReflectionBasedReferenceTypeDelegateFactory.resolveTypeInWorld(this.myClass.getSuperclass(), world);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getWeaverState()
+        */
+       public WeaverStateInfo getWeaverState() {
+               return null;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getResolvedTypeX()
+        */
+       public ReferenceType getResolvedTypeX() {
+               return this.resolvedType;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#doesNotExposeShadowMungers()
+        */
+       public boolean doesNotExposeShadowMungers() {
+               return false;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ReferenceTypeDelegate#getDeclaredGenericSignature()
+        */
+       public String getDeclaredGenericSignature() {
+               // no generic sig in 1.4
+               return null;
+       }
+
+       public void ensureDelegateConsistent() {
+               // Nothing to do - a reflection based delegate can't become
+               // inconsistent...
+       }
+
+       public ReflectionBasedResolvedMemberImpl createResolvedMemberFor(Member aMember) {
+               return null;
+       }
+
+       public String getSourcefilename() {
+               // crappy guess..
+               return resolvedType.getName() + ".class";
+       }
+
+       public ISourceContext getSourceContext() {
+               return SourceContextImpl.UNKNOWN_SOURCE_CONTEXT;
+       }
+
+       public boolean copySourceContext() {
+               return true;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegateFactory.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegateFactory.java
new file mode 100644 (file)
index 0000000..dc315bd
--- /dev/null
@@ -0,0 +1,218 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.aspectj.util.LangUtil;
+import org.aspectj.weaver.ReferenceType;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedMemberImpl;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.World;
+
+/**
+ * @author colyer
+ * Creates the appropriate ReflectionBasedReferenceTypeDelegate according to
+ * the VM level we are running at. Uses reflection to avoid 1.5 dependencies in
+ * 1.4 and 1.3 code base.
+ */
+public class ReflectionBasedReferenceTypeDelegateFactory {
+
+       public static ReflectionBasedReferenceTypeDelegate
+               createDelegate(ReferenceType forReferenceType, World inWorld, ClassLoader usingClassLoader) {
+               try {
+                       Class c = Class.forName(forReferenceType.getName(),false,usingClassLoader);
+                       if (LangUtil.is15VMOrGreater()) {
+                               ReflectionBasedReferenceTypeDelegate rbrtd = create15Delegate(forReferenceType,c,usingClassLoader,inWorld);
+                               if (rbrtd!=null) return rbrtd; // can be null if we didn't find the class the delegate logic loads
+                       }
+                       return new ReflectionBasedReferenceTypeDelegate(c,usingClassLoader,inWorld,forReferenceType);
+               } catch (ClassNotFoundException cnfEx) {
+                       return null;
+               }
+       }
+       
+       // can return 'null' if we can't find the class
+       private static ReflectionBasedReferenceTypeDelegate create15Delegate(ReferenceType forReferenceType, Class forClass, ClassLoader usingClassLoader, World inWorld) {
+               try {
+                       Class delegateClass = Class.forName("org.aspectj.weaver.reflect.Java15ReflectionBasedReferenceTypeDelegate");
+                       ReflectionBasedReferenceTypeDelegate ret = (ReflectionBasedReferenceTypeDelegate) delegateClass.newInstance();
+                       ret.initialize(forReferenceType,forClass,usingClassLoader,inWorld);
+                       return ret;
+               } catch (ClassNotFoundException cnfEx) {
+                       throw new IllegalStateException("Attempted to create Java 1.5 reflection based delegate but org.aspectj.weaver.reflect.Java15ReflectionBasedReferenceTypeDelegate was not found on classpath");
+               } catch (InstantiationException insEx) {
+                       throw new IllegalStateException("Attempted to create Java 1.5 reflection based delegate but InstantiationException: " + insEx + " occured");
+               } catch (IllegalAccessException illAccEx) {
+                       throw new IllegalStateException("Attempted to create Java 1.5 reflection based delegate but IllegalAccessException: " + illAccEx + " occured");
+               }
+       }
+       
+       private static GenericSignatureInformationProvider createGenericSignatureProvider(World inWorld) {
+               if (LangUtil.is15VMOrGreater()) {
+                       try {
+                               Class providerClass = Class.forName("org.aspectj.weaver.reflect.Java15GenericSignatureInformationProvider");
+                               Constructor cons = providerClass.getConstructor(new Class[] {World.class});
+                               GenericSignatureInformationProvider ret = (GenericSignatureInformationProvider) cons.newInstance(new Object[] {inWorld});
+                               return ret;                             
+                       } catch (ClassNotFoundException cnfEx) {
+                               // drop through and create a 14 provider...
+                               // throw new IllegalStateException("Attempted to create Java 1.5 generic signature provider but org.aspectj.weaver.reflect.Java15GenericSignatureInformationProvider was not found on classpath");
+                       } catch (NoSuchMethodException nsmEx) {
+                               throw new IllegalStateException("Attempted to create Java 1.5 generic signature provider but: " + nsmEx + " occured");
+                       } catch (InstantiationException insEx) {
+                               throw new IllegalStateException("Attempted to create Java 1.5 generic signature provider but: " + insEx + " occured");
+                       } catch (InvocationTargetException invEx) {
+                               throw new IllegalStateException("Attempted to create Java 1.5 generic signature provider but: " + invEx + " occured");                          
+                       } catch (IllegalAccessException illAcc) {
+                               throw new IllegalStateException("Attempted to create Java 1.5 generic signature provider but: " + illAcc + " occured");                                                         
+                       }
+               }
+               return new Java14GenericSignatureInformationProvider();
+       }
+       
+       /**
+        * convert a java.lang.reflect.Member into a resolved member in the world
+        * @param reflectMember
+        * @param inWorld
+        * @return
+        */
+       public static ResolvedMember createResolvedMember(Member reflectMember, World inWorld) {
+               if (reflectMember instanceof Method) {
+                       return createResolvedMethod((Method)reflectMember,inWorld);
+               } else if (reflectMember instanceof Constructor) {
+                       return createResolvedConstructor((Constructor)reflectMember,inWorld);
+               } else {
+                       return createResolvedField((Field)reflectMember,inWorld);
+               }
+       }
+       
+       public static ResolvedMember createResolvedMethod(Method aMethod, World inWorld) {
+               ReflectionBasedResolvedMemberImpl ret = new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.METHOD,
+                               toResolvedType(aMethod.getDeclaringClass(),(IReflectionWorld)inWorld),
+                               aMethod.getModifiers(),
+                               toResolvedType(aMethod.getReturnType(),(IReflectionWorld)inWorld),
+                               aMethod.getName(),
+                               toResolvedTypeArray(aMethod.getParameterTypes(),inWorld),
+                               toResolvedTypeArray(aMethod.getExceptionTypes(),inWorld),
+                               aMethod
+                               );
+               if (inWorld instanceof IReflectionWorld) {
+                       ret.setAnnotationFinder(((IReflectionWorld)inWorld).getAnnotationFinder());
+               }
+               ret.setGenericSignatureInformationProvider(createGenericSignatureProvider(inWorld));
+               return ret;
+       }
+       
+       public static ResolvedMember createResolvedAdviceMember(Method aMethod, World inWorld) {
+               ReflectionBasedResolvedMemberImpl ret =
+                       new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.ADVICE,
+                               toResolvedType(aMethod.getDeclaringClass(),(IReflectionWorld)inWorld),
+                               aMethod.getModifiers(),
+                               toResolvedType(aMethod.getReturnType(),(IReflectionWorld)inWorld),
+                               aMethod.getName(),
+                               toResolvedTypeArray(aMethod.getParameterTypes(),inWorld),
+                               toResolvedTypeArray(aMethod.getExceptionTypes(),inWorld),
+                               aMethod
+                               );
+               if (inWorld instanceof IReflectionWorld) {
+                       ret.setAnnotationFinder(((IReflectionWorld)inWorld).getAnnotationFinder());
+               }
+               ret.setGenericSignatureInformationProvider(createGenericSignatureProvider(inWorld));
+               return ret;
+       }
+       
+       public static ResolvedMember createStaticInitMember(Class forType, World inWorld) {
+               return new ResolvedMemberImpl(org.aspectj.weaver.Member.STATIC_INITIALIZATION,
+                               toResolvedType(forType,(IReflectionWorld)inWorld),
+                               Modifier.STATIC,
+                               ResolvedType.VOID,
+                               "<clinit>",
+                               new UnresolvedType[0],
+                               new UnresolvedType[0]
+                               );
+       }
+
+       public static ResolvedMember createResolvedConstructor(Constructor aConstructor, World inWorld) {
+               ReflectionBasedResolvedMemberImpl ret =
+                  new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.CONSTRUCTOR,
+                               toResolvedType(aConstructor.getDeclaringClass(),(IReflectionWorld)inWorld),
+                               aConstructor.getModifiers(),
+                               // to return what BCEL returns, the return type for ctor is void
+                               ResolvedType.VOID,//toResolvedType(aConstructor.getDeclaringClass(),(IReflectionWorld)inWorld),
+                               "<init>",
+                               toResolvedTypeArray(aConstructor.getParameterTypes(),inWorld),
+                               toResolvedTypeArray(aConstructor.getExceptionTypes(),inWorld),
+                               aConstructor
+                               );
+               if (inWorld instanceof IReflectionWorld) {
+                       ret.setAnnotationFinder(((IReflectionWorld)inWorld).getAnnotationFinder());
+               }
+               ret.setGenericSignatureInformationProvider(createGenericSignatureProvider(inWorld));
+               return ret;
+       }
+
+       public static ResolvedMember createResolvedField(Field aField, World inWorld) {
+               ReflectionBasedResolvedMemberImpl ret =
+                       new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.FIELD,
+                               toResolvedType(aField.getDeclaringClass(),(IReflectionWorld)inWorld),
+                               aField.getModifiers(),
+                               toResolvedType(aField.getType(),(IReflectionWorld)inWorld),
+                               aField.getName(),
+                               new UnresolvedType[0],
+                               aField);
+               if (inWorld instanceof IReflectionWorld) {
+                       ret.setAnnotationFinder(((IReflectionWorld)inWorld).getAnnotationFinder());
+               }
+               ret.setGenericSignatureInformationProvider(createGenericSignatureProvider(inWorld));
+               return ret;
+       }
+       
+       public static ResolvedMember createHandlerMember(Class exceptionType, Class inType,World inWorld) {
+               return new ResolvedMemberImpl(
+                               org.aspectj.weaver.Member.HANDLER,
+                               toResolvedType(inType,(IReflectionWorld)inWorld),
+                               Modifier.STATIC,
+                               "<catch>",
+                               "(" + inWorld.resolve(exceptionType.getName()).getSignature() + ")V");
+       }
+       
+       public static ResolvedType resolveTypeInWorld(Class aClass, World aWorld) {
+//              classes that represent arrays return a class name that is the signature of the array type, ho-hum...
+               String className = aClass.getName();
+               if (aClass.isArray()) {
+                       return aWorld.resolve(UnresolvedType.forSignature(className.replace('.','/')));
+               }
+               else{
+                       return aWorld.resolve(className);
+               } 
+       }
+       
+       private static ResolvedType toResolvedType(Class aClass, IReflectionWorld aWorld) {
+               return aWorld.resolve(aClass);
+       }
+
+       private static ResolvedType[] toResolvedTypeArray(Class[] classes, World inWorld) {
+               ResolvedType[] ret = new ResolvedType[classes.length];
+               for (int i = 0; i < ret.length; i++) {
+                       ret[i] = ((IReflectionWorld)inWorld).resolve(classes[i]);
+               }
+               return ret;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedResolvedMemberImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedResolvedMemberImpl.java
new file mode 100644 (file)
index 0000000..f982f89
--- /dev/null
@@ -0,0 +1,216 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import java.lang.reflect.Member;
+import java.util.Iterator;
+
+import org.aspectj.weaver.AnnotationAJ;
+import org.aspectj.weaver.MemberKind;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedMemberImpl;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+
+/**
+ * Subtype of ResolvedMemberImpl used in reflection world. Knows how to get
+ * annotations from a java.lang.reflect.Member
+ * 
+ */
+public class ReflectionBasedResolvedMemberImpl extends ResolvedMemberImpl {
+
+       private AnnotationFinder annotationFinder = null;
+       private GenericSignatureInformationProvider gsigInfoProvider = new Java14GenericSignatureInformationProvider();
+
+       private Member reflectMember;
+
+       /**
+        * @param kind
+        * @param declaringType
+        * @param modifiers
+        * @param returnType
+        * @param name
+        * @param parameterTypes
+        */
+       public ReflectionBasedResolvedMemberImpl(MemberKind kind,
+                       UnresolvedType declaringType, int modifiers,
+                       UnresolvedType returnType, String name,
+                       UnresolvedType[] parameterTypes, Member reflectMember) {
+               super(kind, declaringType, modifiers, returnType, name, parameterTypes);
+               this.reflectMember = reflectMember;
+       }
+
+       /**
+        * @param kind
+        * @param declaringType
+        * @param modifiers
+        * @param returnType
+        * @param name
+        * @param parameterTypes
+        * @param checkedExceptions
+        */
+       public ReflectionBasedResolvedMemberImpl(MemberKind kind,
+                       UnresolvedType declaringType, int modifiers,
+                       UnresolvedType returnType, String name,
+                       UnresolvedType[] parameterTypes,
+                       UnresolvedType[] checkedExceptions, Member reflectMember) {
+               super(kind, declaringType, modifiers, returnType, name, parameterTypes,
+                               checkedExceptions);
+               this.reflectMember = reflectMember;
+       }
+
+       /**
+        * @param kind
+        * @param declaringType
+        * @param modifiers
+        * @param returnType
+        * @param name
+        * @param parameterTypes
+        * @param checkedExceptions
+        * @param backingGenericMember
+        */
+       public ReflectionBasedResolvedMemberImpl(MemberKind kind,
+                       UnresolvedType declaringType, int modifiers,
+                       UnresolvedType returnType, String name,
+                       UnresolvedType[] parameterTypes,
+                       UnresolvedType[] checkedExceptions,
+                       ResolvedMember backingGenericMember, Member reflectMember) {
+               super(kind, declaringType, modifiers, returnType, name, parameterTypes,
+                               checkedExceptions, backingGenericMember);
+               this.reflectMember = reflectMember;
+       }
+
+       /**
+        * @param kind
+        * @param declaringType
+        * @param modifiers
+        * @param name
+        * @param signature
+        */
+       public ReflectionBasedResolvedMemberImpl(MemberKind kind,
+                       UnresolvedType declaringType, int modifiers, String name,
+                       String signature, Member reflectMember) {
+               super(kind, declaringType, modifiers, name, signature);
+               this.reflectMember = reflectMember;
+       }
+
+       public Member getMember() {
+               return this.reflectMember;
+       }
+
+       // generic signature support
+
+       public void setGenericSignatureInformationProvider(
+                       GenericSignatureInformationProvider gsigProvider) {
+               this.gsigInfoProvider = gsigProvider;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ResolvedMemberImpl#getGenericParameterTypes()
+        */
+       public UnresolvedType[] getGenericParameterTypes() {
+               return this.gsigInfoProvider.getGenericParameterTypes(this);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ResolvedMemberImpl#getGenericReturnType()
+        */
+       public UnresolvedType getGenericReturnType() {
+               return this.gsigInfoProvider.getGenericReturnType(this);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ResolvedMemberImpl#isSynthetic()
+        */
+       public boolean isSynthetic() {
+               return this.gsigInfoProvider.isSynthetic(this);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ResolvedMemberImpl#isVarargsMethod()
+        */
+       public boolean isVarargsMethod() {
+               return this.gsigInfoProvider.isVarArgs(this);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.aspectj.weaver.ResolvedMemberImpl#isBridgeMethod()
+        */
+       public boolean isBridgeMethod() {
+               return this.gsigInfoProvider.isBridge(this);
+       }
+
+       // annotation support
+
+       public void setAnnotationFinder(AnnotationFinder finder) {
+               this.annotationFinder = finder;
+       }
+
+       public boolean hasAnnotation(UnresolvedType ofType) {
+               unpackAnnotations();
+               return super.hasAnnotation(ofType);
+       }
+
+       public boolean hasAnnotations() {
+               unpackAnnotations();
+               return super.hasAnnotations();
+       }
+
+       public ResolvedType[] getAnnotationTypes() {
+               unpackAnnotations();
+               return super.getAnnotationTypes();
+       }
+
+       public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
+               unpackAnnotations();
+               if (annotationFinder == null)
+                       return null;
+               for (Iterator iterator = annotationTypes.iterator(); iterator.hasNext();) {
+                       ResolvedType type = (ResolvedType) iterator.next();
+                       if (type.getSignature().equals(ofType.getSignature())) {
+                               return annotationFinder.getAnnotationOfType(ofType,
+                                               reflectMember);
+                       }
+               }
+               return null;
+       }
+
+       public String getAnnotationDefaultValue() {
+               if (annotationFinder == null)
+                       return null;
+               return annotationFinder.getAnnotationDefaultValue(reflectMember);
+       }
+
+       public ResolvedType[][] getParameterAnnotationTypes() {
+               if (parameterAnnotationTypes == null && annotationFinder != null) {
+                       parameterAnnotationTypes = annotationFinder
+                                       .getParameterAnnotationTypes(reflectMember);
+               }
+               return parameterAnnotationTypes;
+       }
+
+       private void unpackAnnotations() {
+               if (annotationTypes == null && annotationFinder != null) {
+                       annotationTypes = annotationFinder.getAnnotations(reflectMember);
+               }
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionFastMatchInfo.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionFastMatchInfo.java
new file mode 100644 (file)
index 0000000..892fdab
--- /dev/null
@@ -0,0 +1,42 @@
+/* *******************************************************************
+ * Copyright (c) 2006 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.patterns.FastMatchInfo;
+import org.aspectj.weaver.tools.MatchingContext;
+
+/**
+ * An implementation of FastMatchInfo that can also expose a 
+ * MatchingContext.
+ * 
+ * @author Adrian Colyer
+ * @since 1.5.1
+ */
+public class ReflectionFastMatchInfo extends FastMatchInfo {
+
+       private final MatchingContext context;
+
+       public ReflectionFastMatchInfo(ResolvedType type, Shadow.Kind kind, MatchingContext context) {
+               super(type,kind);
+               this.context = context;         
+       }
+
+       /**
+        * @return Returns the matching context.
+        */
+       public MatchingContext getMatchingContext() {
+               return this.context;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionShadow.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionShadow.java
new file mode 100644 (file)
index 0000000..9d98e3b
--- /dev/null
@@ -0,0 +1,345 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.Var;
+import org.aspectj.weaver.tools.MatchingContext;
+
+/**
+ * @author colyer
+ *
+ */
+public class ReflectionShadow extends Shadow {
+
+       private final World world;
+       private final ResolvedType enclosingType;
+       private final ResolvedMember enclosingMember;
+       private final MatchingContext matchContext;
+       private Var thisVar = null;
+       private Var targetVar = null;
+       private Var[] argsVars = null;
+       private Var atThisVar = null;
+       private Var atTargetVar = null;
+       private Map atArgsVars = new HashMap();
+       private Map withinAnnotationVar = new HashMap();
+       private Map withinCodeAnnotationVar = new HashMap();
+       private Map annotationVar = new HashMap();
+       private AnnotationFinder annotationFinder;
+       
+       public static Shadow makeExecutionShadow(World inWorld, java.lang.reflect.Member forMethod, MatchingContext withContext) {
+               Kind kind = (forMethod instanceof Method) ? Shadow.MethodExecution : Shadow.ConstructorExecution;
+               Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(forMethod, inWorld);
+               ResolvedType enclosingType = signature.getDeclaringType().resolve(inWorld);
+               return new ReflectionShadow(inWorld,kind,signature,null,enclosingType,null,withContext);
+       }
+       
+       public static Shadow makeAdviceExecutionShadow(World inWorld, java.lang.reflect.Method forMethod, MatchingContext withContext) {
+               Kind kind = Shadow.AdviceExecution;
+               Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedAdviceMember(forMethod, inWorld);
+               ResolvedType enclosingType = signature.getDeclaringType().resolve(inWorld);
+               return new ReflectionShadow(inWorld,kind,signature,null,enclosingType,null,withContext);
+       }
+       
+       public static Shadow makeCallShadow(World inWorld, java.lang.reflect.Member aMember, java.lang.reflect.Member withinCode, MatchingContext withContext) {
+               Shadow enclosingShadow = makeExecutionShadow(inWorld,withinCode,withContext);
+               Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(aMember, inWorld);
+               ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(withinCode, inWorld);
+               ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld);
+               Kind kind = aMember instanceof Method ? Shadow.MethodCall : Shadow.ConstructorCall;
+               return new ReflectionShadow(inWorld,kind,signature,enclosingShadow,enclosingType,enclosingMember,withContext);
+       }
+
+       public static Shadow makeCallShadow(World inWorld, java.lang.reflect.Member aMember, Class thisClass, MatchingContext withContext) {
+               Shadow enclosingShadow = makeStaticInitializationShadow(inWorld, thisClass,withContext);
+               Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(aMember, inWorld);
+               ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createStaticInitMember(thisClass, inWorld);
+               ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld);
+               Kind kind = aMember instanceof Method ? Shadow.MethodCall : Shadow.ConstructorCall;
+               return new ReflectionShadow(inWorld,kind,signature,enclosingShadow,enclosingType,enclosingMember,withContext);
+       }
+
+       public static Shadow makeStaticInitializationShadow(World inWorld, Class forType, MatchingContext withContext) {
+               Member signature = ReflectionBasedReferenceTypeDelegateFactory.createStaticInitMember(forType, inWorld);
+               ResolvedType enclosingType = signature.getDeclaringType().resolve(inWorld);
+               Kind kind = Shadow.StaticInitialization;
+               return new ReflectionShadow(inWorld,kind,signature,null,enclosingType,null,withContext);
+       }
+       
+       public static Shadow makePreInitializationShadow(World inWorld, Constructor forConstructor, MatchingContext withContext) {
+               Kind kind =  Shadow.PreInitialization;
+               Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(forConstructor, inWorld);
+               ResolvedType enclosingType = signature.getDeclaringType().resolve(inWorld);
+               return new ReflectionShadow(inWorld,kind,signature,null,enclosingType,null,withContext);
+       }
+       
+       public static Shadow makeInitializationShadow(World inWorld, Constructor forConstructor, MatchingContext withContext) {
+               Kind kind =  Shadow.Initialization;
+               Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(forConstructor, inWorld);
+               ResolvedType enclosingType = signature.getDeclaringType().resolve(inWorld);
+               return new ReflectionShadow(inWorld,kind,signature,null,enclosingType,null,withContext);
+       }
+       
+       public static Shadow makeHandlerShadow(World inWorld, Class exceptionType, Class withinType, MatchingContext withContext) {
+               Kind kind = Shadow.ExceptionHandler;
+               Shadow enclosingShadow = makeStaticInitializationShadow(inWorld, withinType,withContext);
+               Member signature = ReflectionBasedReferenceTypeDelegateFactory.createHandlerMember(exceptionType, withinType, inWorld);
+               ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createStaticInitMember(withinType, inWorld);
+               ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld);
+               return new ReflectionShadow(inWorld,kind,signature,enclosingShadow,enclosingType,enclosingMember,withContext);  
+       }
+       
+       public static Shadow makeHandlerShadow(World inWorld, Class exceptionType, java.lang.reflect.Member withinCode, MatchingContext withContext) {
+               Kind kind = Shadow.ExceptionHandler;
+               Shadow enclosingShadow = makeExecutionShadow(inWorld, withinCode,withContext);
+               Member signature = ReflectionBasedReferenceTypeDelegateFactory.createHandlerMember(exceptionType, withinCode.getDeclaringClass(), inWorld);
+               ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(withinCode, inWorld);
+               ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld);
+               return new ReflectionShadow(inWorld,kind,signature,enclosingShadow,enclosingType,enclosingMember,withContext);  
+       }
+       
+       public static Shadow makeFieldGetShadow(World inWorld, Field forField, Class callerType, MatchingContext withContext) {
+               Shadow enclosingShadow = makeStaticInitializationShadow(inWorld, callerType,withContext);
+               Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedField(forField, inWorld);
+               ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createStaticInitMember(callerType, inWorld);
+               ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld);
+               Kind kind = Shadow.FieldGet;
+               return new ReflectionShadow(inWorld,kind,signature,enclosingShadow,enclosingType,enclosingMember,withContext);
+       }
+       
+       public static Shadow makeFieldGetShadow(World inWorld, Field forField, java.lang.reflect.Member inMember, MatchingContext withContext) {
+               Shadow enclosingShadow = makeExecutionShadow(inWorld,inMember,withContext);
+               Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedField(forField, inWorld);
+               ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(inMember, inWorld);
+               ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld);
+               Kind kind = Shadow.FieldGet;
+               return new ReflectionShadow(inWorld,kind,signature,enclosingShadow,enclosingType,enclosingMember,withContext);
+       }
+
+       public static Shadow makeFieldSetShadow(World inWorld, Field forField, Class callerType, MatchingContext withContext) {
+               Shadow enclosingShadow = makeStaticInitializationShadow(inWorld, callerType, withContext);
+               Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedField(forField, inWorld);
+               ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createStaticInitMember(callerType, inWorld);
+               ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld);
+               Kind kind = Shadow.FieldSet;
+               return new ReflectionShadow(inWorld,kind,signature,enclosingShadow,enclosingType,enclosingMember,withContext);
+       }
+
+       public static Shadow makeFieldSetShadow(World inWorld, Field forField, java.lang.reflect.Member inMember, MatchingContext withContext) {
+               Shadow enclosingShadow = makeExecutionShadow(inWorld,inMember,withContext);
+               Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedField(forField, inWorld);
+               ResolvedMember enclosingMember = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(inMember, inWorld);
+               ResolvedType enclosingType = enclosingMember.getDeclaringType().resolve(inWorld);
+               Kind kind = Shadow.FieldSet;
+               return new ReflectionShadow(inWorld,kind,signature,enclosingShadow,enclosingType,enclosingMember,withContext);
+       }
+
+       public ReflectionShadow(World world, Kind kind, Member signature, Shadow enclosingShadow, ResolvedType enclosingType, ResolvedMember enclosingMember, MatchingContext withContext) {
+               super(kind,signature,enclosingShadow);
+               this.world = world;
+               this.enclosingType = enclosingType;
+               this.enclosingMember = enclosingMember;
+               this.matchContext = withContext;
+               if (world instanceof IReflectionWorld) {
+                       this.annotationFinder = ((IReflectionWorld)world).getAnnotationFinder();
+               }
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getIWorld()
+        */
+       public World getIWorld() {
+               return world;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getThisVar()
+        */
+       public Var getThisVar() {
+               if (thisVar == null && hasThis()) {
+                       thisVar = ReflectionVar.createThisVar(getThisType().resolve(world),this.annotationFinder);
+               }
+               return thisVar;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getTargetVar()
+        */
+       public Var getTargetVar() {
+               if (targetVar == null && hasTarget()) {
+                       targetVar = ReflectionVar.createTargetVar(getThisType().resolve(world),this.annotationFinder);
+               }
+               return targetVar;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getEnclosingType()
+        */
+       public UnresolvedType getEnclosingType() {
+               return this.enclosingType;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getArgVar(int)
+        */
+       public Var getArgVar(int i) {
+               if (argsVars == null) {
+                       this.argsVars = new Var[this.getArgCount()];
+                       for (int j = 0; j < this.argsVars.length; j++) {
+                               this.argsVars[j] = ReflectionVar.createArgsVar(getArgType(j).resolve(world), j,this.annotationFinder);
+                       }
+               }
+               if (i < argsVars.length) {
+                       return argsVars[i];
+               } else {
+                       return null;
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getThisJoinPointVar()
+        */
+       public Var getThisJoinPointVar() {
+               // TODO Auto-generated method stub
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getThisJoinPointStaticPartVar()
+        */
+       public Var getThisJoinPointStaticPartVar() {
+               // TODO Auto-generated method stub
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getThisEnclosingJoinPointStaticPartVar()
+        */
+       public Var getThisEnclosingJoinPointStaticPartVar() {
+               // TODO Auto-generated method stub
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getKindedAnnotationVar(org.aspectj.weaver.UnresolvedType)
+        */
+       public Var getKindedAnnotationVar(UnresolvedType forAnnotationType) {
+               ResolvedType annType = forAnnotationType.resolve(world);
+               if (annotationVar.get(annType) == null) {
+                       Var v = ReflectionVar.createAtAnnotationVar(annType,this.annotationFinder);
+                       annotationVar.put(annType,v);
+               }
+               return (Var) annotationVar.get(annType);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getWithinAnnotationVar(org.aspectj.weaver.UnresolvedType)
+        */
+       public Var getWithinAnnotationVar(UnresolvedType forAnnotationType) {
+               ResolvedType annType = forAnnotationType.resolve(world);
+               if (withinAnnotationVar.get(annType) == null) {
+                       Var v = ReflectionVar.createWithinAnnotationVar(annType,this.annotationFinder);
+                       withinAnnotationVar.put(annType,v);
+               }
+               return (Var) withinAnnotationVar.get(annType);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getWithinCodeAnnotationVar(org.aspectj.weaver.UnresolvedType)
+        */
+       public Var getWithinCodeAnnotationVar(UnresolvedType forAnnotationType) {
+               ResolvedType annType = forAnnotationType.resolve(world);
+               if (withinCodeAnnotationVar.get(annType) == null) {
+                       Var v = ReflectionVar.createWithinCodeAnnotationVar(annType,this.annotationFinder);
+                       withinCodeAnnotationVar.put(annType,v);
+               }
+               return (Var) withinCodeAnnotationVar.get(annType);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getThisAnnotationVar(org.aspectj.weaver.UnresolvedType)
+        */
+       public Var getThisAnnotationVar(UnresolvedType forAnnotationType) {
+               if (atThisVar == null) {
+                       atThisVar = ReflectionVar.createThisAnnotationVar(forAnnotationType.resolve(world),this.annotationFinder);
+               }
+               return atThisVar;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getTargetAnnotationVar(org.aspectj.weaver.UnresolvedType)
+        */
+       public Var getTargetAnnotationVar(UnresolvedType forAnnotationType) {
+               if (atTargetVar == null) {
+                       atTargetVar = ReflectionVar.createTargetAnnotationVar(forAnnotationType.resolve(world),this.annotationFinder);
+               }
+               return atTargetVar;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getArgAnnotationVar(int, org.aspectj.weaver.UnresolvedType)
+        */
+       public Var getArgAnnotationVar(int i, UnresolvedType forAnnotationType) {
+               ResolvedType annType = forAnnotationType.resolve(world);
+               if (atArgsVars.get(annType) == null) {
+                       Var[] vars = new Var[getArgCount()];
+                       atArgsVars.put(annType,vars);
+               }
+               Var[] vars = (Var[]) atArgsVars.get(annType);
+               if (i > (vars.length - 1) ) return null;
+               if (vars[i] == null) {
+                       vars[i] = ReflectionVar.createArgsAnnotationVar(annType, i,this.annotationFinder);
+               }
+               return vars[i];
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getEnclosingCodeSignature()
+        */
+       public Member getEnclosingCodeSignature() {
+               // XXX this code is copied from BcelShadow with one minor change...
+       if (getKind().isEnclosingKind()) {
+               return getSignature();
+       } else if (getKind() == Shadow.PreInitialization) {
+          // PreInit doesn't enclose code but its signature
+          // is correctly the signature of the ctor.
+         return getSignature();
+       } else if (enclosingShadow == null) {
+               return this.enclosingMember;
+       } else {
+               return enclosingShadow.getSignature();
+       }
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.Shadow#getSourceLocation()
+        */
+       public ISourceLocation getSourceLocation() {
+               return null;
+       }
+
+       public MatchingContext getMatchingContext() {
+               return this.matchContext;
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionVar.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionVar.java
new file mode 100644 (file)
index 0000000..59876a7
--- /dev/null
@@ -0,0 +1,169 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import java.lang.reflect.Member;
+
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.ast.Var;
+
+/**
+ * A variable at a reflection shadow, used by the residual tests.
+ */
+public final class ReflectionVar extends Var {
+
+       static final int THIS_VAR = 0;
+       static final int TARGET_VAR = 1;
+       static final int ARGS_VAR = 2;
+       static final int AT_THIS_VAR = 3;
+       static final int AT_TARGET_VAR = 4;
+       static final int AT_ARGS_VAR = 5;
+       static final int AT_WITHIN_VAR = 6;
+       static final int AT_WITHINCODE_VAR = 7;
+       static final int AT_ANNOTATION_VAR = 8;
+       
+       private AnnotationFinder annotationFinder = null;
+       
+//     static {
+//             try {
+//                     Class java15AnnotationFinder = Class.forName("org.aspectj.weaver.reflect.Java15AnnotationFinder");
+//                     annotationFinder = (AnnotationFinder) java15AnnotationFinder.newInstance();
+//             } catch(ClassNotFoundException ex) {
+//                     // must be on 1.4 or earlier
+//             } catch(IllegalAccessException ex) {
+//                     // not so good
+//                     throw new RuntimeException("AspectJ internal error",ex);
+//             } catch(InstantiationException ex) {
+//                     throw new RuntimeException("AspectJ internal error",ex);
+//             }
+//     }
+       
+       private int argsIndex = 0;
+       private int varType;
+       
+       public static ReflectionVar createThisVar(ResolvedType type,AnnotationFinder finder) {
+               ReflectionVar ret = new ReflectionVar(type,finder);
+               ret.varType = THIS_VAR;
+               return ret;
+       }
+       
+       public static ReflectionVar createTargetVar(ResolvedType type, AnnotationFinder finder) {
+               ReflectionVar ret = new ReflectionVar(type,finder);
+               ret.varType = TARGET_VAR;
+               return ret;             
+       }
+       
+       public static ReflectionVar createArgsVar(ResolvedType type, int index, AnnotationFinder finder) {
+               ReflectionVar ret = new ReflectionVar(type,finder);
+               ret.varType = ARGS_VAR;
+               ret.argsIndex = index;
+               return ret;             
+       }
+       
+       public static ReflectionVar createThisAnnotationVar(ResolvedType type, AnnotationFinder finder) {
+               ReflectionVar ret = new ReflectionVar(type,finder);
+               ret.varType = AT_THIS_VAR;
+               return ret;
+       }
+       
+       public static ReflectionVar createTargetAnnotationVar(ResolvedType type, AnnotationFinder finder) {
+               ReflectionVar ret = new ReflectionVar(type,finder);
+               ret.varType = AT_TARGET_VAR;
+               return ret;             
+       }
+       
+       public static ReflectionVar createArgsAnnotationVar(ResolvedType type, int index, AnnotationFinder finder) {
+               ReflectionVar ret = new ReflectionVar(type,finder);
+               ret.varType = AT_ARGS_VAR;
+               ret.argsIndex = index;
+               return ret;             
+       }
+       
+       public static ReflectionVar createWithinAnnotationVar(ResolvedType annType, AnnotationFinder finder) {
+               ReflectionVar ret = new ReflectionVar(annType,finder);
+               ret.varType = AT_WITHIN_VAR;
+               return ret;
+       }
+       
+       public static ReflectionVar createWithinCodeAnnotationVar(ResolvedType annType, AnnotationFinder finder) {
+               ReflectionVar ret = new ReflectionVar(annType,finder);
+               ret.varType = AT_WITHINCODE_VAR;
+               return ret;
+       }
+
+       public static ReflectionVar createAtAnnotationVar(ResolvedType annType, AnnotationFinder finder) {
+               ReflectionVar ret = new ReflectionVar(annType,finder);
+               ret.varType = AT_ANNOTATION_VAR;
+               return ret;
+       }
+
+       private ReflectionVar(ResolvedType type,AnnotationFinder finder) {
+               super(type);
+               this.annotationFinder = finder;
+       }
+                       
+       
+       public Object getBindingAtJoinPoint(Object thisObject, Object targetObject, Object[] args) {
+               return getBindingAtJoinPoint(thisObject,targetObject,args,null,null,null);
+       }
+       /**
+        * At a join point with the given this, target, and args, return the object to which this
+        * var is bound.
+        * @param thisObject
+        * @param targetObject
+        * @param args
+        * @return
+        */
+       public Object getBindingAtJoinPoint(
+                       Object thisObject, 
+                       Object targetObject, 
+                       Object[] args,
+                       Member subject,
+                       Member withinCode,
+                       Class withinType) {
+               switch( this.varType) {
+               case THIS_VAR: return thisObject;
+               case TARGET_VAR: return targetObject;
+               case ARGS_VAR:
+                       if (this.argsIndex > (args.length - 1)) return null;
+                       return args[argsIndex];
+               case AT_THIS_VAR:
+                       if (annotationFinder != null) {
+                               return annotationFinder.getAnnotation(getType(), thisObject);
+                       } else return null;
+               case AT_TARGET_VAR:
+                       if (annotationFinder != null) {
+                               return annotationFinder.getAnnotation(getType(), targetObject);
+                       } else return null;
+               case AT_ARGS_VAR:
+                       if (this.argsIndex > (args.length - 1)) return null;
+                       if (annotationFinder != null) {
+                               return annotationFinder.getAnnotation(getType(), args[argsIndex]);
+                       } else return null;
+               case AT_WITHIN_VAR:
+                       if (annotationFinder != null) {
+                               return annotationFinder.getAnnotationFromClass(getType(), withinType);
+                       } else return null;
+               case AT_WITHINCODE_VAR:
+                       if (annotationFinder != null) {
+                               return annotationFinder.getAnnotationFromMember(getType(), withinCode);
+                       } else return null;
+               case AT_ANNOTATION_VAR:
+                       if (annotationFinder != null) {
+                               return annotationFinder.getAnnotationFromMember(getType(), subject);
+                       } else return null;
+               }
+                       
+               return null;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionWorld.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionWorld.java
new file mode 100644 (file)
index 0000000..4f14303
--- /dev/null
@@ -0,0 +1,140 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import org.aspectj.bridge.AbortException;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.util.LangUtil;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.IWeavingSupport;
+import org.aspectj.weaver.ReferenceType;
+import org.aspectj.weaver.ReferenceTypeDelegate;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.WeakClassLoaderReference;
+import org.aspectj.weaver.World;
+
+/**
+ * A ReflectionWorld is used solely for purposes of type resolution based on the runtime classpath (java.lang.reflect). It does not
+ * support weaving operations (creation of mungers etc..).
+ * 
+ */
+public class ReflectionWorld extends World implements IReflectionWorld {
+
+       private WeakClassLoaderReference classLoaderReference;
+       private AnnotationFinder annotationFinder;
+
+       private ReflectionWorld() {
+               // super();
+               // this.setMessageHandler(new ExceptionBasedMessageHandler());
+               // setBehaveInJava5Way(LangUtil.is15VMOrGreater());
+               // this.classLoaderReference = new
+               // WeakClassLoaderReference(ReflectionWorld.class.getClassLoader());
+               // this.annotationFinder =
+               // makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(),
+               // this);
+       }
+
+       public ReflectionWorld(ClassLoader aClassLoader) {
+               super();
+               this.setMessageHandler(new ExceptionBasedMessageHandler());
+               setBehaveInJava5Way(LangUtil.is15VMOrGreater());
+               classLoaderReference = new WeakClassLoaderReference(aClassLoader);
+               annotationFinder = makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(), this);
+       }
+
+       public static AnnotationFinder makeAnnotationFinderIfAny(ClassLoader loader, World world) {
+               AnnotationFinder annotationFinder = null;
+               try {
+                       if (LangUtil.is15VMOrGreater()) {
+                               Class java15AnnotationFinder = Class.forName("org.aspectj.weaver.reflect.Java15AnnotationFinder");
+                               annotationFinder = (AnnotationFinder) java15AnnotationFinder.newInstance();
+                               annotationFinder.setClassLoader(loader);
+                               annotationFinder.setWorld(world);
+                       }
+               } catch (ClassNotFoundException ex) {
+                       // must be on 1.4 or earlier
+               } catch (IllegalAccessException ex) {
+                       // not so good
+                       throw new BCException("AspectJ internal error", ex);
+               } catch (InstantiationException ex) {
+                       throw new BCException("AspectJ internal error", ex);
+               }
+               return annotationFinder;
+       }
+
+       public ClassLoader getClassLoader() {
+               return classLoaderReference.getClassLoader();
+       }
+
+       public AnnotationFinder getAnnotationFinder() {
+               return annotationFinder;
+       }
+
+       public ResolvedType resolve(Class aClass) {
+               return resolve(this, aClass);
+       }
+
+       public static ResolvedType resolve(World world, Class aClass) {
+               // classes that represent arrays return a class name that is the
+               // signature of the array type, ho-hum...
+               String className = aClass.getName();
+               if (aClass.isArray()) {
+                       return world.resolve(UnresolvedType.forSignature(className.replace('.', '/')));
+               } else {
+                       return world.resolve(className);
+               }
+       }
+
+       protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) {
+               return ReflectionBasedReferenceTypeDelegateFactory.createDelegate(ty, this, classLoaderReference.getClassLoader());
+       }
+
+       public static class ReflectionWorldException extends RuntimeException {
+
+               private static final long serialVersionUID = -3432261918302793005L;
+
+               public ReflectionWorldException(String message) {
+                       super(message);
+               }
+       }
+
+       private static class ExceptionBasedMessageHandler implements IMessageHandler {
+
+               public boolean handleMessage(IMessage message) throws AbortException {
+                       throw new ReflectionWorldException(message.toString());
+               }
+
+               public boolean isIgnoring(org.aspectj.bridge.IMessage.Kind kind) {
+                       if (kind == IMessage.INFO) {
+                               return true;
+                       } else {
+                               return false;
+                       }
+               }
+
+               public void dontIgnore(org.aspectj.bridge.IMessage.Kind kind) {
+                       // empty
+               }
+
+               public void ignore(org.aspectj.bridge.IMessage.Kind kind) {
+                       // empty
+               }
+
+       }
+
+       public IWeavingSupport getWeavingSupport() {
+               return null;
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ShadowMatchImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ShadowMatchImpl.java
new file mode 100644 (file)
index 0000000..88309b8
--- /dev/null
@@ -0,0 +1,189 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import java.lang.reflect.Member;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.ast.And;
+import org.aspectj.weaver.ast.Call;
+import org.aspectj.weaver.ast.FieldGetCall;
+import org.aspectj.weaver.ast.HasAnnotation;
+import org.aspectj.weaver.ast.ITestVisitor;
+import org.aspectj.weaver.ast.Instanceof;
+import org.aspectj.weaver.ast.Literal;
+import org.aspectj.weaver.ast.Not;
+import org.aspectj.weaver.ast.Or;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.ast.Var;
+import org.aspectj.weaver.internal.tools.MatchingContextBasedTest;
+import org.aspectj.weaver.patterns.ExposedState;
+import org.aspectj.weaver.tools.DefaultMatchingContext;
+import org.aspectj.weaver.tools.JoinPointMatch;
+import org.aspectj.weaver.tools.MatchingContext;
+import org.aspectj.weaver.tools.PointcutParameter;
+import org.aspectj.weaver.tools.ShadowMatch;
+
+/**
+ * @author colyer
+ * Implementation of ShadowMatch for reflection based worlds.
+ */
+public class ShadowMatchImpl implements ShadowMatch {
+
+       private FuzzyBoolean match;
+       private ExposedState state;
+       private Test residualTest;
+       private PointcutParameter[] params;
+       private Member withinCode;
+       private Member subject;
+       private Class withinType;
+       private MatchingContext matchContext = new DefaultMatchingContext();
+       
+       public ShadowMatchImpl(FuzzyBoolean match, Test test, ExposedState state, PointcutParameter[] params) {
+               this.match = match;
+               this.residualTest = test;
+               this.state = state;
+               this.params = params;
+       }
+       
+       public void setWithinCode(Member aMember) { this.withinCode = aMember; }
+       public void setSubject(Member aMember) { this.subject = aMember; }
+       public void setWithinType(Class aClass) { this.withinType = aClass; }
+               
+       public boolean alwaysMatches() {
+               return match.alwaysTrue();
+       }
+
+       public boolean maybeMatches() {
+               return match.maybeTrue();
+       }
+
+       public boolean neverMatches() {
+               return match.alwaysFalse();
+       }
+
+       public JoinPointMatch matchesJoinPoint(Object thisObject, Object targetObject, Object[] args) {
+               if (neverMatches()) return JoinPointMatchImpl.NO_MATCH;
+               if (new RuntimeTestEvaluator(residualTest,thisObject,targetObject,args,this.matchContext).matches()) {
+                       return new JoinPointMatchImpl(getPointcutParameters(thisObject,targetObject,args));
+               } else {
+                       return JoinPointMatchImpl.NO_MATCH;
+               }
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.tools.ShadowMatch#setMatchingContext(org.aspectj.weaver.tools.MatchingContext)
+        */
+       public void setMatchingContext(MatchingContext aMatchContext) {
+               this.matchContext = aMatchContext;
+       }
+
+       private PointcutParameter[] getPointcutParameters(Object thisObject, Object targetObject, Object[] args) {
+               Var[] vars = state.vars;
+               PointcutParameterImpl[] bindings = new PointcutParameterImpl[params.length];
+               for (int i = 0; i < bindings.length; i++) {
+                       bindings[i] = new PointcutParameterImpl(params[i].getName(),params[i].getType());
+                       bindings[i].setBinding(((ReflectionVar)vars[i]).getBindingAtJoinPoint(thisObject, targetObject, args,subject,withinCode,withinType));
+               }
+               return bindings;
+       }
+
+       private static class RuntimeTestEvaluator implements ITestVisitor {
+
+               private boolean matches = true;
+               private final Test test;
+               private final Object thisObject;
+               private final Object targetObject;
+               private final Object[] args;
+               private final MatchingContext matchContext;
+               
+               
+               public RuntimeTestEvaluator(Test aTest,Object thisObject, Object targetObject, Object[] args, MatchingContext context) {
+                       this.test = aTest;
+                       this.thisObject = thisObject;
+                       this.targetObject = targetObject;
+                       this.args = args;
+                       this.matchContext = context;
+               }
+               
+               public boolean matches() {
+                       test.accept(this);
+                       return matches;
+               }
+               
+               public void visit(And e) {
+                       boolean leftMatches = 
+                               new RuntimeTestEvaluator(e.getLeft(),thisObject,targetObject,args,matchContext).matches();
+                       if (!leftMatches) {
+                               matches = false;
+                       } else {
+                               matches = new RuntimeTestEvaluator(e.getRight(),thisObject,targetObject,args,matchContext).matches();
+                       }                       
+               }
+
+               public void visit(Instanceof i) {
+                       ReflectionVar v = (ReflectionVar) i.getVar();
+                       Object value = v.getBindingAtJoinPoint(thisObject,targetObject, args);
+                       World world = v.getType().getWorld();
+                       ResolvedType desiredType = i.getType().resolve(world);
+                       ResolvedType actualType = world.resolve(value.getClass().getName());
+                       matches = desiredType.isAssignableFrom(actualType);
+               }
+               
+               public void visit(MatchingContextBasedTest matchingContextTest) {
+                       matches = matchingContextTest.matches(this.matchContext);
+               }
+
+               public void visit(Not not) {
+                       matches = ! new RuntimeTestEvaluator(not.getBody(),thisObject,targetObject,args,matchContext).matches();
+               }
+
+               public void visit(Or or) {
+                       boolean leftMatches = 
+                               new RuntimeTestEvaluator(or.getLeft(),thisObject,targetObject,args,matchContext).matches();
+                       if (leftMatches) {
+                               matches = true;
+                       } else {
+                               matches = new RuntimeTestEvaluator(or.getRight(),thisObject,targetObject,args,matchContext).matches();
+                       }
+               }
+
+               public void visit(Literal literal) {
+                       if (literal == Literal.FALSE) {
+                               matches = false;
+                       } else {
+                               matches = true;
+                       }
+               }
+
+               public void visit(Call call) {
+                       throw new UnsupportedOperationException("Can't evaluate call test at runtime");
+               }
+
+               public void visit(FieldGetCall fieldGetCall) {
+                       throw new UnsupportedOperationException("Can't evaluate fieldGetCall test at runtime");                 
+               }
+
+               public void visit(HasAnnotation hasAnnotation) {
+                       ReflectionVar v = (ReflectionVar) hasAnnotation.getVar();
+                       Object value = v.getBindingAtJoinPoint(thisObject,targetObject, args);
+                       World world = v.getType().getWorld();
+                       ResolvedType actualVarType = world.resolve(value.getClass().getName());
+                       ResolvedType requiredAnnotationType = hasAnnotation.getAnnotationType().resolve(world);
+                       matches = actualVarType.hasAnnotation(requiredAnnotationType);
+               }
+               
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/AbstractTrace.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/AbstractTrace.java
new file mode 100644 (file)
index 0000000..2ec0aa3
--- /dev/null
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Matthew Webster - initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.tools;
+
+import java.io.File;
+import java.lang.reflect.Array;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Date;
+
+import org.aspectj.bridge.IMessage.Kind;
+
+public abstract class AbstractTrace implements Trace {
+
+       protected Class tracedClass;
+
+       private static SimpleDateFormat timeFormat;
+       
+       protected AbstractTrace (Class clazz) {
+               this.tracedClass = clazz;
+       }
+       
+       public abstract void enter (String methodName, Object thiz, Object[] args);
+       
+       public abstract void enter(String methodName, Object thiz);
+
+       public abstract void exit(String methodName, Object ret);
+
+       public abstract void exit(String methodName, Throwable th);
+
+       /*
+        * Convenience methods
+        */
+       public void enter (String methodName) {
+               enter(methodName,null,null);
+       }
+
+       public void enter (String methodName, Object thiz, Object arg) {
+               enter(methodName,thiz,new Object[] { arg });
+       }
+
+       public void enter (String methodName, Object thiz, boolean z) {
+               enter(methodName,thiz,new Boolean(z));
+       }
+
+       public void exit (String methodName, boolean b) {
+               exit(methodName,new Boolean(b));
+       }
+
+       public void exit (String methodName, int i) {
+               exit(methodName,new Integer(i));
+       }
+
+       public void event (String methodName, Object thiz, Object arg) {
+               event(methodName,thiz,new Object[] { arg });
+       }
+
+       public void warn(String message) {
+               warn(message,null);
+       }
+
+       public void error(String message) {
+               error(message,null);
+       }
+
+       public void fatal (String message) {
+               fatal(message,null);
+       }
+       
+       /*
+        * Formatting
+        */
+       protected String formatMessage(String kind, String className, String methodName, Object thiz, Object[] args) {
+               StringBuffer message = new StringBuffer();
+               Date now = new Date();
+               message.append(formatDate(now)).append(" ");
+               message.append(Thread.currentThread().getName()).append(" ");
+               message.append(kind).append(" ");
+               message.append(className);
+               message.append(".").append(methodName);
+               if (thiz != null) message.append(" ").append(formatObj(thiz));
+               if (args != null) message.append(" ").append(formatArgs(args));
+               return message.toString();
+       }
+       
+       protected String formatMessage(String kind, String text, Throwable th) {
+               StringBuffer message = new StringBuffer();
+               Date now = new Date();
+               message.append(formatDate(now)).append(" ");
+               message.append(Thread.currentThread().getName()).append(" ");
+               message.append(kind).append(" ");
+               message.append(text);
+               if (th != null) message.append(" ").append(formatObj(th));
+               return message.toString();
+       }
+       
+       private static String formatDate (Date date) {
+               if (timeFormat == null) {
+                       timeFormat = new SimpleDateFormat("HH:mm:ss.SSS");
+               }
+               
+               return timeFormat.format(date);
+       }
+
+       /**
+        * Format objects safely avoiding toString which can cause recursion,
+        * NullPointerExceptions or highly verbose results.
+        *  
+        * @param obj parameter to be formatted
+        * @return the formated parameter
+        */
+       protected Object formatObj(Object obj) {
+               
+               /* These classes have a safe implementation of toString() */
+               if (obj == null
+                               || obj instanceof String
+                           || obj instanceof Number
+                           || obj instanceof Boolean
+                           || obj instanceof Exception
+                           || obj instanceof Character
+                           || obj instanceof Class
+                           || obj instanceof File
+                           || obj instanceof StringBuffer
+                           || obj instanceof URL
+                           || obj instanceof Kind
+                   ) return obj;
+               else if (obj.getClass().isArray()) {
+                       return formatArray(obj);
+               }
+               else if (obj instanceof Collection) {
+                       return formatCollection((Collection)obj);
+               }
+               else try {
+                       
+                       /* Classes can provide an alternative implementation of toString() */
+                       if (obj instanceof Traceable) {
+                               Traceable t = (Traceable)obj;
+                               return t.toTraceString();
+                       }
+                       
+                       /* Use classname@hashcode */
+                       else return obj.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(obj));
+               
+               /* Object.hashCode() can be override and may thow an exception */       
+               } catch (Exception ex) {
+                       return obj.getClass().getName() + "@FFFFFFFF";
+               }
+       }
+       
+       protected String formatArray (Object obj) {
+               return obj.getClass().getComponentType().getName() + "[" + Array.getLength(obj) + "]"; 
+       }
+       
+       protected String formatCollection (Collection c) {
+               return c.getClass().getName() + "(" + c.size() + ")"; 
+       }
+
+       /** 
+        * Format arguments into a comma separated list
+        * 
+        * @param names array of argument names
+        * @param args array of arguments
+        * @return the formated list
+        */
+       protected String formatArgs(Object[] args) {
+               StringBuffer sb = new StringBuffer();
+               
+               for (int i = 0; i < args.length; i++) {
+                       sb.append(formatObj(args[i]));
+                       if (i < args.length-1) sb.append(", ");
+               }
+               
+               return sb.toString();
+       }
+       
+       protected Object[] formatObjects(Object[] args) {
+               for (int i = 0; i < args.length; i++) {
+                       args[i] = formatObj(args[i]);
+               }
+               
+               return args;
+       }
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/CommonsTrace.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/CommonsTrace.java
new file mode 100644 (file)
index 0000000..25562c0
--- /dev/null
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Matthew Webster - initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.tools;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class CommonsTrace extends AbstractTrace {
+
+       private Log log;
+       private String className;
+       
+       public CommonsTrace (Class clazz) {
+               super(clazz);
+               this.log = LogFactory.getLog(clazz);
+               this.className = tracedClass.getName();
+       }
+       
+       public void enter(String methodName, Object thiz, Object[] args) {
+               if (log.isDebugEnabled()) {
+                       log.debug(formatMessage(">", className, methodName, thiz, args));
+               }
+       }
+
+       public void enter(String methodName, Object thiz) {
+               if (log.isDebugEnabled()) {
+                       log.debug(formatMessage(">", className, methodName, thiz, null));
+               }
+       }
+
+       public void exit(String methodName, Object ret) {
+               if (log.isDebugEnabled()) {
+                       log.debug(formatMessage("<", className, methodName, ret, null));
+               }
+       }
+
+       public void exit(String methodName, Throwable th) {
+               if (log.isDebugEnabled()) {
+                       log.debug(formatMessage("<", className, methodName, th, null));
+               }
+       }
+
+       public void exit(String methodName) {
+               if (log.isDebugEnabled()) {
+                       log.debug(formatMessage("<", className, methodName, null, null));
+               }
+       }
+
+       public void event(String methodName, Object thiz, Object[] args) {
+               if (log.isDebugEnabled()) {
+                       log.debug(formatMessage("-", className, methodName, thiz, args));
+               }
+       }
+
+       public void event(String methodName) {
+               if (log.isDebugEnabled()) {
+                       log.debug(formatMessage("-", className, methodName, null, null));
+               }
+       }
+
+       public boolean isTraceEnabled () {
+               return log.isDebugEnabled();
+       }
+
+       public void setTraceEnabled (boolean b) {
+       }
+
+       public void debug (String message) {
+               if (log.isDebugEnabled()) {
+                       log.debug(message);
+               }
+       }
+
+       public void info(String message) {
+               if (log.isInfoEnabled()) {
+                       log.info(message);
+               }
+       }
+
+       public void warn (String message, Throwable th) {
+               if (log.isWarnEnabled()) {
+                       log.warn(message,th);
+               }
+       }
+
+       public void error (String message, Throwable th) {
+               if (log.isErrorEnabled()) {
+                       log.error(message,th);
+               }
+       }
+
+       public void fatal (String message, Throwable th) {
+               if (log.isFatalEnabled()) {
+                       log.fatal(message,th);
+               }
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/CommonsTraceFactory.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/CommonsTraceFactory.java
new file mode 100644 (file)
index 0000000..8f9f91e
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Matthew Webster - initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.tools;
+
+import org.apache.commons.logging.LogFactory;
+//OPTIMIZE move out of main weaver for now?
+public class CommonsTraceFactory extends TraceFactory {
+
+       private LogFactory logFactory = LogFactory.getFactory();
+       
+       public Trace getTrace(Class clazz) {
+               return new CommonsTrace(clazz);
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/ContextBasedMatcher.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/ContextBasedMatcher.java
new file mode 100644 (file)
index 0000000..fc247dc
--- /dev/null
@@ -0,0 +1,65 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.tools;
+
+/**
+ * Pointcut expression interface for pointcut
+ * expressions returned by a
+ * PointcutDesignatorHandler. Provides an additional
+ * matching method for matching based on context
+ * information over and above that normally used
+ * by AspectJ.
+ * 
+ * @see MatchingContext
+ *
+ */
+public interface ContextBasedMatcher {
+
+       /**
+        * return true iff this matcher could ever match
+        * a join point in the given type
+        * @deprecated use couldMatchJoinPointsInType(Class,MatchingContext) instead
+        */
+       boolean couldMatchJoinPointsInType(Class aClass);
+       
+       /**
+        * return true iff this matcher could ever match
+        * a join point in the given type, may also use any
+        * match context information available
+        * @since 1.5.1
+        */
+       boolean couldMatchJoinPointsInType(Class aClass, MatchingContext matchContext);
+       
+       /**
+        * return true if matchesStatically can ever return
+        * FuzzyBoolean.MAYBE (necessitating a per-join point test
+        * to determine matching at a given join point).
+        */
+       boolean mayNeedDynamicTest();
+
+       /**
+        * Return FuzzyBoolean.YES if a join point with the given
+        * matching context is always matched. 
+        * Return FuzzyBoolean.NO if a join point with the given
+        * matching context is never matched.
+        * Return FuzzyBoolean.MAYBE if a match cannot be determined
+        * statically (whilst generating a ShadowMatch), and must
+        * be determined on a per-join point basis. 
+        */
+       FuzzyBoolean matchesStatically(MatchingContext matchContext);
+
+       /**
+        * Called during processing of ShadowMatch.matchesJoinPoint
+        * when matchesStatically returned FuzzyBoolean.MAYBE. 
+        */
+       boolean matchesDynamically(MatchingContext matchContext);
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/DefaultMatchingContext.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/DefaultMatchingContext.java
new file mode 100644 (file)
index 0000000..fa47a87
--- /dev/null
@@ -0,0 +1,56 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.tools;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Default implementation of MatchingContext, backed
+ * by a Map.
+ */
+public class DefaultMatchingContext implements MatchingContext {
+
+       private Map contextMap = new HashMap();
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.tools.MatchingContext#hasContextParameter(java.lang.String)
+        */
+       public boolean hasContextBinding(String contextParameterName) {
+               return this.contextMap.containsKey(contextParameterName);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.tools.MatchingContext#get(java.lang.String)
+        */
+       public Object getBinding(String contextParameterName) {
+               return this.contextMap.get(contextParameterName);
+       }
+       
+       /**
+        * Add a context binding with the given name and value
+        * @param name
+        * @param value
+        */
+       public void addContextBinding(String name, Object value) {
+               this.contextMap.put(name, value);
+       }
+       
+       /**
+        * Remove the context binding with the given name
+        * @param name
+        */
+       public void removeContextBinding(String name) {
+               this.contextMap.remove(name);
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/DefaultTrace.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/DefaultTrace.java
new file mode 100644 (file)
index 0000000..ad95bbb
--- /dev/null
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Matthew Webster - initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.tools;
+
+import java.io.PrintStream;
+
+
+public class DefaultTrace extends AbstractTrace {
+       
+       private boolean traceEnabled = false;
+       private PrintStream print = System.err;
+       
+       public DefaultTrace (Class clazz) {
+               super(clazz);
+       }
+       
+       public boolean isTraceEnabled () {
+               return traceEnabled;
+       }
+       
+       public void setTraceEnabled (boolean b) {
+               traceEnabled = b;
+       }
+       
+       public void enter (String methodName, Object thiz, Object[] args) {
+               if (traceEnabled) {
+                       println(formatMessage(">",tracedClass.getName(),methodName,thiz, args));
+               }
+       }
+       
+       public void enter (String methodName, Object thiz) {
+               if (traceEnabled) {
+                       println(formatMessage(">",tracedClass.getName(),methodName,thiz, null));
+               }
+       }
+
+       public void exit (String methodName, Object ret) {
+               if (traceEnabled) {
+                       println(formatMessage("<",tracedClass.getName(),methodName,ret, null));
+               }
+       }
+
+       public void exit (String methodName) {
+               if (traceEnabled) {
+                       println(formatMessage("<",tracedClass.getName(),methodName,null, null));
+               }
+       }
+
+       public void exit(String methodName, Throwable th) {
+               if (traceEnabled) {
+                       println(formatMessage("<",tracedClass.getName(),methodName,th, null));
+               }
+       }
+       
+       public void event(String methodName, Object thiz, Object[] args) {
+               if (traceEnabled) {
+                       println(formatMessage("-",tracedClass.getName(),methodName,thiz, args));
+               }
+       }
+
+       public void event(String methodName) {
+               if (traceEnabled) {
+                       println(formatMessage("-",tracedClass.getName(),methodName,null,null));
+               }
+       }
+
+       public void debug (String message) {
+               println(formatMessage("?",message,null));
+       }
+
+       public void info(String message) {
+               println(formatMessage("I",message,null));
+       }
+
+       public void warn (String message, Throwable th) {
+               println(formatMessage("W",message,th));
+               if (th != null) th.printStackTrace();
+       }
+
+
+       public void error (String message, Throwable th) {
+               println(formatMessage("E",message,th));
+               if (th != null) th.printStackTrace();
+       }
+
+       public void fatal (String message, Throwable th) {
+               println(formatMessage("X",message,th));
+               if (th != null) th.printStackTrace();
+       }
+
+       /**
+        * Template method that allows choice of destination for output
+        * 
+        * @param s message to be traced
+        */
+       protected void println (String s) {
+               print.println(s);
+       }
+
+       public void setPrintStream (PrintStream printStream) {
+               this.print = printStream;
+       }
+
+//     private static boolean isTracingEnabled = getBoolean("org.aspectj.weaver.tools.tracing",false);
+//
+//     private static boolean getBoolean (String name, boolean def) {
+//             String defaultValue = String.valueOf(def);
+//             String value = System.getProperty(name,defaultValue);
+//             return Boolean.valueOf(value).booleanValue();
+//     }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/DefaultTraceFactory.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/DefaultTraceFactory.java
new file mode 100644 (file)
index 0000000..c786058
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Matthew Webster - initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.tools;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class DefaultTraceFactory extends TraceFactory {
+
+       public final static String ENABLED_PROPERTY = "org.aspectj.tracing.enabled";
+       public final static String FILE_PROPERTY = "org.aspectj.tracing.file";
+
+    private boolean tracingEnabled = getBoolean(ENABLED_PROPERTY,false);
+    private PrintStream print;
+
+    public DefaultTraceFactory() {
+               String filename = System.getProperty(FILE_PROPERTY);
+               if (filename != null) {
+                       File file = new File(filename);
+                       try {
+                               print = new PrintStream(new FileOutputStream(file));
+                       }
+                       catch (IOException ex) {
+                       if (debug) ex.printStackTrace();
+                       }
+               }
+       }
+    
+    public boolean isEnabled() {
+               return tracingEnabled;
+       }
+    
+    public Trace getTrace (Class clazz) {
+       DefaultTrace trace = new DefaultTrace(clazz);
+       trace.setTraceEnabled(tracingEnabled);
+       if (print != null) trace.setPrintStream(print);
+       return trace;
+    }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/FuzzyBoolean.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/FuzzyBoolean.java
new file mode 100644 (file)
index 0000000..77079c0
--- /dev/null
@@ -0,0 +1,37 @@
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ *               2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.tools;
+
+/** 
+ * This class implements a boolean that includes a "maybe"
+ */
+public final class FuzzyBoolean {
+       
+       // Note :- this implementation is not safe under serialization / deserialization
+       private String name;
+       
+    public static final FuzzyBoolean YES   = new FuzzyBoolean("YES");
+    public static final FuzzyBoolean NO    = new FuzzyBoolean("NO");
+    public static final FuzzyBoolean MAYBE = new FuzzyBoolean("MAYBE");
+
+    
+       public static final FuzzyBoolean fromBoolean(boolean b) {
+               return b ? YES : NO;
+       }
+
+       public String toString() { return name; }
+       
+       private FuzzyBoolean() {}
+       
+       private FuzzyBoolean(String n) { this.name = n; }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/GeneratedClassHandler.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/GeneratedClassHandler.java
new file mode 100644 (file)
index 0000000..43be823
--- /dev/null
@@ -0,0 +1,29 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Matthew Webster, Adrian Colyer, 
+ *     Martin Lippert     initial implementation 
+ * ******************************************************************/
+package org.aspectj.weaver.tools;
+
+/**
+ * Interface implemented by weaving class loaders to allow classes generated by
+ * the weaving process to be defined.
+ */
+public interface GeneratedClassHandler {
+       
+       /**
+        * Accept class generated by WeavingAdaptor. The class loader should store
+        * the class definition in its local cache until called upon to load it.
+        * @param name class name
+        * @param bytes class definition
+        */
+       public void acceptClass (String name, byte[] bytes);
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/ISupportsMessageContext.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/ISupportsMessageContext.java
new file mode 100644 (file)
index 0000000..69e55b1
--- /dev/null
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Matthew Webster - initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.tools;
+
+import org.aspectj.bridge.IMessageContext;
+
+public interface ISupportsMessageContext {
+
+       public void setMessageContext (IMessageContext messageContext);
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/JoinPointMatch.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/JoinPointMatch.java
new file mode 100644 (file)
index 0000000..588b3c0
--- /dev/null
@@ -0,0 +1,31 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.tools;
+
+/**
+ * @author colyer
+ * The result of asking a ShadowMatch to match at a given join point.
+ */
+public interface JoinPointMatch {
+
+       /**
+        * True if the pointcut expression has matched at this join point, and false 
+        * otherwise
+        */
+       boolean matches();
+       
+       /**
+        * Get the parameter bindings at the matched join point. 
+        * If the join point was not matched an empty array is returned.
+        */
+       PointcutParameter[] getParameterBindings();
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/MatchingContext.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/MatchingContext.java
new file mode 100644 (file)
index 0000000..e668a30
--- /dev/null
@@ -0,0 +1,43 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.tools;
+
+/**
+ * When extending AspectJ's pointcut parsing and
+ * matching with custom PointcutDesignatorHandlers,
+ * it may be necessary to match based on context information
+ * at a join point not exposed simply by java.lang.reflect
+ * member information or argument values. The matching context
+ * interface provides an extension point for the specification
+ * of additional shadow and join point context that can be
+ * taken into account during the matching process.
+ * 
+ *  @see DefaultMatchingContext
+ */
+public interface MatchingContext {
+
+       /**
+        * Returns true iff this matching context has a defined
+        * binding for the given context parameter.
+        * @param contextParameterName
+        */
+       boolean hasContextBinding(String contextParameterName);
+       
+       /**
+        * returns the binding associated with the 
+        * given context parameter name (or null if
+        * there is no such context). 
+        * @param contextParameterName
+        * @return
+        */
+       Object getBinding(String contextParameterName);
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutDesignatorHandler.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutDesignatorHandler.java
new file mode 100644 (file)
index 0000000..63f4a81
--- /dev/null
@@ -0,0 +1,49 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.tools;
+
+
+/**
+ * The PointcutDesignator interface allows extension of the
+ * AspectJ pointcut language so that third-party tools integrating
+ * with AspectJ can add easily their own custom 
+ * domain-specific designators and have them interoperate seamlessly
+ * with the standard AspectJ designators.
+ *
+ * A pointcut designator can only be used for matching, not for
+ * binding.
+ */
+public interface PointcutDesignatorHandler {
+
+       /**
+        * The name of this pointcut designator. For example,
+        * if this designator handles a "bean(&lt;NamePattern&gt;)
+        * format designator, this method would return "bean".
+        * @return
+        */
+       String getDesignatorName() ;
+       
+       /**
+        * Parse the given expression string
+        * and return a ContextBasedMatcher that can be used
+        * for matching.
+        * @param expression  the body of the pointcut expression. 
+        * For example, given the expression "bean(*DAO)" the parse
+        * method will be called with the argument "*DAO".
+        * @return a pointcut expression that can be used for
+        * matching.
+        * @throws IllegalArgumentException if the expression
+        * is ill-formed.
+        */
+       ContextBasedMatcher parse(String expression);
+       
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutExpression.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutExpression.java
new file mode 100644 (file)
index 0000000..6b598a5
--- /dev/null
@@ -0,0 +1,204 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+
+package org.aspectj.weaver.tools;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+
+/**
+ * Represents an AspectJ pointcut expression and provides convenience methods to determine
+ * whether or not the pointcut matches join points specified in terms of the
+ * java.lang.reflect interfaces.
+ */
+public interface PointcutExpression {
+
+       /**
+        * Set the matching context to be used for
+        * subsequent calls to match.
+        * @see MatchingContext
+        */
+       void setMatchingContext(MatchingContext aMatchContext);
+       
+       /**
+        * Determine whether or not this pointcut could ever match a join point in the given class.
+        * @param aClass  the candidate class
+        * @return true iff this pointcut <i>may</i> match a join point within(aClass), and false otherwise 
+        */
+       boolean couldMatchJoinPointsInType(Class aClass);
+       
+       /**
+        * Returns true iff this pointcut contains any expression that might necessitate a dynamic test
+        * at some join point (e.g. args)
+        */
+       boolean mayNeedDynamicTest();
+       
+       /**
+        * Determine whether or not this pointcut matches the execution of a given method.
+        * @param aMethod the method being executed
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or never
+        * matches join points representing the execution of the method. 
+        */
+       ShadowMatch matchesMethodExecution(Method aMethod );
+       
+       /**
+        * Determine whether or not this pointcut matches the execution of a given constructor.
+        * @param aConstructor the constructor being executed
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or never
+        * matches join points representing the execution of the constructor. 
+        */
+       ShadowMatch matchesConstructorExecution(Constructor aConstructor);
+
+       /**
+        * Determine whether or not this pointcut matches the static initialization
+        * of the given class.
+        * @param aClass the class being statically initialized
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or never
+        * matchs join points representing the static initialization of the given type
+        */
+       ShadowMatch matchesStaticInitialization(Class aClass);
+       
+       /**
+        * Determine whether or not this pointcut matches the execution of a given piece of advice.
+        * @param anAdviceMethod a method representing the advice being executed
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or never
+        * matches join points representing the execution of the advice. 
+        */             
+       ShadowMatch matchesAdviceExecution(Method anAdviceMethod);
+       
+       /**
+        * Determine whether or not this pointcut matches the initialization of an
+        * object initiated by a call to the given constructor.
+        * @param aConstructor the constructor initiating the initialization
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or never
+        * matches join points representing initialization via the given constructor. 
+        */     
+       ShadowMatch matchesInitialization(Constructor aConstructor);
+       
+       /**
+        * Determine whether or not this pointcut matches the pre-initialization of an
+        * object initiated by a call to the given constructor.
+        * @param aConstructor the constructor initiating the initialization
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or never
+        * matches join points representing pre-initialization via the given constructor. 
+        */     
+       ShadowMatch matchesPreInitialization(Constructor aConstructor);
+       
+       /**
+        * Determine whether or not this pointcut matches a method call to the given method, made during 
+        * the execution of the given method or constructor.
+        * @param aMethod the method being called
+        * @param withinCode the Method or Constructor from within which the call is made
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or never
+        * matches join points representing a call to this method during the execution of the given member.
+        */
+       ShadowMatch matchesMethodCall(Method aMethod, Member withinCode);
+
+       /**
+        * Determine whether or not this pointcut matches a method call to the given method, made outside 
+        * of the scope of any method or constructor, but within the callerType (for example, during
+        * static initialization of the type).
+        * @param aMethod the method being called
+        * @param callerType the declared type of the caller
+        * @param receiverType the declared type of the recipient of the call
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or never
+        * matches join points representing a call to this method during the execution of the given member.
+        */
+       ShadowMatch matchesMethodCall(Method aMethod, Class callerType);
+
+       /**
+        * Determine whether or not this pointcut matches a method call to the given constructor, made during 
+        * the execution of the given method or constructor.
+        * @param aConstructor the constructor being called
+        * @param withinCode the Method or Constructor from within which the call is made
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or never
+        * matches join points representing a call to this constructor during the execution of the given member.
+        */
+       ShadowMatch matchesConstructorCall(Constructor aConstructor, Member withinCode);
+
+       /**
+        * Determine whether or not this pointcut matches a method call to the given constructor, made outside 
+        * of the scope of any method or constructor, but within the callerType.
+        * @param aConstructor the cosstructor being called
+        * @param callerType the declared type of the caller
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or never
+        * matches join points representing a call to this constructor during the execution of the given member.
+        */
+       ShadowMatch matchesConstructorCall(Constructor aConstructor, Class callerType);
+
+       /**
+        * Determine whether or not this pointcut matches the execution of a given exception
+        * handler within the given method or constructor
+        * @param exceptionType the static type of the exception being handled
+        * @param withinCode the method or constructor in which the catch block is declared
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or 
+        * never matches join points representing the handling of the given exception
+        */     
+       ShadowMatch matchesHandler(Class exceptionType, Member withinCode);
+       
+       /**
+        * Determine whether or not this pointcut matches the execution of a given exception
+        * handler outside of the scope of any method or constructor, but within the handling type.
+        * @param exceptionType the static type of the exception being handled
+        * @param handlingType the type in which the handler block is executing
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or 
+        * never matches join points representing the handling of the given exception
+        */     
+       ShadowMatch matchesHandler(Class exceptionType, Class handlingType);
+       
+       /**
+        * Determine whether or not this pointcut matches a set of the given field from within the given
+        * method or constructor.
+        * @param aField the field being updated
+        * @param withinCode the Method or Constructor owning the call site
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or
+        * never matches field set join points for the given field and call site.
+        */
+       ShadowMatch matchesFieldSet(Field aField, Member withinCode);
+       
+       /**
+        * Determine whether or not this pointcut matches a set of the given field outside of the
+        * scope of any method or constructor, but within the given type (for example, during
+        * static initialization).
+        * @param aField the field being updated
+        * @param withinType the type owning the call site
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or
+        * never matches field set join points for the given field and call site.
+        */
+       ShadowMatch matchesFieldSet(Field aField, Class withinType);
+       
+       /**
+        * Determine whether or not this pointcut matches a get of the given field from within the given
+        * method or constructor.
+        * @param aField the field being updated
+        * @param withinCode the Method or Constructor owning the call site
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or
+        * never matches field get join points for the given field and call site.
+        */
+       ShadowMatch matchesFieldGet(Field aField, Member withinCode);
+
+       /**
+        * Determine whether or not this pointcut matches a get of the given field outside of the
+        * scope of any method or constructor, but within the given type (for example, during
+        * static initialization).
+        * @param aField the field being accessed
+        * @param withinType the type owning the call site
+        * @return a ShadowMatch indicating whether the pointcut always, sometimes, or
+        * never matches field get join points for the given field and call site.
+        */
+       ShadowMatch matchesFieldGet(Field aField, Class withinType);
+       
+       /**
+        * Return a string representation of this pointcut expression.
+        */
+       String getPointcutExpression();
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutParameter.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutParameter.java
new file mode 100644 (file)
index 0000000..a0eaa10
--- /dev/null
@@ -0,0 +1,36 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.tools;
+
+/**
+ * @author colyer
+ * Represents a parameter in a pointcut expression.
+ * For example pointcut pc(String s) : .....; has a PointcutParameter of
+ * name "s" and type String.
+ */
+public interface PointcutParameter {
+
+       /**
+        * The name of this parameter
+        */
+       String getName();
+       
+       /**
+        * The type of the parameter
+        */
+       Class getType();
+       
+       /**
+        * At a matched join point, the parameter binding. 
+        */
+       Object getBinding();
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutParser.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutParser.java
new file mode 100644 (file)
index 0000000..13841b7
--- /dev/null
@@ -0,0 +1,546 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.weaver.tools;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.SourceLocation;
+import org.aspectj.weaver.BindingScope;
+import org.aspectj.weaver.IHasPosition;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.WeakClassLoaderReference;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.internal.tools.PointcutExpressionImpl;
+import org.aspectj.weaver.internal.tools.TypePatternMatcherImpl;
+import org.aspectj.weaver.patterns.AndPointcut;
+import org.aspectj.weaver.patterns.CflowPointcut;
+import org.aspectj.weaver.patterns.FormalBinding;
+import org.aspectj.weaver.patterns.IScope;
+import org.aspectj.weaver.patterns.KindedPointcut;
+import org.aspectj.weaver.patterns.NotPointcut;
+import org.aspectj.weaver.patterns.OrPointcut;
+import org.aspectj.weaver.patterns.ParserException;
+import org.aspectj.weaver.patterns.PatternParser;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.patterns.SimpleScope;
+import org.aspectj.weaver.patterns.ThisOrTargetAnnotationPointcut;
+import org.aspectj.weaver.patterns.ThisOrTargetPointcut;
+import org.aspectj.weaver.patterns.TypePattern;
+import org.aspectj.weaver.reflect.PointcutParameterImpl;
+import org.aspectj.weaver.reflect.ReflectionWorld;
+
+/**
+ * A PointcutParser can be used to build PointcutExpressions for a user-defined subset of AspectJ's pointcut language
+ */
+public class PointcutParser {
+
+       private ReflectionWorld world;
+       private WeakClassLoaderReference classLoaderReference;
+       private final Set supportedPrimitives;
+       private final Set pointcutDesignators = new HashSet();
+
+       /**
+        * @return a Set containing every PointcutPrimitive except if, cflow, and cflowbelow (useful for passing to PointcutParser
+        *         constructor).
+        */
+       public static Set getAllSupportedPointcutPrimitives() {
+               Set primitives = new HashSet();
+               primitives.add(PointcutPrimitive.ADVICE_EXECUTION);
+               primitives.add(PointcutPrimitive.ARGS);
+               primitives.add(PointcutPrimitive.CALL);
+               primitives.add(PointcutPrimitive.EXECUTION);
+               primitives.add(PointcutPrimitive.GET);
+               primitives.add(PointcutPrimitive.HANDLER);
+               primitives.add(PointcutPrimitive.INITIALIZATION);
+               primitives.add(PointcutPrimitive.PRE_INITIALIZATION);
+               primitives.add(PointcutPrimitive.SET);
+               primitives.add(PointcutPrimitive.STATIC_INITIALIZATION);
+               primitives.add(PointcutPrimitive.TARGET);
+               primitives.add(PointcutPrimitive.THIS);
+               primitives.add(PointcutPrimitive.WITHIN);
+               primitives.add(PointcutPrimitive.WITHIN_CODE);
+               primitives.add(PointcutPrimitive.AT_ANNOTATION);
+               primitives.add(PointcutPrimitive.AT_THIS);
+               primitives.add(PointcutPrimitive.AT_TARGET);
+               primitives.add(PointcutPrimitive.AT_ARGS);
+               primitives.add(PointcutPrimitive.AT_WITHIN);
+               primitives.add(PointcutPrimitive.AT_WITHINCODE);
+               primitives.add(PointcutPrimitive.REFERENCE);
+
+               return primitives;
+       }
+
+       /**
+        * Returns a pointcut parser that can parse the full AspectJ pointcut language with the following exceptions:
+        * <ul>
+        * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+        * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
+        * <li>The pointcut expression must be anonymous with no formals allowed.
+        * </ul>
+        * <p>
+        * When resolving types in pointcut expressions, the context classloader is used to find types.
+        * </p>
+        */
+       public static PointcutParser getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution() {
+               PointcutParser p = new PointcutParser();
+               p.setClassLoader(Thread.currentThread().getContextClassLoader());
+               return p;
+       }
+
+       /**
+        * Returns a pointcut parser that can parse pointcut expressions built from a user-defined subset of AspectJ's supported
+        * pointcut primitives. The following restrictions apply:
+        * <ul>
+        * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+        * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
+        * <li>The pointcut expression must be anonymous with no formals allowed.
+        * </ul>
+        * <p>
+        * When resolving types in pointcut expressions, the context classloader is used to find types.
+        * </p>
+        * 
+        * @param supportedPointcutKinds a set of PointcutPrimitives this parser should support
+        * @throws UnsupportedOperationException if the set contains if, cflow, or cflow below
+        */
+       public static PointcutParser getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(
+                       Set supportedPointcutKinds) {
+               PointcutParser p = new PointcutParser(supportedPointcutKinds);
+               p.setClassLoader(Thread.currentThread().getContextClassLoader());
+               return p;
+       }
+
+       /**
+        * Returns a pointcut parser that can parse the full AspectJ pointcut language with the following exceptions:
+        * <ul>
+        * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+        * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
+        * <li>The pointcut expression must be anonymous with no formals allowed.
+        * </ul>
+        * <p>
+        * When resolving types in pointcut expressions, the given classloader is used to find types.
+        * </p>
+        */
+       public static PointcutParser getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(
+                       ClassLoader classLoader) {
+               PointcutParser p = new PointcutParser();
+               p.setClassLoader(classLoader);
+               return p;
+       }
+
+       /**
+        * Returns a pointcut parser that can parse pointcut expressions built from a user-defined subset of AspectJ's supported
+        * pointcut primitives. The following restrictions apply:
+        * <ul>
+        * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+        * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
+        * <li>The pointcut expression must be anonymous with no formals allowed.
+        * </ul>
+        * <p>
+        * When resolving types in pointcut expressions, the given classloader is used to find types.
+        * </p>
+        * 
+        * @param supportedPointcutKinds a set of PointcutPrimitives this parser should support
+        * @throws UnsupportedOperationException if the set contains if, cflow, or cflow below
+        */
+       public static PointcutParser getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
+                       Set supportedPointcutKinds, ClassLoader classLoader) {
+               PointcutParser p = new PointcutParser(supportedPointcutKinds);
+               p.setClassLoader(classLoader);
+               return p;
+       }
+
+       /**
+        * Create a pointcut parser that can parse the full AspectJ pointcut language with the following exceptions:
+        * <ul>
+        * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+        * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
+        * <li>The pointcut expression must be anonymous with no formals allowed.
+        * </ul>
+        */
+       protected PointcutParser() {
+               supportedPrimitives = getAllSupportedPointcutPrimitives();
+               setClassLoader(PointcutParser.class.getClassLoader());
+       }
+
+       /**
+        * Create a pointcut parser that can parse pointcut expressions built from a user-defined subset of AspectJ's supported pointcut
+        * primitives. The following restrictions apply:
+        * <ul>
+        * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+        * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
+        * <li>The pointcut expression must be anonymous with no formals allowed.
+        * </ul>
+        * 
+        * @param supportedPointcutKinds a set of PointcutPrimitives this parser should support
+        * @throws UnsupportedOperationException if the set contains if, cflow, or cflow below
+        */
+       private PointcutParser(Set/* <PointcutPrimitives> */supportedPointcutKinds) {
+               supportedPrimitives = supportedPointcutKinds;
+               for (Iterator iter = supportedPointcutKinds.iterator(); iter.hasNext();) {
+                       PointcutPrimitive element = (PointcutPrimitive) iter.next();
+                       if ((element == PointcutPrimitive.IF) || (element == PointcutPrimitive.CFLOW)
+                                       || (element == PointcutPrimitive.CFLOW_BELOW)) {
+                               throw new UnsupportedOperationException("Cannot handle if, cflow, and cflowbelow primitives");
+                       }
+               }
+               setClassLoader(PointcutParser.class.getClassLoader());
+       }
+
+       protected void setWorld(ReflectionWorld aWorld) {
+               this.world = aWorld;
+       }
+
+       /**
+        * Set the classloader that this parser should use for type resolution.
+        * 
+        * @param aLoader
+        */
+       protected void setClassLoader(ClassLoader aLoader) {
+               this.classLoaderReference = new WeakClassLoaderReference(aLoader);
+               world = new ReflectionWorld(this.classLoaderReference.getClassLoader());
+       }
+
+       /**
+        * Set the lint properties for this parser from the given resource on the classpath.
+        * 
+        * @param resourcePath path to a file containing aspectj lint properties
+        */
+       public void setLintProperties(String resourcePath) throws IOException {
+               URL url = this.classLoaderReference.getClassLoader().getResource(resourcePath);
+               InputStream is = url.openStream();
+               Properties p = new Properties();
+               p.load(is);
+               setLintProperties(p);
+       }
+
+       /**
+        * Set the lint properties for this parser from the given properties set.
+        * 
+        * @param properties
+        */
+       public void setLintProperties(Properties properties) {
+               getWorld().getLint().setFromProperties(properties);
+       }
+
+       /**
+        * Register a new pointcut designator handler with this parser. This provides an extension mechansim for the integration of
+        * domain-specific pointcut designators with the AspectJ pointcut language.
+        * 
+        * @param designatorHandler
+        */
+       public void registerPointcutDesignatorHandler(PointcutDesignatorHandler designatorHandler) {
+               this.pointcutDesignators.add(designatorHandler);
+               if (world != null)
+                       world.registerPointcutHandler(designatorHandler);
+       }
+
+       /**
+        * Create a pointcut parameter of the given name and type.
+        * 
+        * @param name
+        * @param type
+        * @return
+        */
+       public PointcutParameter createPointcutParameter(String name, Class type) {
+               return new PointcutParameterImpl(name, type);
+       }
+
+       /**
+        * Parse the given pointcut expression. A global scope is assumed for resolving any type references, and the pointcut must
+        * contain no formals (variables to be bound).
+        * 
+        * @throws UnsupportedPointcutPrimitiveException if the parser encounters a primitive pointcut expression of a kind not
+        *         supported by this PointcutParser.
+        * @throws IllegalArgumentException if the expression is not a well-formed pointcut expression
+        */
+       public PointcutExpression parsePointcutExpression(String expression) throws UnsupportedPointcutPrimitiveException,
+                       IllegalArgumentException {
+               return parsePointcutExpression(expression, null, new PointcutParameter[0]);
+       }
+
+       /**
+        * Parse the given pointcut expression. The pointcut is resolved as if it had been declared inside the inScope class (this
+        * allows the pointcut to contain unqualified references to other pointcuts declared in the same type for example). The pointcut
+        * may contain zero or more formal parameters to be bound at matched join points.
+        * 
+        * @throws UnsupportedPointcutPrimitiveException if the parser encounters a primitive pointcut expression of a kind not
+        *         supported by this PointcutParser.
+        * @throws IllegalArgumentException if the expression is not a well-formed pointcut expression
+        */
+       public PointcutExpression parsePointcutExpression(String expression, Class inScope, PointcutParameter[] formalParameters)
+                       throws UnsupportedPointcutPrimitiveException, IllegalArgumentException {
+               PointcutExpressionImpl pcExpr = null;
+               try {
+                       Pointcut pc = resolvePointcutExpression(expression, inScope, formalParameters);
+                       pc = concretizePointcutExpression(pc, inScope, formalParameters);
+                       validateAgainstSupportedPrimitives(pc, expression); // again, because we have now followed any ref'd pcuts
+                       pcExpr = new PointcutExpressionImpl(pc, expression, formalParameters, getWorld());
+               } catch (ParserException pEx) {
+                       throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx));
+               } catch (ReflectionWorld.ReflectionWorldException rwEx) {
+                       throw new IllegalArgumentException(rwEx.getMessage());
+               }
+               return pcExpr;
+       }
+
+       protected Pointcut resolvePointcutExpression(String expression, Class inScope, PointcutParameter[] formalParameters) {
+               try {
+                       PatternParser parser = new PatternParser(expression);
+                       parser.setPointcutDesignatorHandlers(pointcutDesignators, world);
+                       Pointcut pc = parser.parsePointcut();
+                       validateAgainstSupportedPrimitives(pc, expression);
+                       IScope resolutionScope = buildResolutionScope((inScope == null ? Object.class : inScope), formalParameters);
+                       pc = pc.resolve(resolutionScope);
+                       return pc;
+               } catch (ParserException pEx) {
+                       throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx));
+               }
+       }
+
+       protected Pointcut concretizePointcutExpression(Pointcut pc, Class inScope, PointcutParameter[] formalParameters) {
+               ResolvedType declaringTypeForResolution = null;
+               if (inScope != null) {
+                       declaringTypeForResolution = getWorld().resolve(inScope.getName());
+               } else {
+                       declaringTypeForResolution = ResolvedType.OBJECT.resolve(getWorld());
+               }
+               IntMap arity = new IntMap(formalParameters.length);
+               for (int i = 0; i < formalParameters.length; i++) {
+                       arity.put(i, i);
+               }
+               return pc.concretize(declaringTypeForResolution, declaringTypeForResolution, arity);
+       }
+
+       /**
+        * Parse the given aspectj type pattern, and return a matcher that can be used to match types using it.
+        * 
+        * @param typePattern an aspectj type pattern
+        * @return a type pattern matcher that matches using the given pattern
+        * @throws IllegalArgumentException if the type pattern cannot be successfully parsed.
+        */
+       public TypePatternMatcher parseTypePattern(String typePattern) throws IllegalArgumentException {
+               try {
+                       TypePattern tp = new PatternParser(typePattern).parseTypePattern();
+                       tp.resolve(world);
+                       return new TypePatternMatcherImpl(tp, world);
+               } catch (ParserException pEx) {
+                       throw new IllegalArgumentException(buildUserMessageFromParserException(typePattern, pEx));
+               } catch (ReflectionWorld.ReflectionWorldException rwEx) {
+                       throw new IllegalArgumentException(rwEx.getMessage());
+               }
+       }
+
+       private World getWorld() {
+               return world;
+       }
+
+       /* for testing */
+       Set getSupportedPrimitives() {
+               return supportedPrimitives;
+       }
+
+       /* for testing */
+       IMessageHandler setCustomMessageHandler(IMessageHandler aHandler) {
+               IMessageHandler current = getWorld().getMessageHandler();
+               getWorld().setMessageHandler(aHandler);
+               return current;
+       }
+
+       private IScope buildResolutionScope(Class inScope, PointcutParameter[] formalParameters) {
+               if (formalParameters == null)
+                       formalParameters = new PointcutParameter[0];
+               FormalBinding[] formalBindings = new FormalBinding[formalParameters.length];
+               for (int i = 0; i < formalBindings.length; i++) {
+                       formalBindings[i] = new FormalBinding(toUnresolvedType(formalParameters[i].getType()), formalParameters[i].getName(), i);
+               }
+               if (inScope == null) {
+                       return new SimpleScope(getWorld(), formalBindings);
+               } else {
+                       ResolvedType inType = getWorld().resolve(inScope.getName());
+                       ISourceContext sourceContext = new ISourceContext() {
+                               public ISourceLocation makeSourceLocation(IHasPosition position) {
+                                       return new SourceLocation(new File(""), 0);
+                               }
+
+                               public ISourceLocation makeSourceLocation(int line, int offset) {
+                                       return new SourceLocation(new File(""), line);
+                               }
+
+                               public int getOffset() {
+                                       return 0;
+                               }
+
+                               public void tidy() {
+                               }
+                       };
+                       return new BindingScope(inType, sourceContext, formalBindings);
+               }
+       }
+
+       private UnresolvedType toUnresolvedType(Class clazz) {
+               if (clazz.isArray()) {
+                       return UnresolvedType.forSignature(clazz.getName().replace('.', '/'));
+               } else {
+                       return UnresolvedType.forName(clazz.getName());
+               }
+       }
+
+       private void validateAgainstSupportedPrimitives(Pointcut pc, String expression) {
+               switch (pc.getPointcutKind()) {
+               case Pointcut.AND:
+                       validateAgainstSupportedPrimitives(((AndPointcut) pc).getLeft(), expression);
+                       validateAgainstSupportedPrimitives(((AndPointcut) pc).getRight(), expression);
+                       break;
+               case Pointcut.ARGS:
+                       if (!supportedPrimitives.contains(PointcutPrimitive.ARGS))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.ARGS);
+                       break;
+               case Pointcut.CFLOW:
+                       CflowPointcut cfp = (CflowPointcut) pc;
+                       if (cfp.isCflowBelow()) {
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.CFLOW_BELOW);
+                       } else {
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.CFLOW);
+                       }
+               case Pointcut.HANDLER:
+                       if (!supportedPrimitives.contains(PointcutPrimitive.HANDLER))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.HANDLER);
+                       break;
+               case Pointcut.IF:
+               case Pointcut.IF_FALSE:
+               case Pointcut.IF_TRUE:
+                       throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.IF);
+               case Pointcut.KINDED:
+                       validateKindedPointcut(((KindedPointcut) pc), expression);
+                       break;
+               case Pointcut.NOT:
+                       validateAgainstSupportedPrimitives(((NotPointcut) pc).getNegatedPointcut(), expression);
+                       break;
+               case Pointcut.OR:
+                       validateAgainstSupportedPrimitives(((OrPointcut) pc).getLeft(), expression);
+                       validateAgainstSupportedPrimitives(((OrPointcut) pc).getRight(), expression);
+                       break;
+               case Pointcut.THIS_OR_TARGET:
+                       boolean isThis = ((ThisOrTargetPointcut) pc).isThis();
+                       if (isThis && !supportedPrimitives.contains(PointcutPrimitive.THIS)) {
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.THIS);
+                       } else if (!supportedPrimitives.contains(PointcutPrimitive.TARGET)) {
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.TARGET);
+                       }
+                       break;
+               case Pointcut.WITHIN:
+                       if (!supportedPrimitives.contains(PointcutPrimitive.WITHIN))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.WITHIN);
+                       break;
+               case Pointcut.WITHINCODE:
+                       if (!supportedPrimitives.contains(PointcutPrimitive.WITHIN_CODE))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.WITHIN_CODE);
+                       break;
+               case Pointcut.ATTHIS_OR_TARGET:
+                       isThis = ((ThisOrTargetAnnotationPointcut) pc).isThis();
+                       if (isThis && !supportedPrimitives.contains(PointcutPrimitive.AT_THIS)) {
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_THIS);
+                       } else if (!supportedPrimitives.contains(PointcutPrimitive.AT_TARGET)) {
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_TARGET);
+                       }
+                       break;
+               case Pointcut.ATARGS:
+                       if (!supportedPrimitives.contains(PointcutPrimitive.AT_ARGS))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_ARGS);
+                       break;
+               case Pointcut.ANNOTATION:
+                       if (!supportedPrimitives.contains(PointcutPrimitive.AT_ANNOTATION))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_ANNOTATION);
+                       break;
+               case Pointcut.ATWITHIN:
+                       if (!supportedPrimitives.contains(PointcutPrimitive.AT_WITHIN))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_WITHIN);
+                       break;
+               case Pointcut.ATWITHINCODE:
+                       if (!supportedPrimitives.contains(PointcutPrimitive.AT_WITHINCODE))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_WITHINCODE);
+                       break;
+               case Pointcut.REFERENCE:
+                       if (!supportedPrimitives.contains(PointcutPrimitive.REFERENCE))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.REFERENCE);
+                       break;
+               case Pointcut.USER_EXTENSION:
+                       // always ok...
+                       break;
+               case Pointcut.NONE: // deliberate fall-through
+               default:
+                       throw new IllegalArgumentException("Unknown pointcut kind: " + pc.getPointcutKind());
+               }
+       }
+
+       private void validateKindedPointcut(KindedPointcut pc, String expression) {
+               Shadow.Kind kind = pc.getKind();
+               if ((kind == Shadow.MethodCall) || (kind == Shadow.ConstructorCall)) {
+                       if (!supportedPrimitives.contains(PointcutPrimitive.CALL))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.CALL);
+               } else if ((kind == Shadow.MethodExecution) || (kind == Shadow.ConstructorExecution)) {
+                       if (!supportedPrimitives.contains(PointcutPrimitive.EXECUTION))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.EXECUTION);
+               } else if (kind == Shadow.AdviceExecution) {
+                       if (!supportedPrimitives.contains(PointcutPrimitive.ADVICE_EXECUTION))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.ADVICE_EXECUTION);
+               } else if (kind == Shadow.FieldGet) {
+                       if (!supportedPrimitives.contains(PointcutPrimitive.GET))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.GET);
+               } else if (kind == Shadow.FieldSet) {
+                       if (!supportedPrimitives.contains(PointcutPrimitive.SET))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.SET);
+               } else if (kind == Shadow.Initialization) {
+                       if (!supportedPrimitives.contains(PointcutPrimitive.INITIALIZATION))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.INITIALIZATION);
+               } else if (kind == Shadow.PreInitialization) {
+                       if (!supportedPrimitives.contains(PointcutPrimitive.PRE_INITIALIZATION))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.PRE_INITIALIZATION);
+               } else if (kind == Shadow.StaticInitialization) {
+                       if (!supportedPrimitives.contains(PointcutPrimitive.STATIC_INITIALIZATION))
+                               throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.STATIC_INITIALIZATION);
+               }
+       }
+
+       private String buildUserMessageFromParserException(String pc, ParserException ex) {
+               StringBuffer msg = new StringBuffer();
+               msg.append("Pointcut is not well-formed: expecting '");
+               msg.append(ex.getMessage());
+               msg.append("'");
+               IHasPosition location = ex.getLocation();
+               msg.append(" at character position ");
+               msg.append(location.getStart());
+               msg.append("\n");
+               msg.append(pc);
+               msg.append("\n");
+               for (int i = 0; i < location.getStart(); i++) {
+                       msg.append(" ");
+               }
+               for (int j = location.getStart(); j <= location.getEnd(); j++) {
+                       msg.append("^");
+               }
+               msg.append("\n");
+               return msg.toString();
+       }
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutPrimitive.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/PointcutPrimitive.java
new file mode 100644 (file)
index 0000000..ae3f607
--- /dev/null
@@ -0,0 +1,50 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+
+package org.aspectj.weaver.tools;
+
+import org.aspectj.util.TypeSafeEnum;
+
+/**
+ * An enumeration of the different kinds of pointcut primitives
+ * supported by AspectJ.
+ */
+public final class PointcutPrimitive extends TypeSafeEnum {
+
+       public static final PointcutPrimitive CALL = new PointcutPrimitive("call",1);
+       public static final PointcutPrimitive EXECUTION = new PointcutPrimitive("execution",2);
+       public static final PointcutPrimitive GET = new PointcutPrimitive("get",3);
+       public static final PointcutPrimitive SET = new PointcutPrimitive("set",4);
+       public static final PointcutPrimitive INITIALIZATION = new PointcutPrimitive("initialization",5);
+       public static final PointcutPrimitive PRE_INITIALIZATION = new PointcutPrimitive("preinitialization",6);
+       public static final PointcutPrimitive STATIC_INITIALIZATION = new PointcutPrimitive("staticinitialization",7);
+       public static final PointcutPrimitive HANDLER = new PointcutPrimitive("handler",8);
+       public static final PointcutPrimitive ADVICE_EXECUTION = new PointcutPrimitive("adviceexecution",9);
+       public static final PointcutPrimitive WITHIN = new PointcutPrimitive("within",10);
+       public static final PointcutPrimitive WITHIN_CODE = new PointcutPrimitive("withincode",11);
+       public static final PointcutPrimitive CFLOW = new PointcutPrimitive("cflow",12);
+       public static final PointcutPrimitive CFLOW_BELOW = new PointcutPrimitive("cflowbelow",13);
+       public static final PointcutPrimitive IF = new PointcutPrimitive("if",14);
+       public static final PointcutPrimitive THIS = new PointcutPrimitive("this",15);
+       public static final PointcutPrimitive TARGET = new PointcutPrimitive("target",16);
+       public static final PointcutPrimitive ARGS = new PointcutPrimitive("args",17);
+       public static final PointcutPrimitive REFERENCE = new PointcutPrimitive("reference pointcut",18);
+       public static final PointcutPrimitive AT_ANNOTATION = new PointcutPrimitive("@annotation",19);
+       public static final PointcutPrimitive AT_THIS = new PointcutPrimitive("@this",20);
+       public static final PointcutPrimitive AT_TARGET = new PointcutPrimitive("@target",21);
+       public static final PointcutPrimitive AT_ARGS = new PointcutPrimitive("@args",22);
+       public static final PointcutPrimitive AT_WITHIN = new PointcutPrimitive("@within",23);
+       public static final PointcutPrimitive AT_WITHINCODE = new PointcutPrimitive("@withincode",24);
+
+       private PointcutPrimitive(String name, int key) {
+               super(name, key);
+       }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/ShadowMatch.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/ShadowMatch.java
new file mode 100644 (file)
index 0000000..55e2581
--- /dev/null
@@ -0,0 +1,58 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.tools;
+
+/**
+ * The result of asking a PointcutExpression to match at a shadow (method execution,
+ * handler, constructor call, and so on).
+ *
+ */
+public interface ShadowMatch {
+
+       /**
+        * True iff the pointcut expression will match any join point at this
+        * shadow (for example, any call to the given method).
+        */
+       boolean alwaysMatches();
+       
+       /**
+        * True if the pointcut expression may match some join points at this
+        * shadow (for example, some calls to the given method may match, depending
+        * on the type of the caller).
+        * <p>If alwaysMatches is true, then maybeMatches is always true.</p>
+        */
+       boolean maybeMatches();
+       
+       /**
+        * True iff the pointcut expression can never match any join point at this
+        * shadow (for example, the pointcut will never match a call to the given
+        * method).
+        */
+       boolean neverMatches();
+       
+       /**
+        * Return the result of matching a join point at this shadow with the given
+        * this, target, and args.
+        * @param thisObject  the object bound to this at the join point
+        * @param targetObject the object bound to target at the join point
+        * @param args the arguments at the join point
+        * @return
+        */
+       JoinPointMatch matchesJoinPoint(Object thisObject, Object targetObject, Object[] args);
+       
+       /**
+        * Set a matching context to be used when matching
+        * join points.
+        * @see MatchingContext
+        */
+       void setMatchingContext(MatchingContext aMatchContext);
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/Trace.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/Trace.java
new file mode 100644 (file)
index 0000000..c1a040d
--- /dev/null
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Matthew Webster - initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.tools;
+
+public interface Trace {
+
+       public void enter (String methodName, Object thiz, Object[] args);
+
+       public void enter (String methodName, Object thiz);
+
+       public void exit (String methodName, Object ret);
+
+       public void exit (String methodName, Throwable th);
+
+       public void exit (String methodName);
+
+       public void event (String methodName);
+
+       public void event (String methodName, Object thiz, Object[] args);
+       
+       public void debug (String message);
+       
+       public void info (String message);
+
+       public void warn (String message);
+
+       public void warn (String message, Throwable th);
+
+       public void error (String message);
+
+       public void error (String message, Throwable th);
+
+       public void fatal (String message);
+
+       public void fatal (String message, Throwable th);
+       
+       
+       /*
+        * Convenience methods
+        */
+       public void enter (String methodName, Object thiz, Object arg);
+
+       public void enter (String methodName, Object thiz, boolean z);
+
+       public void exit (String methodName, boolean b);
+
+       public void exit (String methodName, int i);
+
+       public void event (String methodName, Object thiz, Object arg);
+       
+       public boolean isTraceEnabled ();
+
+       public void setTraceEnabled (boolean b);
+}
\ No newline at end of file
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/TraceFactory.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/TraceFactory.java
new file mode 100644 (file)
index 0000000..6d819de
--- /dev/null
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Matthew Webster - initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.tools;
+
+import org.aspectj.util.LangUtil;
+
+public abstract class TraceFactory {
+    
+       public final static String DEBUG_PROPERTY = "org.aspectj.tracing.debug";
+       public final static String FACTORY_PROPERTY = "org.aspectj.tracing.factory";
+       public final static String DEFAULT_FACTORY_NAME = "default";
+       
+    protected static boolean debug = getBoolean(DEBUG_PROPERTY,false); 
+    private static TraceFactory instance;
+    
+    public Trace getTrace (Class clazz) {
+       return instance.getTrace(clazz);
+    }
+    
+    public static TraceFactory getTraceFactory () {
+       return instance;
+    }
+    
+    protected static boolean getBoolean(String name, boolean def) {
+               String defaultValue = String.valueOf(def);
+               String value = System.getProperty(name,defaultValue);
+               return Boolean.valueOf(value).booleanValue();
+       }
+
+       static {
+               
+               /*
+                * Allow user to override default behaviour or specify their own factory 
+                */
+               String factoryName = System.getProperty(FACTORY_PROPERTY);
+               if (factoryName != null) try {
+                       if (factoryName.equals(DEFAULT_FACTORY_NAME)) {
+                               instance = new DefaultTraceFactory();
+                       }
+                       else {
+                       Class factoryClass = Class.forName(factoryName);
+                       instance = (TraceFactory)factoryClass.newInstance();
+                       }
+               }
+       catch (Throwable th) {
+               if (debug) th.printStackTrace();
+       }
+       
+               /*
+                * Try to load external trace infrastructure using supplied factories
+                */
+       if (instance == null) try {
+                       if (LangUtil.is15VMOrGreater()) {
+                       Class factoryClass = Class.forName("org.aspectj.weaver.tools.Jdk14TraceFactory");
+                       instance = (TraceFactory)factoryClass.newInstance();
+                       } else {
+                       Class factoryClass = Class.forName("org.aspectj.weaver.tools.CommonsTraceFactory");
+                       instance = (TraceFactory)factoryClass.newInstance();
+                       }
+       }
+       catch (Throwable th) {
+               if (debug) th.printStackTrace();
+       }
+
+       /*
+                * Use default trace 
+                */
+       if (instance == null) {
+           instance = new DefaultTraceFactory();
+       }
+       
+       if (debug) System.err.println("TraceFactory.instance=" + instance);
+    }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/Traceable.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/Traceable.java
new file mode 100644 (file)
index 0000000..957786e
--- /dev/null
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Matthew Webster - initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.tools;
+
+public interface Traceable {
+
+       public String toTraceString ();
+       
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/TypePatternMatcher.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/TypePatternMatcher.java
new file mode 100644 (file)
index 0000000..be3b840
--- /dev/null
@@ -0,0 +1,23 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * ******************************************************************/
+package org.aspectj.weaver.tools;
+
+/**
+ * A compiled AspectJ type pattern that can be used to
+ * match against types at runtime.
+ */
+public interface TypePatternMatcher {
+
+       /**
+        * Does this type pattern matcher match the
+        * given type (Class).
+        */
+       public boolean matches(Class aClass);
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/UnsupportedPointcutPrimitiveException.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/UnsupportedPointcutPrimitiveException.java
new file mode 100644 (file)
index 0000000..6e0bbd6
--- /dev/null
@@ -0,0 +1,44 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *   Adrian Colyer                     Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.tools;
+
+import org.aspectj.weaver.WeaverMessages;
+
+/**
+ * @author colyer
+ *
+ */
+public class UnsupportedPointcutPrimitiveException extends RuntimeException {
+
+       private static final long serialVersionUID = 3258689888517043251L;
+
+       private PointcutPrimitive unsupportedPrimitive; 
+       private String pointcutExpression;
+       
+       public UnsupportedPointcutPrimitiveException(String pcExpression, PointcutPrimitive primitive) {
+               super(WeaverMessages.format(WeaverMessages.UNSUPPORTED_POINTCUT_PRIMITIVE,pcExpression,primitive.getName()));
+               this.pointcutExpression = pcExpression;
+               this.unsupportedPrimitive = primitive;
+       }
+
+       /**
+        * @return Returns the unsupportedPrimitive.
+        */
+       public PointcutPrimitive getUnsupportedPrimitive() {
+               return unsupportedPrimitive;
+       }
+       
+       public String getInvalidPointcutExpression() {
+               return pointcutExpression;
+       }
+       
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/tools/WeavingClassLoader.java b/org.aspectj.matcher/src/org/aspectj/weaver/tools/WeavingClassLoader.java
new file mode 100644 (file)
index 0000000..84987e1
--- /dev/null
@@ -0,0 +1,31 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Matthew Webster, Adrian Colyer, 
+ *     Martin Lippert     initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.weaver.tools;
+
+import java.net.URL;
+
+/**
+ * An interface for weaving class loaders to provide callbacks for a
+ * WeavingAdaptor.
+ */
+public interface WeavingClassLoader extends GeneratedClassHandler {
+       
+       /**
+        * Returns the aspects to be used by a WeavingAdaptor to weave classes
+        * defined by the class loader.
+        * @return the aspects used for weaving classes.
+        */
+       public URL[] getAspectURLs ();
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/weaver-messages.properties b/org.aspectj.matcher/src/org/aspectj/weaver/weaver-messages.properties
new file mode 100644 (file)
index 0000000..eced71a
--- /dev/null
@@ -0,0 +1,199 @@
+#####################################################################
+# Copyright (c) 2004 Contributors.
+# All rights reserved. 
+# This program and the accompanying materials are made available 
+# under the terms of the Eclipse Public License v1.0 
+# which accompanies this distribution and is available at 
+# http://www.eclipse.org/legal/epl-v10.html 
+#  
+# Contributors: 
+#     Adrian Colyer - Initial version
+#####################################################################
+
+# Messages output by the AspectJ Weaver
+
+# Pointcut related messages...
+argsInDeclare=args() pointcut designator cannot be used in declare statement
+cflowInDeclare=cflow{0}() pointcut designator cannot be used in declare statement
+ifInDeclare=if() pointcut designator cannot be used in declare statement
+thisOrTargetInDeclare={0}() pointcut designator cannot be used in declare statement
+abstractPointcut={0} is abstract
+abstractPointcutNotMadeConcrete=inherited abstract {0} is not made concrete in {1}
+conflictingInheritedPointcuts=conflicting inherited pointcuts in {0}
+circularPointcutDeclaration=circular pointcut declaration involving: {0}
+cantFindPointcut=can''t find pointcut ''{0}'' on {1}
+exactTypePatternRequired=exact type pattern required
+pointcutNotVisible=pointcut ''{0}'' is not visible from type ''{1}'' - cannot override
+cantBindType=can''t bind type name ''{0}''
+wildcardTypePatternNotAllowed=wildcard type pattern not allowed, must use type name
+fieldCantBeVoid=fields cannot have a void type
+noNewArrayJoinpointsByDefault=There are no join points for array construction unless -Xjoinpoints:arrayconstruction is specified
+unsupportedPointcutPrimitive=Pointcut expression ''{0}'' contains unsupported pointcut primitive ''{1}''
+missingTypePreventsMatch="Unable to determine match at this join point because the type ''{0}'' cannot be found"
+
+# Declare parents messages...
+decpObject=can''t change the parents of java.lang.Object
+cantExtendSelf=type ''{0}''can not extend itself
+interfaceExtendClass=interface can not extend a class
+decpHierarchy=can only insert a class into hierarchy, but {0} is not a subtype of {1}
+
+# declare precedence messages...
+multipleMatchesInPrecedence=multiple matches for {0}, matches both {1} and {2}
+circularityInPrecedenceStar=circularity in declare precedence, ''*'' occurs more than once
+nonAspectTypesInPrecedence=Non-aspect types can only be specified in a declare precedence statement when subtypes are included.  Non-aspect type is : {0}
+circularityInPrecedenceTwo=circularity in declare precedence, ''{0}'' matches two patterns
+
+# declare soft messages...
+notThrowable={0} is not a subtype of Throwable
+
+# itd messages...
+itdConsOnAspect=can''t declare constructor on an aspect
+returnTypeMismatch=can''t override {0} with {1} return types don''t match
+paramTypeMismatch=can''t override {0} with {1} parameter types don''t match
+visibilityReduction=can''t override {0} with {1} visibility is reduced
+cantOverrideFinalMember=can''t override final {0}
+doesntThrow=overriden method doesn't throw {0}
+overriddenStatic={0} cannot override {1}; overridden method is static
+overridingStatic={0} cannot override {1}; overriding method is static
+itdConflict=intertype declaration from {0} conflicts with intertype declaration: {1} from {2}
+itdMemberConflict=inter-type declaration from {0} conflicts with existing member: {1}
+itdNonExposedImplementor=type {0} must be accessible for weaving interface inter type declaration from aspect {1}
+itdAbstractMustBePublicOnInterface=abstract intertype method declaration ''{0}'' on interface {1} must be declared public (compiler limitation)
+
+# advice messages...
+nonVoidReturn=applying to join point that doesn't return void: {0}
+incompatibleReturnType=incompatible return type applying to {0}
+cantThrowChecked=can''t throw checked exception ''{0}'' at this join point ''{1}''
+circularDependency=circular advice precedence: can''t determine precedence between two or more pieces of advice that apply to the same join point: {0}
+
+# aspect messages..
+missingPerClause=expected per clause on super aspect not found on {0}
+wrongPerClause=wrong kind of per clause on super, expected {0} but found {1}
+
+# Reweavable messages...
+alreadyWoven=class ''{0}'' is already woven and has not been built in reweavable mode
+reweavableMode=weaver operating in reweavable mode.  Need to verify any required types exist.
+processingReweavable=processing reweavable type {0}: {1}
+missingReweavableType=type {0} is needed by reweavable type {1}
+verifiedReweavableType=successfully verified type {0} exists.  Originates from {1}
+aspectNeeded=aspect {0} is needed when using type {1}
+reweavableAspectNotRegistered=aspect ''{0}'' woven into ''{1}'' must be defined to the weaver (placed on the aspectpath, or defined in an aop.xml file if using LTW).
+
+# The infamous and deserving a category all of its own...
+cantFindType=can''t find type {0}
+cantFindCoreType=can''t find critical required type {0}
+cantFindTypeWithinpcd=Unable to find type {0} whilst processing within() pointcut at this source location
+cftDuringAroundWeave=Can't find type {0} whilst applying around advice
+cftDuringAroundWeavePreinit=Can't find type {0} whilst applying around advice to preinitialization join point
+cftExceptionType=Can't find exception type {0} whilst processing advice
+cftArgType=Can't find type {0} whilst processing args() pcd
+cantFindParentType=can''t find type {0} needed to evaluate methods inherited by subtype {1}
+cantFindParentTypeNoSub=can''t find type {0} when attempting to find the set of methods it declares
+cantFindTypeFields=can''t find fields of missing type {0}
+cantFindTypeSuperclass=can''t determine superclass of missing type {0}
+cantFindTypeInterfaces=can''t determine implemented interfaces of missing type {0}
+cantFindTypeMethods=can''t determine methods of missing type {0}
+cantFindTypePointcuts=can''t determine pointcuts declared in missing type {0}
+cantFindTypeModifiers=can''t determine modifiers of missing type {0}
+cantFindTypeAnnotation=can''t determine annotations of missing type {0}
+cantFindTypeAssignable=can''t determine whether missing type {0} is an instance of {1}
+cantFindTypeCoerceable=can''t determine whether missing type {0} can be coerced from {1}
+cantFindTypeJoinPoint=can''t find type {0} whilst determining signatures of call or execution join point for {1}, this may cause a pointcut to fail to match at this join point 
+cantFindTypeInterfaceMethods=can''t find type {0} whilst determining all methods of an implementing subtype, this may cause a pointcut to fail to match at a call or execution join point, or an illegal method override via an ITD to go undetected
+
+# Implementation limitations...
+decpBinaryLimitation=can''t use declare parents to change superclass of binary form ''{0}'' (implementation limitation)
+overwriteJSR45=overwriting JSR45 information for {0} (compiler limitation)
+ifInPerClause=if() pointcut designator cannot be used directly in a per clause (compiler limitation).  Create a named pointcut containing the if() and refer to it
+ifLexicallyInCflow=if not supported lexically within cflow (compiler limitation)
+onlyBeforeOnHandler=Only before advice is supported on handler join points (compiler limitation)
+noAroundOnSynchronization=Around advice is not supported on the lock and unlock join points (compiler limitation)
+aroundOnPreInit=around on pre-initialization not supported (compiler limitation)
+aroundOnInit=around on initialization not supported (compiler limitation)
+aroundOnInterfaceStaticInit=around on staticinitialization of interface ''{0}'' not supported (compiler limitation)
+
+# Bytecode generation nasties...
+problemGeneratingMethod=problem generating method {0}.{1} : {2}
+classTooBig=The class {0} exceeds the maximum class size supported by the JVM (constant pool too big).
+
+# Classpath messages
+zipfileEntryMissing=zipfile classpath entry does not exist: {0}
+zipfileEntryInvalid=zipfile classpath entry is invalid: {0} <{1}>
+directoryEntryMissing=directory classpath entry does not exist: {0}
+outjarInInputPath=-outjar cannot be a member of -injars, -inpath or -aspectpath
+
+# Lint messages
+problemLoadingXLint=problem loading Xlint properties file: {0}, {1}
+unableToLoadXLintDefault=couldn''t load XlintDefault.properties
+errorLoadingXLintDefault=problem loading XlintDefault.properties, {0}
+invalidXLintKey=invalid Xlint key: {0}
+invalidXLintMessageKind=invalid Xlint message kind (must be one of ignore, warning, error): {0}
+
+# Binding of formals
+unboundFormalInPC=the parameter {0} is not bound in [all branches of] pointcut
+ambiguousBindingInPC=the binding of parameter {0} is ambiguous in pointcut
+ambiguousBindingInOrPC=ambiguous binding of parameter(s) {0} across ''||'' in pointcut
+negationDoesntAllowBinding=cannot bind a parameter in a negated expression
+
+# Java5 
+
+# Enum
+itdcOnEnumNotAllowed=can''t make inter-type constructor declarations on enum types
+itdmOnEnumNotAllowed=can''t make inter-type method declarations on enum types
+itdfOnEnumNotAllowed=can''t make inter-type field declarations on enum types
+cantDecpOnEnumToImplInterface=can''t use declare parents to make enum type {0} implement an interface
+cantDecpOnEnumToExtendClass=can''t use declare parents to alter supertype of enum type {0}
+cantDecpToMakeEnumSupertype=can''t use declare parents to make ''java.lang.Enum'' the parent of type {0}
+
+# Annotation
+itdcOnAnnotationNotAllowed=can''t make inter-type constructor declarations on annotation types
+itdmOnAnnotationNotAllowed=can''t make inter-type method declarations on annotation types
+itdfOnAnnotationNotAllowed=can''t make inter-type field declarations on annotation types
+cantDecpOnAnnotationToImplInterface=can''t use declare parents to make annotation type {0} implement an interface
+cantDecpOnAnnotationToExtendClass=can''t use declare parents to alter supertype of annotation type {0}
+cantDecpToMakeAnnotationSupertype=can''t use declare parents to make ''java.lang.annotation.Annotation'' the parent of type {0}
+incorrectTargetForDeclareAnnotation={0} is not a valid target for annotation {1}, this annotation can only be applied to these element types {2}
+
+referenceToNonAnnotationType=Type referred to is not an annotation type: {0}
+bindingNonRuntimeRetentionAnnotation=Annotation type {0} does not have runtime retention
+noMatchBecauseSourceRetention=Failing match because annotation ''{0}'' on type ''{1}'' has SOURCE retention.  Matching allowed when RetentionPolicy is CLASS or RUNTIME
+
+# Annotation value
+invalidAnnotationValue=Invalid annotation value ''{0}'', expected {1} value
+unknownAnnotationValue=The annotation ''{0}'' does not define a value named ''{1}''
+
+# Generics
+cantDecpMultipleParameterizations=Cannot declare parent {0} onto type {1} since it already has {2} in its hierarchy
+noParameterizedTypePatternInHandler=a parameterized type pattern may not be used in a handler pointcut expression
+incorrectNumberOfTypeArguments=Type pattern does not match because the wrong number of type parameters are specified: Type {0} requires {1} parameter(s)
+violatesTypeVariableBounds=Type {0} does not meet the specification for type parameter {1} ({2}) in generic type {3}
+notAGenericType=Type pattern does not match because {0} is not a generic type
+noStaticInitJPsForParameterizedTypes=no static initialization join points for parameterized types, use raw type instead
+noParameterizedTypePatternInWithin=parameterized type pattern not supported by 'within', use a raw type pattern instead
+noParameterizedTypesInThisAndTarget=parameterized types not supported for this and target pointcuts (erasure limitation)
+noParameterizedTypesInGetAndSet=can't use parameterized type patterns for the declaring type of a get or set pointcut expression (use the raw type instead)
+noInitJPsForParameterizedTypes=no [pre]initialization join points for parameterized types, use raw type instead
+noGenericThrowables=invalid throws pattern: a generic class may not be a direct or indirect subclass of Throwable
+noParameterizedDeclaringTypesWithinCode=can't use parameterized type patterns for the declaring type of a withincode pointcut expression (use the raw type instead)
+noParameterizedDeclaringTypesInExecution=can't use parameterized type patterns for the declaring type of an execution pointcut expression (use the raw type instead)
+noParameterizedDeclaringTypesInCall=can't use parameterized type patterns for the declaring type of a call pointcut expression (use the raw type instead)
+noRawTypePointcutReferences=cannot use a raw type reference to refer to a pointcut in a generic type (use a parameterized reference instead)
+
+hasMemberNotEnabled=the type pattern {0} can only be used when the -XhasMember option is set
+
+# Java5 features used in pre-Java 5 environment
+atannotationNeedsJava5=the @annotation pointcut expression is only supported at Java 5 compliance level or above
+atwithinNeedsJava5=the @within pointcut expression is only supported at Java 5 compliance level or above
+atwithincodeNeedsJava5=the @withincode pointcut expression is only supported at Java 5 compliance level or above
+atthisNeedsJava5=the @this pointcut expression is only supported at Java 5 compliance level or above
+attargetNeedsJava5=the @target pointcut expression is only supported at Java 5 compliance level or above
+atargsNeedsJava5=the @args pointcut expression is only supported at Java 5 compliance level or above
+declareAtTypeNeedsJava5=declare @type is only supported at Java 5 compliance level or above
+declareAtMethodNeedsJava5=declare @method is only supported at Java 5 compliance level or above
+declareAtFieldNeedsJava5=declare @field is only supported at Java 5 compliance level or above
+declareAtConsNeedsJava5=declare @constructor is only supported at Java 5 compliance level or above
+annotationsRequireJava5=annotation type patterns are only supported at Java 5 compliance level or above
+
+# @AspectJ
+returningFormalNotDeclaredInAdvice=the last parameter of this advice must be named ''{0}'' to bind the returning value
+thrownFormalNotDeclaredInAdvice=the last parameter of this advice must be named ''{0}'' and be of a subtype of Throwable
\ No newline at end of file