aboutsummaryrefslogtreecommitdiffstats
path: root/weaver
diff options
context:
space:
mode:
authorwisberg <wisberg>2002-12-16 17:58:19 +0000
committerwisberg <wisberg>2002-12-16 17:58:19 +0000
commitd842c4f1139629c1f062b74ba818d233b2c31043 (patch)
tree842d3871620bc0eb60edcd95e55804d67e0f61fa /weaver
parent3ce247199704eae6b2c92c6e38c69584e3250c52 (diff)
downloadaspectj-d842c4f1139629c1f062b74ba818d233b2c31043.tar.gz
aspectj-d842c4f1139629c1f062b74ba818d233b2c31043.zip
initial version
Diffstat (limited to 'weaver')
-rw-r--r--weaver/.classpath15
-rw-r--r--weaver/.project22
-rw-r--r--weaver/bcelIssues.txt12
-rw-r--r--weaver/features.txt305
-rw-r--r--weaver/src/.cvsignore2
-rw-r--r--weaver/src/org/aspectj/weaver/Advice.java243
-rw-r--r--weaver/src/org/aspectj/weaver/AdviceKind.java110
-rw-r--r--weaver/src/org/aspectj/weaver/AjAttribute.java411
-rw-r--r--weaver/src/org/aspectj/weaver/AjcMemberMaker.java508
-rw-r--r--weaver/src/org/aspectj/weaver/AsmAdaptor.java157
-rw-r--r--weaver/src/org/aspectj/weaver/BCException.java29
-rw-r--r--weaver/src/org/aspectj/weaver/BetaException.java29
-rw-r--r--weaver/src/org/aspectj/weaver/Checker.java61
-rw-r--r--weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java76
-rw-r--r--weaver/src/org/aspectj/weaver/CrosscuttingMembers.java201
-rw-r--r--weaver/src/org/aspectj/weaver/CrosscuttingMembersSet.java140
-rw-r--r--weaver/src/org/aspectj/weaver/IClassWeaver.java29
-rw-r--r--weaver/src/org/aspectj/weaver/IHasPosition.java33
-rw-r--r--weaver/src/org/aspectj/weaver/IHasSourceLocation.java21
-rw-r--r--weaver/src/org/aspectj/weaver/ISourceContext.java20
-rw-r--r--weaver/src/org/aspectj/weaver/IWeaver.java24
-rw-r--r--weaver/src/org/aspectj/weaver/IntMap.java134
-rw-r--r--weaver/src/org/aspectj/weaver/Iterators.java215
-rw-r--r--weaver/src/org/aspectj/weaver/Lint.java141
-rw-r--r--weaver/src/org/aspectj/weaver/Member.java745
-rw-r--r--weaver/src/org/aspectj/weaver/NameMangler.java300
-rw-r--r--weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java78
-rw-r--r--weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java43
-rw-r--r--weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java53
-rw-r--r--weaver/src/org/aspectj/weaver/PerObjectInterfaceTypeMunger.java68
-rw-r--r--weaver/src/org/aspectj/weaver/PrivilegedAccessMunger.java36
-rw-r--r--weaver/src/org/aspectj/weaver/ResolvedMember.java156
-rw-r--r--weaver/src/org/aspectj/weaver/ResolvedPointcutDefinition.java91
-rw-r--r--weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java162
-rw-r--r--weaver/src/org/aspectj/weaver/ResolvedTypeX.java975
-rw-r--r--weaver/src/org/aspectj/weaver/Shadow.java233
-rw-r--r--weaver/src/org/aspectj/weaver/ShadowMunger.java87
-rw-r--r--weaver/src/org/aspectj/weaver/StaticJoinPointFactory.java58
-rw-r--r--weaver/src/org/aspectj/weaver/TypeX.java683
-rw-r--r--weaver/src/org/aspectj/weaver/WeaverStateKind.java47
-rw-r--r--weaver/src/org/aspectj/weaver/World.java320
-rw-r--r--weaver/src/org/aspectj/weaver/XlintDefault.properties4
-rw-r--r--weaver/src/org/aspectj/weaver/ast/ASTNode.java22
-rw-r--r--weaver/src/org/aspectj/weaver/ast/And.java51
-rw-r--r--weaver/src/org/aspectj/weaver/ast/Call.java41
-rw-r--r--weaver/src/org/aspectj/weaver/ast/CallExpr.java48
-rw-r--r--weaver/src/org/aspectj/weaver/ast/Expr.java36
-rw-r--r--weaver/src/org/aspectj/weaver/ast/FieldGet.java48
-rw-r--r--weaver/src/org/aspectj/weaver/ast/FieldGetCall.java47
-rw-r--r--weaver/src/org/aspectj/weaver/ast/IExprVisitor.java23
-rw-r--r--weaver/src/org/aspectj/weaver/ast/ITestVisitor.java27
-rw-r--r--weaver/src/org/aspectj/weaver/ast/Instanceof.java52
-rw-r--r--weaver/src/org/aspectj/weaver/ast/Literal.java39
-rw-r--r--weaver/src/org/aspectj/weaver/ast/Not.java45
-rw-r--r--weaver/src/org/aspectj/weaver/ast/Or.java49
-rw-r--r--weaver/src/org/aspectj/weaver/ast/Test.java91
-rw-r--r--weaver/src/org/aspectj/weaver/ast/Var.java38
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java312
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelAttributes.java52
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelCflowAccessVar.java92
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelCflowStackFieldAdder.java72
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java889
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelField.java60
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelFieldRef.java103
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelMethod.java107
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java236
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelRenderer.java232
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelShadow.java1731
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelSourceContext.java55
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java566
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelVar.java126
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java374
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelWorld.java320
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java191
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/ExceptionRange.java146
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java471
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java1060
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/LineNumberTag.java39
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/LocalVariableTag.java60
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/Range.java225
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/ShadowRange.java199
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/Tag.java42
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/UnwovenClassFile.java181
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/UnwovenZipClassFile.java45
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/Utility.java442
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/ZipFileWeaver.java41
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/AndPointcut.java84
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java79
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java140
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/BasicToken.java75
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/BasicTokenSource.java153
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/BindingTypePattern.java74
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/Bindings.java127
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java165
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java116
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/Declare.java54
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/DeclareDominates.java110
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/DeclareErrorOrWarning.java99
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/DeclareParents.java100
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/DeclareSoft.java87
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java82
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/ExposedState.java57
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/FormalBinding.java76
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java94
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/IScope.java47
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/IToken.java53
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/ITokenSource.java26
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/IfPointcut.java137
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java115
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/ModifiersPattern.java92
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/NameBindingPointcut.java47
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/NamePattern.java158
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/NotPointcut.java96
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java75
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/OrPointcut.java89
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java79
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/ParserException.java31
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/PatternNode.java82
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/PatternParser.java781
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/PerCflow.java98
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/PerClause.java67
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/PerFromSuper.java94
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/PerObject.java104
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/PerSingleton.java68
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/Pointcut.java228
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java266
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java224
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/SimpleScope.java137
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java108
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/ThrowsPattern.java110
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/TypePattern.java263
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/TypePatternList.java234
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/TypePatternQuestions.java109
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java428
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java83
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java79
-rw-r--r--weaver/testdata/AddNotResidueDynamicHelloWorld.txt82
-rw-r--r--weaver/testdata/AddResidueDynamicHelloWorld.txt82
-rw-r--r--weaver/testdata/AddStateResidueDynamicHelloWorld.txt84
-rw-r--r--weaver/testdata/AfterFancyHelloWorld.txt183
-rw-r--r--weaver/testdata/AfterHelloWorld.txt58
-rw-r--r--weaver/testdata/AfterReturningCheckcastParamFancyHelloWorld.txt86
-rw-r--r--weaver/testdata/AfterReturningCheckcastParamHelloWorld.txt31
-rw-r--r--weaver/testdata/AfterReturningConversionParam.txt83
-rw-r--r--weaver/testdata/AfterReturningConversionParamFancyHelloWorld.txt88
-rw-r--r--weaver/testdata/AfterReturningFancyHelloWorld.txt101
-rw-r--r--weaver/testdata/AfterReturningHelloWorld.txt30
-rw-r--r--weaver/testdata/AfterReturningParamFancyHelloWorld.txt82
-rw-r--r--weaver/testdata/AfterReturningParamHelloWorld.txt27
-rw-r--r--weaver/testdata/AfterThrowingFancyHelloWorld.txt161
-rw-r--r--weaver/testdata/AfterThrowingHelloWorld.txt50
-rw-r--r--weaver/testdata/AfterThrowingParamFancyHelloWorld.txt86
-rw-r--r--weaver/testdata/AfterThrowingParamHelloWorld.txt31
-rw-r--r--weaver/testdata/ArgsAfterReturningFancyHelloWorld.txt108
-rw-r--r--weaver/testdata/ArgsAfterReturningHelloWorld.txt32
-rw-r--r--weaver/testdata/ArgsAfterThrowingHelloWorld.txt42
-rw-r--r--weaver/testdata/ArgsBeforeAfterHelloWorld.txt52
-rw-r--r--weaver/testdata/AroundAllAndOthersFancyHelloWorld.txt1003
-rw-r--r--weaver/testdata/AroundAllAndOthersHelloWorld.txt346
-rw-r--r--weaver/testdata/AroundAllFancyHelloWorld.txt541
-rw-r--r--weaver/testdata/AroundAllHelloWorld.txt183
-rw-r--r--weaver/testdata/AroundAndOthersFancyHelloWorld.txt375
-rw-r--r--weaver/testdata/AroundAndOthersHelloWorld.txt122
-rw-r--r--weaver/testdata/AroundArgsDynamicHelloWorld.txt133
-rw-r--r--weaver/testdata/AroundFancyHelloWorld.txt229
-rw-r--r--weaver/testdata/AroundHelloWorld.txt73
-rw-r--r--weaver/testdata/BeforeFancyHelloWorld.txt90
-rw-r--r--weaver/testdata/BeforeHelloWorld.txt26
-rw-r--r--weaver/testdata/CflowNonStaticBeforeFancyHelloWorld.txt92
-rw-r--r--weaver/testdata/CflowNonStaticBeforeHelloWorld.txt37
-rw-r--r--weaver/testdata/CflowStateResidueDynamicHelloWorld.txt119
-rw-r--r--weaver/testdata/ExtractedFancyHelloWorld.txt169
-rw-r--r--weaver/testdata/ExtractedHelloWorld.txt52
-rw-r--r--weaver/testdata/FieldSet.txt68
-rw-r--r--weaver/testdata/IdDummyAspect.txt16
-rw-r--r--weaver/testdata/IdFancyHelloWorld.txt77
-rw-r--r--weaver/testdata/IdHelloWorld.txt22
-rw-r--r--weaver/testdata/NoResidueDynamicHelloWorld.txt75
-rw-r--r--weaver/testdata/NonStaticBeforeFancyHelloWorld.txt79
-rw-r--r--weaver/testdata/NonStaticBeforeHelloWorld.txt24
-rw-r--r--weaver/testdata/PatternWeaveFancyHelloWorld.txt77
-rw-r--r--weaver/testdata/PatternWeaveHelloWorld.txt22
-rw-r--r--weaver/testdata/PerSingletonField.txt22
-rw-r--r--weaver/testdata/PerThisNonStaticBeforeFancyHelloWorld.txt113
-rw-r--r--weaver/testdata/PerThisNonStaticBeforeHelloWorld.txt34
-rw-r--r--weaver/testdata/Regex.jarbin0 -> 29871 bytes
-rw-r--r--weaver/testdata/StateResidueMultiArgHelloWorld.txt62
-rw-r--r--weaver/testdata/StaticEnclosingTjpBeforeHelloWorld.txt61
-rw-r--r--weaver/testdata/StaticTjpBeforeHelloWorld.txt79
-rw-r--r--weaver/testdata/StringResidue1MultiArgHelloWorld.txt63
-rw-r--r--weaver/testdata/StringResidue2MultiArgHelloWorld.txt60
-rw-r--r--weaver/testdata/StringResidue3MultiArgHelloWorld.txt60
-rw-r--r--weaver/testdata/TjpAround2HelloWorld.txt503
-rw-r--r--weaver/testdata/TjpAroundHelloWorld.txt312
-rw-r--r--weaver/testdata/TjpBeforeHelloWorld.txt129
-rw-r--r--weaver/testdata/TraceJarHello.txt199
-rw-r--r--weaver/testdata/aspectjtools.jarbin0 -> 5196036 bytes
-rw-r--r--weaver/testdata/dummyAspect.jarbin0 -> 581 bytes
-rw-r--r--weaver/testdata/megatrace.jarbin0 -> 4873 bytes
-rw-r--r--weaver/testdata/megatraceNoweave.jarbin0 -> 2631 bytes
-rw-r--r--weaver/testdata/tracing.jarbin0 -> 2220 bytes
-rw-r--r--weaver/testsrc/Aspect.java347
-rw-r--r--weaver/testsrc/BcweaverModuleTests.java30
-rw-r--r--weaver/testsrc/DynamicHelloWorld.java24
-rw-r--r--weaver/testsrc/FancyHelloWorld.java24
-rw-r--r--weaver/testsrc/FieldyHelloWorld.java10
-rw-r--r--weaver/testsrc/HelloWorld.java12
-rw-r--r--weaver/testsrc/MultiArgHelloWorld.java12
-rw-r--r--weaver/testsrc/Test.java11
-rw-r--r--weaver/testsrc/TestSwitchy.java31
-rw-r--r--weaver/testsrc/fluffy/Aspect.java31
-rw-r--r--weaver/testsrc/fluffy/Base.java15
-rw-r--r--weaver/testsrc/fluffy/Derived.java17
-rw-r--r--weaver/testsrc/org/aspectj/weaver/AbstractWorldTestCase.java179
-rw-r--r--weaver/testsrc/org/aspectj/weaver/BcweaverTests.java33
-rw-r--r--weaver/testsrc/org/aspectj/weaver/MemberTestCase.java175
-rw-r--r--weaver/testsrc/org/aspectj/weaver/TestShadow.java79
-rw-r--r--weaver/testsrc/org/aspectj/weaver/TypeXTestCase.java124
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/AfterReturningWeaveTestCase.java58
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/AfterThrowingWeaveTestCase.java43
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/AfterWeaveTestCase.java34
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/ArgsWeaveTestCase.java109
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/AroundArgsWeaveTestCase.java41
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/AroundWeaveTestCase.java93
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/BcelTests.java52
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/BeforeWeaveTestCase.java31
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/CheckerTestCase.java48
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/FieldSetTestCase.java35
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/HierarchyDependsTestCase.java67
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/IdWeaveTestCase.java107
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/MegaZipTestCase.java111
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/MoveInstructionsWeaveTestCase.java73
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/NonstaticWeaveTestCase.java86
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/PatternWeaveTestCase.java117
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/PointcutResidueTestCase.java236
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/TjpWeaveTestCase.java97
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/TraceJarWeaveTestCase.java40
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/UtilityTestCase.java52
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/WeaveOrderTestCase.java155
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/WeaveTestCase.java324
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/WorldTestCase.java148
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/ZipTestCase.java90
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/AndOrNotTestCase.java121
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/BindingTestCase.java142
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/ConcretizationTestCase.java161
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/DeclareErrorOrWarningTestCase.java61
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/ModifiersPatternTestCase.java140
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/NamePatternParserTestCase.java65
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/NamePatternTestCase.java118
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java70
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/PatternsTests.java41
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/SignaturePatternTestCase.java175
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/TestScope.java30
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/ThisOrTargetTestCase.java102
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/TypePatternListTestCase.java190
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/TypePatternTestCase.java290
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/WithinTestCase.java102
257 files changed, 35118 insertions, 0 deletions
diff --git a/weaver/.classpath b/weaver/.classpath
new file mode 100644
index 000000000..17ae558e0
--- /dev/null
+++ b/weaver/.classpath
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="testsrc"/>
+ <classpathentry kind="var" path="JRE_LIB" rootpath="JRE_SRCROOT" sourcepath="JRE_SRC"/>
+ <classpathentry kind="src" path="/runtime"/>
+ <classpathentry kind="lib" path="/lib/bcel/bcel.jar"
+ rootpath="bcel-5.0/src/java" sourcepath="/lib/bcel/bcel-src.zip"/>
+ <classpathentry kind="lib" path="/lib/junit/junit.jar" sourcepath="/lib/junit/src.jar"/>
+ <classpathentry kind="src" path="/util"/>
+ <classpathentry kind="src" path="/testing-util"/>
+ <classpathentry kind="src" path="/bridge"/>
+ <classpathentry kind="src" path="/asm"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/weaver/.project b/weaver/.project
new file mode 100644
index 000000000..940c812a5
--- /dev/null
+++ b/weaver/.project
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>weaver</name>
+ <comment></comment>
+ <projects>
+ <project>asm</project>
+ <project>bridge</project>
+ <project>runtime</project>
+ <project>testing-util</project>
+ <project>util</project>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/weaver/bcelIssues.txt b/weaver/bcelIssues.txt
new file mode 100644
index 000000000..14bf0b16d
--- /dev/null
+++ b/weaver/bcelIssues.txt
@@ -0,0 +1,12 @@
+* updateTarget doesn't work with exnTargets, in particular, when the startPC and endPC are the same handle.
+
+* RemoveNOP doesn't work properly with exnTargets (and, much less importantly, local variable tables),
+ because it always retargets to the NEXT instruction... the endPC should retarget to the LAST instruction.
+
+* parameter names aren't set correctly (to anything) when a MethodGen is read from a Method.
+
+* the superclassname of java.lang.object is set to java.lang.object (!!)
+
+* RET should be a local variable instruction
+
+
diff --git a/weaver/features.txt b/weaver/features.txt
new file mode 100644
index 000000000..2c62391eb
--- /dev/null
+++ b/weaver/features.txt
@@ -0,0 +1,305 @@
+AspectJ 1.1 Features
+------------------------------------------------------------
+
+
+------------------------------
+About this document
+
+This document contains information about the proposed features of
+AspectJ 1.1. It assumes as a baseline that AspectJ 1.1 includes all
+the features of AspectJ 1.0.6. Any feature difference, especially
+incompatible changes, should be noted. It is organized by DOWNLOAD.
+Inside the tools download there are sections per feature.
+
+Feel free to just stick shorthand notes at the end of this file, and
+move them up to the New Features (or other) section as we want.
+
+
+------------------------------
+OPEN ISSUES
+
+* -sourceroots/-injars matrix completeness
+
+* do we release ant tasks in beta?
+
+* do we call beta alpha or alpha beta?
+
+------------------------------
+DOWNLOAD: Tools
+
+General deliverables: Two licence files. A readme. Possibly a changes.
+
+---- runtime
+
+Deliverable: aspectjrt.jar
+
+Changes:
+
+* RUNTIME_LICENCE: AspectjRT.jar now has a BSD-style licence [NOT BETA]
+
+* JOINPOINT_NAMES: Added constant fields holding constant names for
+ the join points.
+
+* NO_COLUMN_NUMBER: thisJoinPoint.getSourceLocation().getColumn()
+ is incompatible with bytecode weaving and can not be supported.
+ Do we want to remove the method or make it return -1?
+
+* NOT_10_BINARY_COMPATIBLE: Some modifications to classes in internal
+ packages means that code built with 1.1 won't run on the 1.0 version
+ of aspectjrt.jar.
+ [XXX this has always been true and sounds more scary than it is.
+ The readme/docs do/should always say that you need to compile and
+ run with at least the same version of the runtime classes as
+ the compiler]
+
+---- tools
+
+Deliverable: aspectjtools.jar
+
+* Single jar containing .class files for all components listed below.
+ This will contain code under both the CPL and the MPL.
+
+---- ajc
+
+Deliverable: ajc, ajc.bat
+
+Changes:
+
+-- new features
+* NO_SOURCE: -source/-usejavac options are not supported [INCOMPATIBLE]
+
+* SOURCEROOT: -sourceroots option indicates that all source files in
+ a particular directory tree should be compiled [NEW]
+ This option is the only way that sourcefiles can currently be
+ specified for incremental compilation on the command-line.
+
+* BYTECODE_WEAVING: supporting bytecode-containing jar files as input
+ for the compiler. [NEW]
+ * Command-line: -injars option
+ Not supported in incremental mode.
+ * Eclipse: not supported [BETA]
+ This has a ripple effect on "code the compiler controls" issues.
+ There are obfustication issues that should be discussed in the readme
+
+* OUTJAR: supports generating a single .jar file with the results of a
+ compilation, rather than separate .class files. This should be
+ most useful when weaving into existing .jar files. The resulting jar
+ file has no meta-information, just classes. [question: compression level?]
+ [NEW]
+
+* BINARY_ASPECTS: Aspects may be compiled to a standalone bytecode
+ form, and later be used in a linking/compiling phase to affect join
+ points. [NEW]
+ This will only be partially working in beta1: The front-end is not
+ reading the binary aspects. [BETA]
+
+* INCREMENTAL: incremental compilation [NEW]
+ * Command-line: interface is using -sourceroots and typing <enter>
+ for an incremental recompile. Better interfaces are possible
+ in the future.
+ * Eclipse: invisible
+ * JBuilder/Netbeans: ??
+ * Emacs: possibly using new command-line interface?
+ * Ant: unsupported in BETA
+
+* NORMAL_OPTIONS: now supporting many javac options ajc failed to in 1.0:
+ essentially those supported in the ECLIPSE_OPTIONS [NEW]
+
+* ECLIPSE_OPTIONS: The eclipse compiler provides a large number of
+ options for controlling its behavior, i.e. -warn:unusedLocals. All
+ of these options may be passed to the command-line ajc compiler. Mik should
+ be bugged to get full list and description of the options [NEW]
+
+
+-- features not supported yet
+
+* NO_WEAVE: An option with unknown name that generates code but does
+ no back-end weaving [NO BETA]
+
+* SOURCE_INFORMATION: Source file information in error messages may be
+ either better or worse (depending on how well we do our eclipse
+ integration, this may not happen). [INCOMPATIBLE, MINIMAL]
+ JSR 45 information is not created/maintained. [BETA]
+
+* NO_AROUND_OPTIMIZATION: -XinlineAroundClosure not implemented.
+ [INCOMPATIBLE] No inlining at all [BETA].
+
+* NO_CALLEE_SIDE_CALL: Not implemented [BETA]
+
+* OTHER_X_OPTIONS: XaddSafePrefix (not used anymore, but we make some
+ weak guarantees about this), XserializableAspects [see below]
+ XTargetNearSource [see below]
+
+
+-- features no longer supported
+* NO_SOURCE: -preprocess/-usejavac/-nocomment/-workingdir options are
+ not supported [INCOMPATIBLE]
+
+* NO_STRICT_LENIENT: The -strict/-lenient flags are no longer
+ supported, since we no longer own the compiler [INCOMPATIBLE, MINIMAL]
+
+
+* NO_PORTING: The -porting flag is no longer supported.
+
+---- Ajdb
+
+* NO_AJDB: Ajdb is no longer supported, shipped, talked about,
+ seen, or believed to exist. We write a nice couple of paragraphs
+ about JSR 45. [INCOMPATIBLE]
+
+
+---- Ajdoc
+
+* NO_AJDOC: Ajdoc is not provided [BETA, possibly but not certainly
+ FINAL as well]
+
+---- ajbrowser
+
+* NO_CROSSCUTTING_STRUCTURE: Crosscutting structure is not shown
+ [BETA_ONLY]
+
+
+------------------------------
+DOWNLOADS: AJDE for Jbuilder, AJDE for Netbeans, AJDE for Emacs
+
+Deliverables: 3 downloads, same as 1.0.6 (Mik, expand?)
+
+Changes:
+
+* NO_AJDE_INCREMENTAL_COMPILATION: the 1.1 compiler will only
+ work in batch mode [BETA_ONLY]
+
+* NO_TARGET_NEAR_SOURCE: -XTargetNearSource option is not supported in
+ the 1.1 command-line compiler. [INCOMPATIBLE]
+
+
+------------------------------
+DOWNLOAD: ajc ant tasks
+
+Deliverables: 1 download, same as 1.0.6
+
+Changes:
+ - adding experimental taskdef based on DefaultCompilerAdapter
+ - updated taskdef to use new compiler interface
+ - neither support incremental mode [XXX leave ant running, touch tag file?]
+
+------------------------------
+DOWNLOAD: Source distributions
+
+Tools Source: completely revamped, includes license for org.eclipse package
+AJDE-JBuilder Source: basically the same, if aspectjtools.jar is one jar
+AJDE-Netbeans Source: basically the same, if aspectjtools.jar is one jar
+
+------------------------------
+DOWNLOAD: Documentation
+
+Deliverable: 1 or 0 downloads. Main deliverable is fleshed-out
+version of this document with outgoing links to bare or updated 1.0.6
+documentation.
+
+Changes (language changes):
+
+* THROWS_PATTERN: Typename patterns are allowed in place of typenames
+ in throws clauses. This is
+ http://aspectj.org/home/hugunin/features11.html#throws-patterns [NEW]
+
+* CALLEE_SIDE_CALLS: 1.1 may pick out different callee-side call join
+ points than 1.0.6 on the same code. [INCOMPATIBLE]
+
+* SINGLE_INTERCLASS_TARGET: 1.1 does not allow inter-class
+ declarations to be made with a TypePattern as target. (workaround
+ available, defense can be presented if asked). [INCOMPATIBLE]
+
+* SINGLE_TYPENAME_PATTERN_TARGET: A simple type-name pattern with no
+ wildcard can match no more than one type. The type that it matches
+ is determined at compile-time. [INCOMPATIBLE]
+ [THIS IS NO LONGER THE CASE, SO IT IS NOT DOCUMENTED AS SUCH]
+
+* ASPECT_PRECEDENCE: Dominates is replaced/mirrored with alternate
+ declare-space specification, or it's not. (??) [INCOMPATIBLE, or
+ NEW, or NOTHING]
+
+* UNAVAILABLE_JOIN_POINTS: [INCOMPATIBLE, MINIMAL]
+ * Initializer Execution join points no longer exist. The
+ information needed to pick them out doesn't exist in bytecode.
+ there was not kinded pcd for it, and we're not sure anyone will
+ actually notice the difference.
+ * Others? (??)
+
+* CONSTRUCTOR_EXECUTION_IS_BIGGER: constructor execution join points
+ (of constructors which call super) include the code for instance
+ initialization (the code inside the old initializer execution join
+ point). Again, the information needed to NOT include this code
+ isn't available in bytecode. This could be a big deal... before
+ advice on many constructor execution join points will run before the
+ dynamic initializers run. [INCOMPATIBLE]
+
+* NEW_PCDS: Kinded PCDs are available for every kind of join
+ point. This is
+ http://aspectj.org/home/hugunin/features11.html#kinded-pcds [NEW]
+ * adviceExecution (spelling?)
+ * preInitialization (spelling?)
+
+* WITHIN_MEMBER_TYPES: Within of a member type (NOT a package-level
+ type) such as within(pkg.Type.MemberType) is not guaranteed to pick
+ out code inside anonymous and local types. (JLS 13.1). If anyone
+ cares, we can do tests on jikes/javac/eclipse to see if we actually
+ do, but this is hopefully a completely minimal issue [INCOMPATIBLE,
+ MINIMAL]. It is unclear if this is a fundamental limitation of
+ bytecode weaving or if it can be fixed with further work.
+
+
+Documentation caveats:
+
+- example code not updated [XXX?]
+- quick ref
+-
+
+------------------------------
+Future work
+
+There are a number of changes that clearly would be either useful or
+easy (hopefully things that are both useful and easy are already
+done), but we don't plan to actually ship them in 1.1.
+
+* HANDLER_EXCLUDES_NON_EXCEPTIONS: (PR826)
+
+* SUPERTYPES_TYPE_PATTERN:
+
+* DYNAMIC_CLASSLOADER_WEAVER:
+
+* SOURCE_WEAVING:
+
+------------------------------
+Shorthand notes
+
+- no optimizations for per* aspects
+
+- declare soft unimplemented [this is on the table for not doing for beta]
+
+- privileged unimplemented [this is on the table for not doing for beta]
+
+- declare dominates (?) [decided before beta]
+
+- declare error/warning source locations are weaker than just missing column [BETA]
+
+
+- a note for the dangerous bends section of the programming guide
+
+ Base.m() throws IOException
+ Derived.m() [no throws]
+
+ call(void Base.m() throws IOException)
+ --> this doesn't match new Derived().m(), but will without the throws
+
+
+- The status of the -XserializableAspects flag is iceberg-like.
+
+- Don't implement intra-type static members onto interfaces
+
+- Don't handle introduced fields with constant values
+
+- no crosscuting structure means no inline annotations w/ -emacssym, but speedbar still
+ shows declaration tree
+
+
diff --git a/weaver/src/.cvsignore b/weaver/src/.cvsignore
new file mode 100644
index 000000000..defacf099
--- /dev/null
+++ b/weaver/src/.cvsignore
@@ -0,0 +1,2 @@
+bcweaver.lst
+bcweaverSrc.lst
diff --git a/weaver/src/org/aspectj/weaver/Advice.java b/weaver/src/org/aspectj/weaver/Advice.java
new file mode 100644
index 000000000..e20627ab0
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/Advice.java
@@ -0,0 +1,243 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.util.*;
+import java.util.List;
+
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.weaver.patterns.*;
+
+public abstract class Advice extends ShadowMunger {
+
+ protected AdviceKind kind;
+ protected Member signature;
+ protected int extraParameterFlags;
+ protected int lexicalPosition;
+
+ // not necessarily declaring aspect, this is a semantics change from 1.0
+ protected ResolvedTypeX 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
+
+ public static Advice makeCflowEntry(World world, Pointcut entry, boolean isBelow, Member stackField, int nFreeVars, List innerCflowEntries) {
+ Advice ret = world.concreteAdvice(isBelow ? AdviceKind.CflowBelowEntry : AdviceKind.CflowEntry,
+ entry, stackField, 0, entry);
+ //0);
+ ret.innerCflowEntries = innerCflowEntries;
+ ret.nFreeVars = nFreeVars;
+ return ret;
+ }
+
+ public static Advice makePerCflowEntry(World world, Pointcut entry, boolean isBelow,
+ Member stackField, ResolvedTypeX inAspect, List innerCflowEntries)
+ {
+ Advice ret = world.concreteAdvice(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,
+ ResolvedTypeX inAspect)
+ {
+ Advice ret = world.concreteAdvice(isThis ? AdviceKind.PerThisEntry : AdviceKind.PerTargetEntry,
+ entry, null, 0, entry);
+
+ ret.concreteAspect = inAspect;
+ return ret;
+ }
+
+ public static Advice makeSoftener(World world, Pointcut entry, TypePattern exceptionType) {
+ Advice ret = world.concreteAdvice(AdviceKind.Softener,
+ entry, null, 0, entry);
+
+ ret.exceptionType = exceptionType;
+ //System.out.println("made ret: " + ret + " with " + exceptionType);
+ return ret;
+ }
+
+
+ public Advice(AdviceKind kind, Pointcut pointcut, Member signature,
+ int extraParameterFlags, int start, int end, ISourceContext sourceContext)
+ {
+ super(pointcut, start, end, sourceContext);
+ this.kind = kind;
+ this.signature = signature;
+ this.extraParameterFlags = extraParameterFlags;
+ this.lexicalPosition = start; //XXX should go away
+ }
+
+
+ public boolean match(Shadow shadow, World world) {
+ if (super.match(shadow, world)) {
+ if (hasExtraParameter() && kind == AdviceKind.AfterReturning) {
+ return getExtraParameterType().isConvertableFrom(shadow.getReturnType(), world);
+ } 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.getMessageHandler().handleMessage(
+ MessageUtil.error("Around on pre-initialization not supported in 1.1",
+ getSourceLocation()));
+ world.getMessageHandler().handleMessage(
+ MessageUtil.error("Around on pre-initialization not supported in 1.1",
+ shadow.getSourceLocation()));
+ return false;
+ } else {
+ if (!getSignature().getReturnType().isConvertableFrom(shadow.getReturnType(), world)) {
+ //System.err.println(this + ", " + sourceContext + ", " + start);
+
+ world.getMessageHandler().handleMessage(
+ MessageUtil.error("incompatible return type applying to " + shadow,
+ getSourceLocation()));
+ //XXX need a crosscutting error message here
+ return false;
+ }
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ // ----
+
+ public AdviceKind getKind() {
+ return kind;
+ }
+
+ public Member getSignature() {
+ return signature;
+ }
+
+ public boolean hasExtraParameter() {
+ return (extraParameterFlags & ExtraArgument) != 0;
+ }
+
+ protected int getExtraParameterCount() {
+ return countOnes(extraParameterFlags & ParameterMask);
+ }
+
+ 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 signature.getParameterTypes().length - getExtraParameterCount();
+ }
+
+ public TypeX getExtraParameterType() {
+ if (!hasExtraParameter()) return ResolvedTypeX.MISSING;
+ return signature.getParameterTypes()[getBaseParameterCount()];
+ }
+
+ public TypeX getDeclaringAspect() {
+ return signature.getDeclaringType();
+ }
+
+ protected String extraParametersToString() {
+ if (extraParameterFlags == 0) {
+ return "";
+ } else {
+ return "(extraFlags: " + extraParameterFlags + ")";
+ }
+ }
+
+ public Pointcut getPointcut() {
+ return pointcut;
+ }
+
+ // ----
+
+ /** @param fromType is guaranteed to be a non-abstract aspect
+ * @param perClause has been concretized at a higher level
+ */
+ public ShadowMunger concretize(ResolvedTypeX fromType, World world, PerClause clause) {
+ // assert !fromType.isAbstract();
+ Pointcut p = pointcut.concretize(fromType, signature.getArity(), this);
+ if (clause != null) {
+ p = new AndPointcut(clause, p);
+ p.state = Pointcut.CONCRETE;
+ }
+
+ Advice munger = world.concreteAdvice(kind, p, signature, extraParameterFlags, start, end, sourceContext);
+ munger.concreteAspect = fromType;
+ //System.err.println("concretizing here " + p + " with clause " + clause);
+ return munger;
+ }
+
+ // ---- from object
+
+ public String toString() {
+ return "("
+ + getKind()
+ + extraParametersToString()
+ + ": "
+ + pointcut
+ + "->"
+ + signature
+ + ")";
+ }
+ public boolean equals(Object other) {
+ if (! (other instanceof Advice)) return false;
+ Advice o = (Advice) other;
+ return o.kind == kind && o.pointcut.equals(pointcut) && o.signature.equals(signature) &&
+ o.extraParameterFlags == extraParameterFlags;
+ }
+ private volatile int hashCode = 0;
+ public int hashCode() {
+ if (hashCode == 0) {
+ int result = 17;
+ result = 37*result + kind.hashCode();
+ result = 37*result + pointcut.hashCode();
+ if (signature != null) result = 37*result + 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;
+
+ public void setLexicalPosition(int lexicalPosition) {
+ this.lexicalPosition = lexicalPosition;
+ }
+
+ public ResolvedTypeX getConcreteAspect() {
+ return concreteAspect;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/AdviceKind.java b/weaver/src/org/aspectj/weaver/AdviceKind.java
new file mode 100644
index 000000000..17e94328c
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/AdviceKind.java
@@ -0,0 +1,110 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+
+import org.aspectj.util.TypeSafeEnum;
+
+/**
+ * The 5 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(DataInputStream 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;
+ }
+ 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);
+
+
+ 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;
+ }
+
+ public boolean isPerObjectEntry() {
+ return this == PerThisEntry || this == PerTargetEntry;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/AjAttribute.java b/weaver/src/org/aspectj/weaver/AjAttribute.java
new file mode 100644
index 000000000..864513371
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/AjAttribute.java
@@ -0,0 +1,411 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+
+import org.aspectj.util.FileUtil;
+import org.aspectj.weaver.patterns.*;
+
+/**
+ * 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(String name, byte[] bytes, ISourceContext context) {
+ try {
+ if (bytes == null) bytes = new byte[0];
+ DataInputStream s = new DataInputStream(new ByteArrayInputStream(bytes));
+ if (name.equals(Aspect.AttributeName)) {
+ return new Aspect(PerClause.readPerClause(s, context));
+ } else if (name.equals(WeaverState.AttributeName)) {
+ return new WeaverState(WeaverStateKind.read(s));
+ } else if (name.equals(AdviceAttribute.AttributeName)) {
+ return AdviceAttribute.read(s, context);
+ } else if (name.equals(PointcutDeclarationAttribute.AttributeName)) {
+ return new PointcutDeclarationAttribute(ResolvedPointcutDefinition.read(s, context));
+ } 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 {
+ throw new BCException("unknown attribute" + name);
+ }
+ } catch (IOException e) {
+ throw new BCException("malformed " + name + " attribute " + 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 ResolvedTypeMunger munger;
+ public TypeMunger(ResolvedTypeMunger munger) {
+ this.munger = munger;
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ munger.write(s);
+ }
+
+ public ConcreteTypeMunger reify(World world, ResolvedTypeX aspectType) {
+ return world.concreteTypeMunger(munger, aspectType);
+ }
+ }
+
+ public static class WeaverState extends AjAttribute {
+ public static final String AttributeName = "org.aspectj.weaver.WeaverState";
+
+ public String getNameString() {
+ return AttributeName;
+ }
+ private WeaverStateKind kind;
+ public WeaverState(WeaverStateKind kind) {
+ this.kind = kind;
+ }
+ public void write(DataOutputStream s) throws IOException {
+ kind.write(s);
+ }
+
+ public WeaverStateKind reify() {
+ return kind;
+ }
+ }
+
+ public static class SourceContextAttribute extends AjAttribute {
+ public static final String AttributeName = "org.aspectj.weaver.SourceContext";
+
+ public String getNameString() {
+ return AttributeName;
+ }
+
+ private String sourceFileName;
+ private 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(s, lineBreaks);
+ }
+
+ public static SourceContextAttribute read(DataInputStream s) throws IOException {
+ return new SourceContextAttribute(s.readUTF(), FileUtil.readIntArray(s));
+ }
+ public int[] getLineBreaks() {
+ return lineBreaks;
+ }
+
+ public String getSourceFileName() {
+ return sourceFileName;
+ }
+ }
+
+ public static class PointcutDeclarationAttribute extends AjAttribute {
+ public static final String AttributeName = "org.aspectj.weaver.PointcutDeclaration";
+
+ public String getNameString() {
+ return AttributeName;
+ }
+
+ private 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 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 AdviceKind kind;
+ private Pointcut pointcut;
+ private int extraArgumentFlags;
+ private int start;
+ private int end;
+ private ISourceContext sourceContext;
+
+ /**
+ * @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;
+ this.extraArgumentFlags = extraArgumentFlags;
+ this.start = start;
+ this.end = end;
+ this.sourceContext = sourceContext;
+ }
+
+ public static AdviceAttribute read(DataInputStream s, ISourceContext context) throws IOException {
+ return new AdviceAttribute(
+ AdviceKind.read(s),
+ 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(extraArgumentFlags);
+ s.writeInt(start);
+ s.writeInt(end);
+ }
+ public Advice reify(Member signature, World world) {
+ return world.concreteAdvice(kind, pointcut, signature, extraArgumentFlags, start, end, sourceContext);
+ }
+
+ public String toString() {
+ return "AdviceAttribute(" + kind + ", " + pointcut + ", " +
+ extraArgumentFlags + ", " + start+")";
+ }
+
+ public int getExtraArgumentFlags() {
+ return extraArgumentFlags;
+ }
+
+ public AdviceKind getKind() {
+ return kind;
+ }
+
+ public Pointcut getPointcut() {
+ return pointcut;
+ }
+
+ }
+
+ public static class Aspect extends AjAttribute {
+ public static final String AttributeName = "org.aspectj.weaver.Aspect";
+ public String getNameString() {
+ return AttributeName;
+ }
+ private PerClause perClause;
+
+ public Aspect(PerClause perClause) {
+ this.perClause = perClause;
+ }
+
+ public PerClause reify(ResolvedTypeX inAspect) {
+ //XXXperClause.concretize(inAspect);
+ return perClause;
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ perClause.write(s);
+ }
+ }
+
+ public static class PrivilegedAttribute extends AjAttribute {
+ public static final String AttributeName = "org.aspectj.weaver.Privileged";
+
+ public String getNameString() {
+ return AttributeName;
+ }
+
+ private ResolvedMember[] accessedMembers;
+ public PrivilegedAttribute(ResolvedMember[] accessedMembers) {
+ this.accessedMembers = accessedMembers;
+ }
+ public void write(DataOutputStream s) throws IOException {
+ s.writeInt(accessedMembers.length);
+ for (int i = 0, len = accessedMembers.length; i < len; i++) {
+ accessedMembers[i].write(s);
+ }
+ }
+
+ public ResolvedMember[] getAccessedMembers() {
+ return accessedMembers;
+ }
+
+ public static PrivilegedAttribute read(DataInputStream s, ISourceContext context) throws IOException {
+ int len = s.readInt();
+ ResolvedMember[] members = new ResolvedMember[len];
+ for (int i=0; i < len; i++) {
+ members[i] = ResolvedMember.readResolvedMember(s, context);
+ }
+ return new PrivilegedAttribute(members);
+ }
+ }
+
+
+ public static class EffectiveSignatureAttribute extends AjAttribute {
+ public static final String AttributeName = "org.aspectj.weaver.EffectiveSignature";
+
+ public String getNameString() {
+ return AttributeName;
+ }
+
+ private ResolvedMember effectiveSignature;
+ private Shadow.Kind shadowKind;
+ private 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(DataInputStream s, ISourceContext context) throws IOException {
+ return new EffectiveSignatureAttribute(
+ ResolvedMember.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/weaver/src/org/aspectj/weaver/AjcMemberMaker.java b/weaver/src/org/aspectj/weaver/AjcMemberMaker.java
new file mode 100644
index 000000000..7996af37f
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/AjcMemberMaker.java
@@ -0,0 +1,508 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+
+
+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 VISIBILITY =
+ Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
+
+ public static final TypeX CFLOW_STACK_TYPE =
+ TypeX.forName(NameMangler.CFLOW_STACK_TYPE);
+ public static final TypeX AROUND_CLOSURE_TYPE =
+ TypeX.forName("org.aspectj.runtime.internal.AroundClosure");
+
+ public static final TypeX CONVERSIONS_TYPE =
+ TypeX.forName("org.aspectj.runtime.internal.Conversions");
+
+ public static final TypeX NO_ASPECT_BOUND_EXCEPTION =
+ TypeX.forName("org.aspectj.lang.NoAspectBoundException");
+
+ public static ResolvedMember ajcClinitMethod(TypeX declaringType) {
+ return new ResolvedMember(
+ Member.METHOD,
+ declaringType,
+ PRIVATE_STATIC,
+ NameMangler.AJC_CLINIT_NAME,
+ "()V");
+ }
+
+ public static Member noAspectBoundExceptionInit() {
+ return new ResolvedMember(
+ Member.METHOD,
+ NO_ASPECT_BOUND_EXCEPTION,
+ Modifier.PUBLIC,
+ "<init>",
+ "()V");
+ }
+
+
+ public static ResolvedMember perCflowPush(TypeX declaringType) {
+ return new ResolvedMember(
+ Member.METHOD,
+ declaringType,
+ PUBLIC_STATIC,
+ NameMangler.PERCFLOW_PUSH_METHOD,
+ "()V");
+ }
+
+ public static ResolvedMember perCflowField(TypeX declaringType) {
+ return new ResolvedMember(
+ Member.FIELD,
+ declaringType,
+ PUBLIC_STATIC_FINAL,
+ NameMangler.PERCFLOW_FIELD_NAME,
+ CFLOW_STACK_TYPE.getSignature());
+ }
+
+ public static ResolvedMember perSingletonField(TypeX declaringType) {
+ return new ResolvedMember(
+ Member.FIELD,
+ declaringType,
+ PUBLIC_STATIC_FINAL,
+ NameMangler.PERSINGLETON_FIELD_NAME,
+ declaringType.getSignature());
+ }
+
+
+ public static ResolvedMember perObjectField(TypeX declaringType, ResolvedTypeX aspectType) {
+ int modifiers = Modifier.PRIVATE;
+ if (!TypeX.SERIALIZABLE.isAssignableFrom(aspectType, aspectType.getWorld())) {
+ modifiers |= Modifier.TRANSIENT;
+ }
+ return new ResolvedMember(
+ Member.FIELD,
+ declaringType,
+ modifiers,
+ aspectType,
+ NameMangler.perObjectInterfaceField(aspectType),
+ TypeX.NONE);
+ }
+
+
+ public static ResolvedMember perObjectBind(TypeX declaringType) {
+ return new ResolvedMember(
+ Member.METHOD,
+ declaringType,
+ PUBLIC_STATIC,
+ NameMangler.PEROBJECT_BIND_METHOD,
+ "(Ljava/lang/Object;)V");
+ }
+
+
+ public static TypeX perObjectInterfaceType(TypeX aspectType) {
+ return TypeX.forName(aspectType.getName()+"$ajcMightHaveAspect");
+ }
+
+ public static ResolvedMember perObjectInterfaceGet(TypeX aspectType) {
+ return new ResolvedMember(
+ Member.METHOD,
+ perObjectInterfaceType(aspectType),
+ Modifier.PUBLIC | Modifier.ABSTRACT,
+ NameMangler.perObjectInterfaceGet(aspectType),
+ "()" + aspectType.getSignature());
+ }
+
+ public static ResolvedMember perObjectInterfaceSet(TypeX aspectType) {
+ return new ResolvedMember(
+ Member.METHOD,
+ perObjectInterfaceType(aspectType),
+ Modifier.PUBLIC | Modifier.ABSTRACT,
+ NameMangler.perObjectInterfaceSet(aspectType),
+ "(" + aspectType.getSignature() + ")V");
+ }
+
+
+
+
+ public static ResolvedMember perSingletonAspectOfMethod(TypeX declaringType) {
+ return new ResolvedMember(Member.METHOD,
+ declaringType, PUBLIC_STATIC, "aspectOf",
+ "()" + declaringType.getSignature());
+ }
+
+ public static ResolvedMember perSingletonHasAspectMethod(TypeX declaringType) {
+ return new ResolvedMember(Member.METHOD,
+ declaringType, PUBLIC_STATIC, "hasAspect",
+ "()Z");
+ };
+
+ public static ResolvedMember perCflowAspectOfMethod(TypeX declaringType) {
+ return perSingletonAspectOfMethod(declaringType);
+ }
+
+ public static ResolvedMember perCflowHasAspectMethod(TypeX declaringType) {
+ return perSingletonHasAspectMethod(declaringType);
+ };
+
+ public static ResolvedMember perObjectAspectOfMethod(TypeX declaringType) {
+ return new ResolvedMember(Member.METHOD,
+ declaringType, PUBLIC_STATIC, "aspectOf",
+ "(Ljava/lang/Object;)" + declaringType.getSignature());
+ }
+
+ public static ResolvedMember perObjectHasAspectMethod(TypeX declaringType) {
+ return new ResolvedMember(Member.METHOD,
+ declaringType, PUBLIC_STATIC, "hasAspect",
+ "(Ljava/lang/Object;)Z");
+ };
+
+ // -- privileged accessors
+
+ public static ResolvedMember privilegedAccessMethodForMethod(TypeX aspectType, ResolvedMember method) {
+ String sig;
+ sig = method.getSignature();
+ return new ResolvedMember(Member.METHOD,
+ method.getDeclaringType(),
+ Modifier.PUBLIC | (method.isStatic() ? Modifier.STATIC : 0),
+ NameMangler.privilegedAccessMethodForMethod(method.getName(),
+ method.getDeclaringType(), aspectType),
+ sig);
+ //XXX needs thrown exceptions to be correct
+ }
+
+ public static ResolvedMember privilegedAccessMethodForFieldGet(TypeX aspectType, Member field) {
+ String sig;
+ if (field.isStatic()) {
+ sig = "()" + field.getSignature();
+ } else {
+ sig = "(" + field.getDeclaringType().getSignature() + ")" + field.getSignature();
+ }
+
+ return new ResolvedMember(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(TypeX aspectType, Member field) {
+ String sig;
+ if (field.isStatic()) {
+ sig = "(" + field.getSignature() + ")V";
+ } else {
+ sig = "(" + field.getDeclaringType().getSignature() + field.getSignature() + ")V";
+ }
+
+ return new ResolvedMember(Member.METHOD,
+ field.getDeclaringType(),
+ PUBLIC_STATIC, //Modifier.PUBLIC | (field.isStatic() ? Modifier.STATIC : 0),
+ NameMangler.privilegedAccessMethodForFieldSet(field.getName(),
+ field.getDeclaringType(), aspectType),
+ sig);
+ }
+
+
+
+ // --- runtimeLibrary api stuff
+
+ public static Member cflowStackPeekInstance() {
+ return new Member(
+ Member.METHOD,
+ CFLOW_STACK_TYPE,
+ 0,
+ "peekInstance",
+ "()Ljava/lang/Object;");
+ }
+
+ public static Member cflowStackPushInstance() {
+ return new Member(
+ Member.METHOD,
+ CFLOW_STACK_TYPE,
+ 0,
+ "pushInstance",
+ "(Ljava/lang/Object;)V");
+ }
+
+ public static Member cflowStackIsValid() {
+ return new Member(
+ Member.METHOD,
+ CFLOW_STACK_TYPE,
+ 0,
+ "isValid",
+ "()Z");
+ }
+ public static Member cflowStackInit() {
+ return new Member(
+ Member.CONSTRUCTOR,
+ CFLOW_STACK_TYPE,
+ 0,
+ "<init>",
+ "()V");
+ }
+ public static Member aroundClosurePreInitializationField() {
+ return new Member(
+ Member.FIELD,
+ AROUND_CLOSURE_TYPE,
+ 0,
+ "preInitializationState",
+ "[Ljava/lang/Object;");
+ }
+ public static Member aroundClosurePreInitializationGetter() {
+ return new Member(
+ Member.METHOD,
+ AROUND_CLOSURE_TYPE,
+ 0,
+ "getPreInitializationState",
+ "()[Ljava/lang/Object;");
+ }
+
+
+ public static ResolvedMember preIntroducedConstructor(
+ TypeX aspectType,
+ TypeX targetType,
+ TypeX[] paramTypes)
+ {
+ return new ResolvedMember(
+ Member.METHOD,
+ aspectType,
+ PUBLIC_STATIC_FINAL,
+ TypeX.OBJECTARRAY,
+ NameMangler.preIntroducedConstructor(aspectType, targetType),
+ paramTypes);
+ }
+
+ public static ResolvedMember postIntroducedConstructor(
+ TypeX aspectType,
+ TypeX targetType,
+ TypeX[] paramTypes)
+ {
+ return new ResolvedMember(
+ Member.METHOD,
+ aspectType,
+ PUBLIC_STATIC_FINAL,
+ ResolvedTypeX.VOID,
+ NameMangler.postIntroducedConstructor(aspectType, targetType),
+ TypeX.insert(targetType, paramTypes));
+ }
+
+ public static ResolvedMember interConstructor(ResolvedTypeX targetType, ResolvedMember constructor, TypeX aspectType) {
+//
+// ResolvedTypeX targetType,
+// TypeX[] argTypes,
+// int modifiers)
+// {
+ ResolvedMember ret =
+ new ResolvedMember(
+ Member.CONSTRUCTOR,
+ targetType,
+ Modifier.PUBLIC,
+ ResolvedTypeX.VOID,
+ "<init>",
+ constructor.getParameterTypes());
+ //System.out.println("ret: " + ret + " mods: " + Modifier.toString(modifiers));
+ if (Modifier.isPublic(constructor.getModifiers()))
+ return ret;
+ int i = 0;
+ while (true) {
+ ret = addCookieTo(ret, aspectType);
+ if (targetType.lookupMemberNoSupers(ret) == null)
+ return ret;
+ }
+ }
+
+ public static ResolvedMember interFieldInitializer(ResolvedMember field, TypeX aspectType) {
+ return new ResolvedMember(Member.METHOD, aspectType, PUBLIC_STATIC,
+ NameMangler.interFieldInitializer(aspectType, field.getDeclaringType(), field.getName()),
+ field.isStatic() ? "()V" : "(" + field.getDeclaringType().getSignature() + ")V"
+ );
+ }
+
+
+
+ private static int makePublic(int modifiers) {
+ return (modifiers & ~VISIBILITY) | Modifier.PUBLIC;
+ }
+
+
+ /**
+ * This static method goes on the aspect that declares the inter-type field
+ */
+ public static ResolvedMember interFieldSetDispatcher(ResolvedMember field, TypeX aspectType) {
+ return new ResolvedMember(Member.METHOD, aspectType, PUBLIC_STATIC,
+ ResolvedTypeX.VOID,
+ NameMangler.interFieldSetDispatcher(aspectType, field.getDeclaringType(), field.getName()),
+ field.isStatic() ? new TypeX[] {field.getReturnType()}
+ : new TypeX[] {field.getDeclaringType(), field.getReturnType()}
+ );
+ }
+
+ /**
+ * This static method goes on the aspect that declares the inter-type field
+ */
+ public static ResolvedMember interFieldGetDispatcher(ResolvedMember field, TypeX aspectType) {
+ return new ResolvedMember(Member.METHOD, aspectType, PUBLIC_STATIC,
+ field.getReturnType(),
+ NameMangler.interFieldGetDispatcher(aspectType, field.getDeclaringType(), field.getName()),
+ field.isStatic() ? TypeX.NONE : new TypeX[] {field.getDeclaringType()}
+ );
+ }
+
+ /**
+ * This field goes on the class the field
+ * is declared onto
+ */
+ public static ResolvedMember interFieldClassField(ResolvedMember field, TypeX aspectType) {
+ return new ResolvedMember(Member.FIELD, field.getDeclaringType(), makePublic(field.getModifiers()),
+ field.getReturnType(),
+ NameMangler.interFieldClassField(field.getModifiers(), aspectType, field.getDeclaringType(), field.getName()),
+ TypeX.NONE
+ );
+ }
+
+
+ /**
+ * This field goes on top-most implementers of the interface the field
+ * is declared onto
+ */
+ public static ResolvedMember interFieldInterfaceField(ResolvedMember field, TypeX onClass, TypeX aspectType) {
+ return new ResolvedMember(Member.FIELD, onClass, Modifier.PUBLIC,
+ field.getReturnType(),
+ NameMangler.interFieldInterfaceField(aspectType, field.getDeclaringType(), field.getName()),
+ TypeX.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, ResolvedTypeX onType, TypeX aspectType) {
+ int modifiers = Modifier.PUBLIC;
+ if (onType.isInterface()) modifiers |= Modifier.ABSTRACT;
+ return new ResolvedMember(Member.METHOD, onType, modifiers,
+ ResolvedTypeX.VOID,
+ NameMangler.interFieldInterfaceSetter(aspectType, field.getDeclaringType(), field.getName()),
+ new TypeX[] {field.getReturnType()}
+ );
+ }
+
+ /**
+ * 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, ResolvedTypeX onType, TypeX aspectType) {
+ int modifiers = Modifier.PUBLIC;
+ if (onType.isInterface()) modifiers |= Modifier.ABSTRACT;
+ return new ResolvedMember(Member.METHOD, onType, modifiers,
+ field.getReturnType(),
+ NameMangler.interFieldInterfaceGetter(aspectType, field.getDeclaringType(), field.getName()),
+ TypeX.NONE
+ );
+ }
+
+
+
+
+ /**
+ * 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 ResolvedMember interMethod(ResolvedMember meth, TypeX aspectType, boolean onInterface)
+ {
+ if (Modifier.isPublic(meth.getModifiers()) && !onInterface) return meth;
+
+ int modifiers = makePublic(meth.getModifiers());
+ if (onInterface) modifiers |= Modifier.ABSTRACT;
+
+ return new ResolvedMember(Member.METHOD, meth.getDeclaringType(),
+ modifiers,
+ meth.getReturnType(),
+ NameMangler.interMethod(meth.getModifiers(), aspectType, meth.getDeclaringType(), meth.getName()),
+ meth.getParameterTypes());
+ }
+
+ /**
+ * This static method goes on the declaring aspect of the inter-type method.
+ */
+ public static ResolvedMember interMethodDispatcher(ResolvedMember meth, TypeX aspectType)
+ {
+ TypeX[] paramTypes = meth.getParameterTypes();
+ if (!meth.isStatic()) {
+ paramTypes = TypeX.insert(meth.getDeclaringType(), paramTypes);
+ }
+
+ return new ResolvedMember(Member.METHOD, aspectType, PUBLIC_STATIC,
+ meth.getReturnType(),
+ NameMangler.interMethodDispatcher(aspectType, meth.getDeclaringType(), meth.getName()),
+ paramTypes);
+ }
+
+ /**
+ * This static method goes on the declaring aspect of the inter-type method.
+ */
+ public static ResolvedMember interMethodBody(ResolvedMember meth, TypeX aspectType)
+ {
+ TypeX[] paramTypes = meth.getParameterTypes();
+ if (!meth.isStatic()) {
+ paramTypes = TypeX.insert(meth.getDeclaringType(), paramTypes);
+ }
+
+ return new ResolvedMember(Member.METHOD, aspectType, PUBLIC_STATIC,
+ meth.getReturnType(),
+ NameMangler.interMethodBody(aspectType, meth.getDeclaringType(), meth.getName()),
+ paramTypes);
+ }
+
+
+
+
+ private static ResolvedMember addCookieTo(ResolvedMember ret, TypeX aspectType) {
+ TypeX[] params = ret.getParameterTypes();
+
+ TypeX[] freshParams = TypeX.add(params, aspectType);
+ return new ResolvedMember(
+ ret.getKind(),
+ ret.getDeclaringType(),
+ ret.getModifiers(),
+ ret.getReturnType(),
+ ret.getName(),
+ freshParams);
+ }
+
+ public static ResolvedMember toObjectConversionMethod(TypeX fromType) {
+ if (fromType.isPrimitive()) {
+ String name = fromType.toString() + "Object";
+ return new ResolvedMember(
+ Member.METHOD,
+ CONVERSIONS_TYPE,
+ PUBLIC_STATIC,
+ TypeX.OBJECT,
+ name,
+ new TypeX[] { fromType });
+ } else {
+ return null;
+ }
+ }
+ public static Member interfaceConstructor(ResolvedTypeX resolvedTypeX) {
+ return new ResolvedMember(
+ Member.CONSTRUCTOR,
+ resolvedTypeX,
+ Modifier.PUBLIC,
+ "<init>",
+ "()V");
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/AsmAdaptor.java b/weaver/src/org/aspectj/weaver/AsmAdaptor.java
new file mode 100644
index 000000000..6830ab2bb
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/AsmAdaptor.java
@@ -0,0 +1,157 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.util.*;
+import java.util.Iterator;
+
+import org.aspectj.asm.*;
+import org.aspectj.asm.StructureModel;
+import org.aspectj.bridge.*;
+import org.aspectj.bridge.SourceLocation;
+
+public class AsmAdaptor {
+ public static void noteMunger(StructureModel model, Shadow shadow, ShadowMunger munger) {
+ if (munger instanceof Advice) {
+ Advice a = (Advice)munger;
+ if (a.getKind().isPerEntry() || a.getKind().isCflow()) {
+ // ??? might want to show these in the future
+ return;
+ }
+
+// System.out.println("--------------------------");
+ ProgramElementNode targetNode = getNode(model, shadow);
+ ProgramElementNode adviceNode = getNode(model, a);
+// System.out.println("> target: " + targetNode + ", advice: " + adviceNode);
+ createAppropriateLinks(targetNode, adviceNode);
+ }
+ }
+
+ private static void createAppropriateLinks(
+ ProgramElementNode target,
+ ProgramElementNode advice)
+ {
+ if (target == null || advice == null) return;
+ addLink(target, new LinkNode(advice), org.aspectj.asm.AdviceAssociation.METHOD_RELATION, true);
+ addLink(advice, new LinkNode(target), org.aspectj.asm.AdviceAssociation.METHOD_RELATION, false);
+// System.out.println(">> added target: " + target + ", advice: " + advice);
+ }
+
+ private static void addLink(
+ ProgramElementNode onNode,
+ LinkNode linkNode,
+ Relation relation,
+ boolean isBack)
+ {
+ RelationNode node = null;
+ String relationName = isBack ? relation.getBackNavigationName() : relation.getForwardNavigationName();
+
+ //System.err.println("on: " + onNode + " relationName: " + relationName + " existin: " + onNode.getRelations());
+
+ for (Iterator i = onNode.getRelations().iterator(); i.hasNext();) {
+ RelationNode relationNode = (RelationNode) i.next();
+ if (relationName.equals(relationNode.getName())) {
+ node = relationNode;
+ break;
+ }
+ }
+ if (node == null) {
+ node = new RelationNode(relation, relationName, new ArrayList());
+ onNode.getRelations().add(node);
+ }
+ node.getChildren().add(linkNode);
+
+ }
+
+ private static ProgramElementNode getNode(StructureModel model, Advice a) {
+ //ResolvedTypeX inAspect = a.getConcreteAspect();
+ Member member = a.getSignature();
+ return lookupMember(model, member);
+ }
+
+ private static ProgramElementNode getNode(StructureModel model, Shadow shadow) {
+ Member enclosingMember = shadow.getEnclosingCodeSignature();
+
+ ProgramElementNode enclosingNode = lookupMember(model, enclosingMember);
+
+ Member shadowSig = shadow.getSignature();
+ if (!shadowSig.equals(enclosingMember)) {
+ ProgramElementNode bodyNode = findOrCreateBodyNode(enclosingNode, shadowSig, shadow);
+ return bodyNode;
+ } else {
+ return enclosingNode;
+ }
+ }
+
+ private static ProgramElementNode findOrCreateBodyNode(
+ ProgramElementNode enclosingNode,
+ Member shadowSig, Shadow shadow)
+ {
+ for (Iterator it = enclosingNode.getChildren().iterator(); it.hasNext(); ) {
+ ProgramElementNode node = (ProgramElementNode)it.next();
+ if (shadowSig.getName().equals(node.getBytecodeName()) &&
+ shadowSig.getSignature().equals(node.getBytecodeSignature()))
+ {
+ return node;
+ }
+ }
+
+ ISourceLocation sl = shadow.getSourceLocation();
+
+ ProgramElementNode peNode = new ProgramElementNode(
+ shadow.toString(),
+ ProgramElementNode.Kind.CODE,
+ new SourceLocation(enclosingNode.getSourceLocation().getSourceFile(), sl.getLine()),
+ 0,
+ "",
+ new ArrayList());
+
+ System.err.println(peNode.getSourceLocation());
+ peNode.setBytecodeName(shadowSig.getName());
+ peNode.setBytecodeSignature(shadowSig.getSignature());
+ enclosingNode.addChild(peNode);
+ return peNode;
+ }
+
+
+
+
+
+ public static ProgramElementNode lookupMember(StructureModel model, Member member) {
+ TypeX declaringType = member.getDeclaringType();
+ ProgramElementNode classNode =
+ model.findNodeForClass(declaringType.getPackageName(), declaringType.getClassName());
+ return findMemberInClass(classNode, member);
+ }
+
+ private static ProgramElementNode findMemberInClass(
+ ProgramElementNode classNode,
+ Member member)
+ {
+ if (classNode == null) return null; // XXX remove this check
+ for (Iterator it = classNode.getChildren().iterator(); it.hasNext(); ) {
+ ProgramElementNode node = (ProgramElementNode)it.next();
+ if (member.getName().equals(node.getBytecodeName()) &&
+ member.getSignature().equals(node.getBytecodeSignature()))
+ {
+ return node;
+ }
+ }
+ return null;
+ }
+
+
+
+
+}
diff --git a/weaver/src/org/aspectj/weaver/BCException.java b/weaver/src/org/aspectj/weaver/BCException.java
new file mode 100644
index 000000000..35ec52780
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/BCException.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+/**
+ * Exception to use inside the bcweaver.
+ */
+public class BCException extends RuntimeException {
+
+ public BCException() {
+ super();
+ }
+
+ public BCException(String s) {
+ super(s);
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/BetaException.java b/weaver/src/org/aspectj/weaver/BetaException.java
new file mode 100644
index 000000000..9cf85fceb
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/BetaException.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+/**
+ * Exception to use inside the bcweaver.
+ */
+public class BetaException extends RuntimeException {
+
+ public BetaException() {
+ super();
+ }
+
+ public BetaException(String s) {
+ super(s);
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/Checker.java b/weaver/src/org/aspectj/weaver/Checker.java
new file mode 100644
index 000000000..eec7d05af
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/Checker.java
@@ -0,0 +1,61 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import org.aspectj.weaver.patterns.*;
+import org.aspectj.weaver.patterns.PerClause;
+import org.aspectj.bridge.*;
+
+
+public class Checker extends ShadowMunger {
+
+ private String msg;
+ private boolean isError;
+
+ public Checker(DeclareErrorOrWarning deow) {
+ super(deow.getPointcut(), deow.getStart(), deow.getEnd(), deow.getSourceContext());
+ this.msg = deow.getMessage();
+ this.isError = deow.isError();
+ }
+
+ public ShadowMunger concretize(ResolvedTypeX fromType, World world, PerClause clause) {
+ pointcut = pointcut.concretize(fromType, 0);
+ return this;
+ }
+
+ public void specializeOn(Shadow shadow) {
+ throw new RuntimeException("illegal state");
+ }
+
+ public void implementOn(Shadow shadow) {
+ throw new RuntimeException("illegal state");
+ }
+
+ public boolean match(Shadow shadow, World world) {
+ if (super.match(shadow, world)) {
+ world.getMessageHandler().handleMessage(
+ new Message(msg,
+ isError ? IMessage.ERROR : IMessage.WARNING,
+ null,
+ shadow.getSourceLocation()));
+ }
+ return false;
+ }
+
+
+ public int compareTo(Object other) {
+ return 0;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java b/weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java
new file mode 100644
index 000000000..9f55b28e9
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java
@@ -0,0 +1,76 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.util.PartialOrder;
+
+public abstract class ConcreteTypeMunger implements PartialOrder.PartialComparable {
+ protected ResolvedTypeMunger munger;
+ protected ResolvedTypeX aspectType;
+
+ public ConcreteTypeMunger(ResolvedTypeMunger munger, ResolvedTypeX aspectType) {
+ this.munger = munger;
+ this.aspectType = aspectType;
+ }
+
+ //public abstract boolean munge(LazyClassGen gen);
+
+ public ResolvedTypeMunger getMunger() {
+ return munger;
+ }
+
+ public ResolvedTypeX getAspectType() {
+ return aspectType;
+ }
+
+ public ResolvedMember getSignature() {
+ return munger.getSignature();
+ }
+
+ public ISourceLocation getSourceLocation() {
+ return null; //XXX
+ }
+
+ public boolean matches(ResolvedTypeX onType) {
+ if (munger == null) throw new RuntimeException("huh: " + this);
+ return munger.matches(onType);
+ }
+
+ public ResolvedMember getMatchingSyntheticMember(Member member) {
+ return munger.getMatchingSyntheticMember(member, aspectType);
+ }
+
+ public int compareTo(Object other) {
+ ConcreteTypeMunger o = (ConcreteTypeMunger) other;
+
+ ResolvedTypeX 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;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/CrosscuttingMembers.java b/weaver/src/org/aspectj/weaver/CrosscuttingMembers.java
new file mode 100644
index 000000000..8635cdaf6
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/CrosscuttingMembers.java
@@ -0,0 +1,201 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.util.*;
+
+import org.aspectj.weaver.patterns.*;
+import org.aspectj.weaver.patterns.PerClause;
+import org.aspectj.bridge.*;
+
+
+/**
+ * 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.
+ */
+
+public class CrosscuttingMembers {
+ private ResolvedTypeX inAspect;
+ private World world;
+
+ private PerClause perClause;
+
+ private List shadowMungers = new ArrayList(4);
+ private List typeMungers = new ArrayList(4);
+
+ private List declareParents = new ArrayList(4);
+ private List declareSofts = new ArrayList(0);
+ private List declareDominates = new ArrayList(4);
+
+
+ public CrosscuttingMembers(ResolvedTypeX inAspect) {
+ this.inAspect = inAspect;
+ this.world = inAspect.getWorld();
+ }
+
+// 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) return; //???
+ typeMungers.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);
+ addShadowMunger(m);
+ } else if (declare instanceof DeclareDominates) {
+ declareDominates.add(declare);
+ } else if (declare instanceof DeclareParents) {
+ declareParents.add(declare);
+ } else if (declare instanceof DeclareSoft) {
+ DeclareSoft d = (DeclareSoft)declare;
+ Pointcut concretePointcut = d.getPointcut().concretize(inAspect, 0);
+ declareSofts.add(new DeclareSoft(d.getException(), concretePointcut));
+ ShadowMunger m = Advice.makeSoftener(world, concretePointcut, d.getException());
+ addConcreteShadowMunger(m);
+ } else {
+ throw new RuntimeException("unimplemented");
+ }
+ }
+
+ 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.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;
+ }
+
+ public boolean replaceWith(CrosscuttingMembers other) {
+ boolean changed = false;
+ if (!perClause.equals(other.perClause)) {
+ changed = true;
+ perClause = other.perClause;
+ }
+
+ //XXX all of the below should be set equality rather than list equality
+ if (!shadowMungers.equals(other.shadowMungers)) {
+ changed = true;
+ shadowMungers = other.shadowMungers;
+ }
+
+ if (!typeMungers.equals(other.typeMungers)) {
+ changed = true;
+ typeMungers = other.typeMungers;
+ }
+
+ 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;
+ }
+
+ return changed;
+ }
+
+ public PerClause getPerClause() {
+ return perClause;
+ }
+
+ public void setPerClause(PerClause perClause) {
+ this.perClause = perClause.concretize(inAspect);
+ }
+
+ 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;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/CrosscuttingMembersSet.java b/weaver/src/org/aspectj/weaver/CrosscuttingMembersSet.java
new file mode 100644
index 000000000..ceebbfeb6
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/CrosscuttingMembersSet.java
@@ -0,0 +1,140 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.util.*;
+
+import org.aspectj.weaver.patterns.*;
+import org.aspectj.weaver.patterns.PerClause;
+import org.aspectj.bridge.*;
+
+
+/**
+ * This holds on to all CrosscuttingMembers for a world. It handles
+ * management of change.
+ */
+
+public class CrosscuttingMembersSet {
+ private World world;
+ private Map members = new HashMap();
+
+ private List shadowMungers = null;
+ private List typeMungers = null;
+ private List declareSofts = null;
+ private List declareParents = null;
+ private List declareDominates = null;
+
+ public CrosscuttingMembersSet(World world) {
+ this.world = world;
+ }
+
+ /**
+ * @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(ResolvedTypeX aspectType) {
+ CrosscuttingMembers xcut = (CrosscuttingMembers)members.get(aspectType);
+ if (xcut == null) {
+ members.put(aspectType, aspectType.collectCrosscuttingMembers());
+ clearCaches();
+ return true;
+ } else {
+ if (xcut.replaceWith(aspectType.collectCrosscuttingMembers())) {
+ clearCaches();
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public void deleteAspect(TypeX aspectType) {
+ members.remove(aspectType);
+ clearCaches();
+ }
+
+ //XXX only for testing
+ public void addFixedCrosscuttingMembers(ResolvedTypeX aspectType) {
+ members.put(aspectType, aspectType.crosscuttingMembers);
+ clearCaches();
+ }
+
+
+ private void clearCaches() {
+ shadowMungers = null;
+ typeMungers = null;
+ declareSofts = null;
+ declareParents = 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 getDeclareSofts() {
+ if (declareSofts == null) {
+ ArrayList ret = new ArrayList();
+ for (Iterator i = members.values().iterator(); i.hasNext(); ) {
+ ret.addAll(((CrosscuttingMembers)i.next()).getDeclareSofts());
+ }
+ declareSofts = ret;
+ }
+ return declareSofts;
+ }
+
+ public List getDeclareParents() {
+ if (declareParents == null) {
+ ArrayList ret = new ArrayList();
+ for (Iterator i = members.values().iterator(); i.hasNext(); ) {
+ ret.addAll(((CrosscuttingMembers)i.next()).getDeclareParents());
+ }
+ declareParents = ret;
+ }
+ return declareParents;
+ }
+
+ 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;
+ }
+
+
+
+}
diff --git a/weaver/src/org/aspectj/weaver/IClassWeaver.java b/weaver/src/org/aspectj/weaver/IClassWeaver.java
new file mode 100644
index 000000000..3dd152e8d
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/IClassWeaver.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/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/weaver/src/org/aspectj/weaver/IHasPosition.java b/weaver/src/org/aspectj/weaver/IHasPosition.java
new file mode 100644
index 000000000..8fb5688a7
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/IHasPosition.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/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/weaver/src/org/aspectj/weaver/IHasSourceLocation.java b/weaver/src/org/aspectj/weaver/IHasSourceLocation.java
new file mode 100644
index 000000000..2ca7a01c8
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/IHasSourceLocation.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import org.aspectj.bridge.ISourceLocation;
+
+public interface IHasSourceLocation extends IHasPosition {
+ ISourceContext getSourceContext();
+ ISourceLocation getSourceLocation();
+}
diff --git a/weaver/src/org/aspectj/weaver/ISourceContext.java b/weaver/src/org/aspectj/weaver/ISourceContext.java
new file mode 100644
index 000000000..c5cf2620f
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ISourceContext.java
@@ -0,0 +1,20 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import org.aspectj.bridge.ISourceLocation;
+
+public interface ISourceContext {
+ public ISourceLocation makeSourceLocation(IHasPosition position);
+}
diff --git a/weaver/src/org/aspectj/weaver/IWeaver.java b/weaver/src/org/aspectj/weaver/IWeaver.java
new file mode 100644
index 000000000..4c38424ac
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/IWeaver.java
@@ -0,0 +1,24 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+/**
+ * A weaver is given all the aspects it will weave. It should create an appropriate kind of
+ * IWorld. It then should be given a bunch of classes (types with implementation), creates an
+ * appropriate IClassWeaver for each such class, and weaves. The IWeaver is responsible for
+ * IO.
+ */
+public interface IWeaver {
+
+}
diff --git a/weaver/src/org/aspectj/weaver/IntMap.java b/weaver/src/org/aspectj/weaver/IntMap.java
new file mode 100644
index 000000000..712a64637
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/IntMap.java
@@ -0,0 +1,134 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.util.*;
+
+public class IntMap {
+ public static final IntMap EMPTY = new IntMap(0) {
+ public boolean directlyInAdvice() { return true; }
+ public Advice getEnclosingAdvice() { return null; } //XXX possible
+ };
+
+
+ // XXX begin hack to avoid a signature refactoring in Pointcut
+ private Advice 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 peekEnclosingDefinitition() {
+ return (ResolvedPointcutDefinition)enclosingDefinition.get(enclosingDefinition.size()-1);
+ }
+
+
+ public boolean directlyInAdvice() {
+ return enclosingDefinition.isEmpty();
+ }
+
+ public Advice getEnclosingAdvice() {
+ return enclosingAdvice;
+ }
+
+ public void setEnclosingAdvice(Advice advice) {
+ this.enclosingAdvice = advice;
+ }
+
+ public Member getAdviceSignature() {
+ return getEnclosingAdvice().signature;
+ }
+
+ public void copyContext(IntMap bindings) {
+ this.enclosingAdvice = bindings.enclosingAdvice;
+ this.enclosingDefinition = bindings.enclosingDefinition;
+ }
+
+ // 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/weaver/src/org/aspectj/weaver/Iterators.java b/weaver/src/org/aspectj/weaver/Iterators.java
new file mode 100644
index 000000000..2685ba92f
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/Iterators.java
@@ -0,0 +1,215 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.util.*;
+
+public final class Iterators {
+
+ /**
+ * Private constructor, nobody should ever make one of these
+ */
+ private Iterators() {
+ super();
+ }
+
+ /**
+ * 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.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(); }
+ };
+ }
+ /** creates an empty iterator.
+ */
+ public static final Iterator EMPTY = new Iterator() {
+ public boolean hasNext() { return false; }
+ public Object next() { throw new NoSuchElementException(); }
+ public void remove() { throw new UnsupportedOperationException(); }
+ };
+}
diff --git a/weaver/src/org/aspectj/weaver/Lint.java b/weaver/src/org/aspectj/weaver/Lint.java
new file mode 100644
index 000000000..82135a1df
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/Lint.java
@@ -0,0 +1,141 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+import java.io.File;
+import java.text.MessageFormat;
+import java.util.*;
+
+import org.aspectj.bridge.*;
+import org.aspectj.bridge.IMessage.Kind;
+
+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 Lint(World world) {
+ this.world = world;
+ }
+
+
+ public void setAll(String messageKind) {
+ setAll(getMessageKind(messageKind));
+ }
+
+ 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) {
+ try {
+ InputStream s = new FileInputStream(file);
+ setFromProperties(s);
+ } catch (IOException ioe) {
+ MessageUtil.error(world.getMessageHandler(), "problem loading Xlint properties file: " +
+ file.getPath() + ", " + ioe.getMessage());
+ }
+ }
+
+ public void loadDefaultProperties() {
+ InputStream s = getClass().getResourceAsStream("XlintDefault.properties");
+ if (s == null) {
+ MessageUtil.warn(world.getMessageHandler(), "couldn't load XlintDefault.properties");
+ return;
+ }
+ try {
+ setFromProperties(s);
+ } catch (IOException ioe) {
+ MessageUtil.error(world.getMessageHandler(), "problem loading XlintDefault.properties, " +
+ 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(), "invalid Xlint key: " + entry.getKey());
+ } else {
+ kind.setKind(getMessageKind((String)entry.getValue()));
+ }
+ }
+ }
+
+ 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(),
+ "invalid Xlint message kind (must be one of ignore, warning, error): " + v);
+ return null;
+ }
+
+
+
+ public class Kind {
+ private String name;
+ private String message;
+ private IMessage.Kind kind = IMessage.WARNING;
+ public Kind(String name, String message) {
+ this.name = name;
+ this.message = message;
+ kinds.put(this.name, this);
+ }
+
+ public boolean isEnabled() {
+ return kind != null;
+ }
+
+ 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 Message(text, kind, null, location));
+ }
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/Member.java b/weaver/src/org/aspectj/weaver/Member.java
new file mode 100644
index 000000000..284454fdf
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/Member.java
@@ -0,0 +1,745 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import org.aspectj.util.TypeSafeEnum;
+
+public class Member implements Comparable {
+
+ private final Kind kind;
+ private final TypeX declaringType;
+ protected final int modifiers; // protected because ResolvedMember uses it
+ private final TypeX returnType;
+ private final String name;
+ private final TypeX[] parameterTypes;
+ private final String signature;
+
+ public Member(
+ Kind kind,
+ TypeX 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 = TypeX.forSignature(signature);
+ this.parameterTypes = TypeX.NONE;
+ } else {
+ Object[] returnAndParams = signatureToTypes(signature);
+ this.returnType = (TypeX) returnAndParams[0];
+ this.parameterTypes = (TypeX[]) returnAndParams[1];
+ }
+ }
+
+ public Member(
+ Kind kind,
+ TypeX declaringType,
+ int modifiers,
+ TypeX returnType,
+ String name,
+ TypeX[] parameterTypes)
+ {
+ super();
+ this.kind = kind;
+ this.declaringType = declaringType;
+ this.modifiers = modifiers;
+ this.returnType = returnType;
+ this.name = name;
+ this.parameterTypes = parameterTypes;
+ if (kind == FIELD) {
+ this.signature = returnType.getSignature();
+ } else {
+ this.signature = typesToSignature(returnType, parameterTypes);
+ }
+ }
+
+ public ResolvedMember resolve(World world) {
+ return world.resolve(this);
+ }
+
+ // ---- utility methods
+
+ /** returns an Object[] pair of TypeX, TypeX[] 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>
+ * TypeX.signatureToTypes("()[Z")[0].equals(Type.forSignature("[Z"))
+ * TypeX.signatureToTypes("(JJ)I")[1]
+ * .equals(TypeX.forSignatures(new String[] {"J", "J"}))
+ * </pre></blockquote>
+ *
+ * @param signature the JVM bytecode method signature string we want to break apart
+ * @return a pair of TypeX, TypeX[] representing the return types and parameter types.
+ */
+ public static String typesToSignature(TypeX returnType, TypeX[] paramTypes) {
+ StringBuffer buf = new StringBuffer();
+ buf.append("(");
+ for (int i = 0, len = paramTypes.length; i < len; i++) {
+ buf.append(paramTypes[i].getSignature());
+ }
+ buf.append(")");
+ buf.append(returnType.getSignature());
+ return buf.toString();
+ }
+
+ /** returns an Object[] pair of TypeX, TypeX[] 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>
+ * TypeX.signatureToTypes("()[Z")[0].equals(Type.forSignature("[Z"))
+ * TypeX.signatureToTypes("(JJ)I")[1]
+ * .equals(TypeX.forSignatures(new String[] {"J", "J"}))
+ * </pre></blockquote>
+ *
+ * @param signature the JVM bytecode method signature string we want to break apart
+ * @return a pair of TypeX, TypeX[] representing the return types and parameter types.
+ */
+ private static Object[] signatureToTypes(String sig) {
+ List l = new ArrayList();
+ int i = 1;
+ while (true) {
+ char c = sig.charAt(i);
+ if (c == ')') break;
+ int start = i;
+ while (c == '[') c = sig.charAt(++i);
+ if (c == 'L') {
+ i = sig.indexOf(';', start) + 1;
+ l.add(TypeX.forSignature(sig.substring(start, i)));
+ } else {
+ l.add(TypeX.forSignature(sig.substring(start, ++i)));
+ }
+ }
+ TypeX[] paramTypes = (TypeX[]) l.toArray(new TypeX[l.size()]);
+ TypeX returnType = TypeX.forSignature(sig.substring(i+1, sig.length()));
+ return new Object[] { returnType, paramTypes };
+ }
+
+ // ---- factory methods
+ public static Member field(String declaring, int mods, String name, String signature) {
+ return field(declaring, mods, TypeX.forSignature(signature), name);
+ }
+ public static Member field(TypeX declaring, int mods, String name, TypeX type) {
+ return new Member(FIELD, declaring, mods, type, name, TypeX.NONE);
+ }
+ public static Member method(TypeX declaring, int mods, String name, String signature) {
+ Object[] pair = signatureToTypes(signature);
+ return method(declaring, mods, (TypeX) pair[0], name, (TypeX[]) pair[1]);
+ }
+ public static Member pointcut(TypeX declaring, String name, String signature) {
+ Object[] pair = signatureToTypes(signature);
+ return pointcut(declaring, 0, (TypeX) pair[0], name, (TypeX[]) pair[1]);
+ }
+
+
+ private static Member field(String declaring, int mods, TypeX ty, String name) {
+ return new Member(
+ FIELD,
+ TypeX.forName(declaring),
+ mods,
+ ty,
+ name,
+ TypeX.NONE);
+ }
+
+ public static Member method(TypeX declTy, int mods, TypeX rTy, String name, TypeX[] paramTys) {
+ return new Member(
+ //??? this calls <clinit> a method
+ name.equals("<init>") ? CONSTRUCTOR : METHOD,
+ declTy,
+ mods,
+ rTy,
+ name,
+ paramTys);
+ }
+ private static Member pointcut(TypeX declTy, int mods, TypeX rTy, String name, TypeX[] paramTys) {
+ return new Member(
+ POINTCUT,
+ declTy,
+ mods,
+ rTy,
+ name,
+ paramTys);
+ }
+
+ public static Member makeExceptionHandlerSignature(TypeX inType, TypeX catchType) {
+ return new Member(
+ HANDLER,
+ inType,
+ Modifier.STATIC,
+ "<catch>",
+ "(" + catchType.getSignature() + ")V");
+ }
+
+ // ---- parsing methods
+
+ /** Takes a string in this form:
+ *
+ * <blockquote><pre>
+ * static? TypeName TypeName.Id
+ * </pre></blockquote>
+ * Pretty much just for testing, and as such should perhaps be moved.
+ */
+
+ public static Member fieldFromString(String str) {
+ str = str.trim();
+ final int len = str.length();
+ int i = 0;
+ int mods = 0;
+ if (str.startsWith("static", i)) {
+ mods = Modifier.STATIC;
+ i += 6;
+ while (Character.isWhitespace(str.charAt(i))) i++;
+ }
+ int start = i;
+ while (! Character.isWhitespace(str.charAt(i))) i++;
+ TypeX retTy = TypeX.forName(str.substring(start, i));
+
+ start = i;
+ i = str.lastIndexOf('.');
+ TypeX declaringTy = TypeX.forName(str.substring(start, i).trim());
+ start = ++i;
+ String name = str.substring(start, len).trim();
+ return new Member(
+ FIELD,
+ declaringTy,
+ mods,
+ retTy,
+ name,
+ TypeX.NONE);
+ }
+
+ /** Takes a string in this form:
+ *
+ * <blockquote><pre>
+ * (static|interface|private)? TypeName TypeName . Id ( TypeName , ...)
+ * </pre></blockquote>
+ * Pretty much just for testing, and as such should perhaps be moved.
+ */
+
+ public static Member methodFromString(String str) {
+ str = str.trim();
+ final int len = str.length();
+ int i = 0;
+
+ int mods = 0;
+ if (str.startsWith("static", i)) {
+ mods = Modifier.STATIC;
+ i += 6;
+ } else if (str.startsWith("interface", i)) {
+ mods = Modifier.INTERFACE;
+ i += 9;
+ } else if (str.startsWith("private", i)) {
+ mods = Modifier.PRIVATE;
+ i += 7;
+ }
+ while (Character.isWhitespace(str.charAt(i))) i++;
+
+ int start = i;
+ while (! Character.isWhitespace(str.charAt(i))) i++;
+ TypeX returnTy = TypeX.forName(str.substring(start, i));
+
+ start = i;
+ i = str.indexOf('(', i);
+ i = str.lastIndexOf('.', i);
+ TypeX declaringTy = TypeX.forName(str.substring(start, i).trim());
+
+ start = ++i;
+ i = str.indexOf('(', i);
+ String name = str.substring(start, i).trim();
+ start = ++i;
+ i = str.indexOf(')', i);
+
+ String[] paramTypeNames = parseIds(str.substring(start, i).trim());
+
+ return method(declaringTy, mods, returnTy, name, TypeX.forNames(paramTypeNames));
+ }
+
+ private static String[] parseIds(String str) {
+ if (str.length() == 0) return ZERO_STRINGS;
+ List l = new ArrayList();
+ int start = 0;
+ while (true) {
+ int i = str.indexOf(',', start);
+ if (i == -1) {
+ l.add(str.substring(start).trim());
+ break;
+ }
+ l.add(str.substring(start, i).trim());
+ start = i+1;
+ }
+ return (String[]) l.toArray(new String[l.size()]);
+ }
+
+ private static final String[] ZERO_STRINGS = new String[0];
+
+ // ---- things we know without resolution
+
+ public boolean equals(Object other) {
+ if (! (other instanceof Member)) return false;
+ Member o = (Member) other;
+
+ return (kind == o.kind
+ && name.equals(o.name)
+ && signature.equals(o.signature)
+ && declaringType.equals(o.declaringType));
+ }
+
+ 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());
+ }
+
+ /**
+ * 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 + kind.hashCode();
+ result = 37*result + name.hashCode();
+ result = 37*result + signature.hashCode();
+ result = 37*result + declaringType.hashCode();
+ hashCode = result;
+ }
+ return hashCode;
+ }
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append(returnType);
+ buf.append(' ');
+ buf.append(declaringType);
+ 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]);
+ }
+ }
+ buf.append(")");
+ }
+ return buf.toString();
+ }
+
+ public String toLongString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append(kind);
+ buf.append(' ');
+ if (modifiers != 0) {
+ buf.append(Modifier.toString(modifiers));
+ buf.append(' ');
+ }
+ buf.append(toString());
+ buf.append(" <");
+ buf.append(signature);
+ buf.append(" >");
+ return buf.toString();
+ }
+
+ public Kind getKind() { return kind; }
+ public TypeX getDeclaringType() { return declaringType; }
+ public TypeX getReturnType() { return returnType; }
+ public TypeX getType() { return returnType; }
+ public String getName() { return name; }
+ public TypeX[] getParameterTypes() { return parameterTypes; }
+ public String getSignature() { return signature; }
+ public int getArity() { return parameterTypes.length; }
+
+ 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(TypeX[] a, TypeX[] 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;
+ }
+
+ // ---- things we know only with resolution
+
+ public int getModifiers(World world) {
+ return world.getModifiers(this);
+ }
+
+ public TypeX[] getExceptions(World world) {
+ return world.getExceptions(this);
+ }
+
+ public final boolean isProtected(World world) {
+ return Modifier.isProtected(world.getModifiers(this));
+ }
+ public final boolean isStatic(World world) {
+ return Modifier.isStatic(world.getModifiers(this));
+ }
+ public final boolean isStrict(World world) {
+ return Modifier.isStrict(world.getModifiers(this));
+ }
+
+ public final boolean isStatic() {
+ return Modifier.isStatic(modifiers);
+ }
+
+ public final boolean isInterface() {
+ return Modifier.isInterface(modifiers); // this is kinda weird
+ }
+
+ public final boolean isPrivate() {
+ return Modifier.isPrivate(modifiers);
+ }
+
+ public final int getCallsiteModifiers() {
+ return modifiers & ~ Modifier.INTERFACE;
+ }
+
+ public final String getExtractableName() {
+ if (name.equals("<init>")) return "init$";
+ else if (name.equals("<clinit>")) return "clinit$";
+ else return name;
+ }
+
+ // ---- fields 'n' stuff
+
+ public static final Member[] NONE = new Member[0];
+
+ public static class Kind extends TypeSafeEnum {
+ public 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 METHOD;
+ case 2: return FIELD;
+ case 3: return CONSTRUCTOR;
+ case 4: return STATIC_INITIALIZATION;
+ case 5: return POINTCUT;
+ case 6: return ADVICE;
+ case 7: return HANDLER;
+ }
+ throw new BCException("weird kind " + key);
+ }
+ }
+
+ public static final Kind METHOD = new Kind("METHOD", 1);
+ public static final Kind FIELD = new Kind("FIELD", 2);
+ public static final Kind CONSTRUCTOR = new Kind("CONSTRUCTOR", 3);
+ public static final Kind STATIC_INITIALIZATION = new Kind("STATIC_INITIALIZATION", 4);
+ public static final Kind POINTCUT = new Kind("POINTCUT", 5);
+ public static final Kind ADVICE = new Kind("ADVICE", 6);
+ public static final Kind HANDLER = new Kind("HANDLER", 7);
+
+
+
+
+ public Collection/*ResolvedTypeX*/ getDeclaringTypes(World world) {
+ ResolvedTypeX 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, ResolvedTypeX curr) {
+ if (acc.contains(curr)) return true;
+
+ boolean b = false;
+ for (Iterator i = curr.getDirectSupertypes(); i.hasNext(); ) {
+ b |= walkUp(acc, (ResolvedTypeX)i.next());
+ }
+
+ if (!b) {
+ b = curr.lookupMemberNoSupers(this) != null;
+ }
+ if (b) acc.add(curr);
+ return b;
+ }
+
+ private boolean walkUpStatic(Collection acc, ResolvedTypeX curr) {
+ if (curr.lookupMemberNoSupers(this) != null) {
+ acc.add(curr);
+ return true;
+ } else {
+ boolean b = false;
+ for (Iterator i = curr.getDirectSupertypes(); i.hasNext(); ) {
+ b |= walkUp(acc, (ResolvedTypeX)i.next());
+ }
+ if (b) acc.add(curr);
+ return b;
+ }
+ }
+
+ // ---- reflective thisJoinPoint stuff
+ public String getSignatureMakerName() {
+ Kind kind = getKind();
+ if (kind == METHOD) {
+ return "makeMethodSig";
+ } else if (kind == CONSTRUCTOR) {
+ return "makeConstructorSig";
+ } else if (kind == FIELD) {
+ return "makeFieldSig";
+ } else if (kind == HANDLER) {
+ return "makeCatchClauseSig";
+ } else if (kind == STATIC_INITIALIZATION) {
+ return "makeInitializerSig";
+ } else if (kind == ADVICE) {
+ return "makeAdviceSig";
+ } else {
+ throw new RuntimeException("unimplemented");
+ }
+ }
+
+
+
+
+ public String getSignatureType() {
+ Kind kind = getKind();
+ if (kind == METHOD) {
+ return "org.aspectj.lang.reflect.MethodSignature";
+ } else if (kind == CONSTRUCTOR) {
+ return "org.aspectj.lang.reflect.ConstructorSignature";
+ } else if (kind == FIELD) {
+ return "org.aspectj.lang.reflect.FieldSignature";
+ } else if (kind == HANDLER) {
+ return "org.aspectj.lang.reflect.CatchClauseSignature";
+ } else if (kind == STATIC_INITIALIZATION) {
+ return "org.aspectj.lang.reflect.InitializerSignature";
+ } else if (kind == ADVICE) {
+ return "org.aspectj.lang.reflect.AdviceSignature";
+ } else {
+ throw new RuntimeException("unimplemented");
+ }
+ }
+
+ public String getSignatureString(World world) {
+ Kind kind = getKind();
+ if (kind == METHOD) {
+ return getMethodSignatureString(world);
+ } else if (kind == CONSTRUCTOR) {
+ return getConstructorSignatureString(world);
+ } else if (kind == FIELD) {
+ return getFieldSignatureString(world);
+ } else if (kind == HANDLER) {
+ return getHandlerSignatureString(world);
+ } else if (kind == STATIC_INITIALIZATION) {
+ return getStaticInitializationSignatureString(world);
+ } else if (kind == ADVICE) {
+ return getAdviceSignatureString(world);
+ } else {
+ throw new RuntimeException("unimplemented");
+ }
+ }
+
+ private String getHandlerSignatureString(World world) {
+ StringBuffer buf = new StringBuffer();
+ buf.append(makeString(0));
+ buf.append('-');
+ //buf.append(getName());
+ buf.append('-');
+ buf.append(makeString(getDeclaringType()));
+ buf.append('-');
+ buf.append(makeString(getParameterTypes()[0]));
+ buf.append('-');
+ //XXX we don't actually try to find the handler parameter name
+ //XXX it probably wouldn't be too hard
+ String pName = "<missing>";
+ //String[] pNames = getParameterNames(world);
+ //if (pNames != null) pName = pNames[0];
+ buf.append(pName);
+ buf.append('-');
+ return buf.toString();
+ }
+
+ private String getStaticInitializationSignatureString(World world) {
+ StringBuffer buf = new StringBuffer();
+ buf.append(makeString(getModifiers(world)));
+ buf.append('-');
+ //buf.append(getName());
+ buf.append('-');
+ buf.append(makeString(getDeclaringType()));
+ buf.append('-');
+ return buf.toString();
+ }
+
+
+
+ protected String getAdviceSignatureString(World world) {
+ StringBuffer buf = new StringBuffer();
+ buf.append(makeString(getModifiers(world)));
+ buf.append('-');
+ buf.append(getName());
+ buf.append('-');
+ buf.append(makeString(getDeclaringType()));
+ buf.append('-');
+ buf.append(makeString(getParameterTypes()));
+ buf.append('-');
+ buf.append(makeString(getParameterNames(world)));
+ buf.append('-');
+ buf.append(makeString(getExceptions(world)));
+ buf.append('-');
+ buf.append(makeString(getReturnType()));
+ buf.append('-');
+ return buf.toString();
+ }
+
+
+ protected String getMethodSignatureString(World world) {
+ StringBuffer buf = new StringBuffer();
+ buf.append(makeString(getModifiers(world)));
+ buf.append('-');
+ buf.append(getName());
+ buf.append('-');
+ buf.append(makeString(getDeclaringType()));
+ buf.append('-');
+ buf.append(makeString(getParameterTypes()));
+ buf.append('-');
+ buf.append(makeString(getParameterNames(world)));
+ buf.append('-');
+ buf.append(makeString(getExceptions(world)));
+ buf.append('-');
+ buf.append(makeString(getReturnType()));
+ buf.append('-');
+ return buf.toString();
+ }
+
+
+
+ protected String getConstructorSignatureString(World world) {
+ StringBuffer buf = new StringBuffer();
+ buf.append(makeString(getModifiers(world)));
+ buf.append('-');
+ buf.append('-');
+ buf.append(makeString(getDeclaringType()));
+ buf.append('-');
+ buf.append(makeString(getParameterTypes()));
+ buf.append('-');
+ buf.append(makeString(getParameterNames(world)));
+ buf.append('-');
+ buf.append(makeString(getExceptions(world)));
+ buf.append('-');
+ return buf.toString();
+ }
+
+
+
+
+ protected String getFieldSignatureString(World world) {
+ StringBuffer buf = new StringBuffer();
+ buf.append(makeString(getModifiers(world)));
+ buf.append('-');
+ buf.append(getName());
+ buf.append('-');
+ buf.append(makeString(getDeclaringType()));
+ buf.append('-');
+ buf.append(makeString(getReturnType()));
+ buf.append('-');
+ return buf.toString();
+ }
+
+ protected String makeString(int i) {
+ return Integer.toString(i, 16); //??? expensive
+ }
+
+
+
+
+ protected String makeString(TypeX t) {
+ // this is the inverse of the odd behavior for Class.forName w/ arrays
+ if (t.isArray()) {
+ return t.getSignature();
+ } else {
+ return t.getName();
+ }
+ }
+
+
+
+ protected String makeString(TypeX[] 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 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();
+ }
+
+ public String[] getParameterNames(World world) {
+ return world.getParameterNames(this);
+ }
+
+
+
+
+
+
+ // ----
+
+
+
+
+
+
+
+
+
+
+}
+
diff --git a/weaver/src/org/aspectj/weaver/NameMangler.java b/weaver/src/org/aspectj/weaver/NameMangler.java
new file mode 100644
index 000000000..69a3271fa
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/NameMangler.java
@@ -0,0 +1,300 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.weaver.bcel.BcelObjectType;
+
+public class NameMangler {
+ private NameMangler() {
+ throw new RuntimeException("static");
+ }
+
+ public static final String PREFIX = "ajc$";
+
+
+ public static final String CFLOW_STACK_TYPE = "org.aspectj.runtime.internal.CFlowStack";
+ 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";
+
+ public static final String AJC_CLINIT_NAME = PREFIX + "clinit";
+
+
+
+ public static String perObjectInterfaceGet(TypeX aspectType) {
+ return makeName(aspectType.getNameAsIdentifier(), "perObjectGet");
+ }
+
+ public static String perObjectInterfaceSet(TypeX aspectType) {
+ return makeName(aspectType.getNameAsIdentifier(), "perObjectSet");
+ }
+
+ public static String perObjectInterfaceField(TypeX aspectType) {
+ return makeName(aspectType.getNameAsIdentifier(), "perObjectField");
+ }
+
+
+
+ public static String privilegedAccessMethodForMethod(String name, TypeX objectType, TypeX aspectType) {
+ return makeName("privMethod", aspectType.getNameAsIdentifier(),
+ objectType.getNameAsIdentifier(), name);
+ }
+
+ public static String privilegedAccessMethodForFieldGet(String name, TypeX objectType, TypeX aspectType) {
+ return makeName("privFieldGet", aspectType.getNameAsIdentifier(),
+ objectType.getNameAsIdentifier(), name);
+ }
+
+ public static String privilegedAccessMethodForFieldSet(String name, TypeX objectType, TypeX aspectType) {
+ return makeName("privFieldSet", aspectType.getNameAsIdentifier(),
+ objectType.getNameAsIdentifier(), name);
+ }
+
+
+
+ /**
+ * The name of methods corresponding to advice declarations
+ */
+ public static String adviceName(TypeX aspectType, AdviceKind kind, int position) {
+ return makeName(kind.getName(), aspectType.getNameAsIdentifier(),
+ Integer.toHexString(position));
+ }
+
+ /**
+ * This field goes on top-most implementers of the interface the field
+ * is declared onto
+ */
+ public static String interFieldInterfaceField(TypeX aspectType, TypeX 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(TypeX aspectType, TypeX 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(TypeX aspectType, TypeX 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(TypeX aspectType, TypeX 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(TypeX aspectType, TypeX 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, TypeX aspectType, TypeX 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(TypeX aspectType, TypeX 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(TypeX aspectType, TypeX 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(TypeX aspectType, TypeX 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, TypeX aspectType, TypeX 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(TypeX aspectType, TypeX 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(TypeX aspectType, TypeX 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(
+ TypeX aspectType,
+ TypeX 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(
+ TypeX aspectType,
+ TypeX targetType)
+ {
+ return makeName("postInterConstructor", aspectType.getNameAsIdentifier(),
+ targetType.getNameAsIdentifier());
+ }
+ // ----
+
+ /**
+ * This static method goes on the declaring aspect of the inter-type method.
+ */
+ public static String superDispatcher(TypeX classType, String name)
+ {
+ return makeName("superDispatch",
+ classType.getNameAsIdentifier(), name);
+ }
+
+ // ----
+
+ private static TypeX getOutermostType(TypeX type) {
+ TypeX outerType = type.getDeclaringType();
+ if (outerType == null) return type;
+ return getOutermostType(outerType);
+ }
+
+
+ private static String makeVisibilityName(int modifiers, TypeX aspectType) {
+ if (Modifier.isPrivate(modifiers)) {
+ return getOutermostType(aspectType).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 makeClosureClassName(
+ BcelObjectType enclosingType,
+ int index)
+ {
+ return enclosingType.getName() + "$AjcClosure" + index;
+ }
+
+ public static String aroundCallbackMethodName(
+ Member shadowSig,
+ LazyClassGen enclosingType)
+ {
+ String ret =
+ shadowSig.getExtractableName()
+ + "_aroundBody"
+ + enclosingType.getNewGeneratedNameTag();
+ return ret;
+ }
+
+ public static String proceedMethodName(String adviceMethodName) {
+ return adviceMethodName + "proceed";
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java b/weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java
new file mode 100644
index 000000000..5940d4789
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java
@@ -0,0 +1,78 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+import java.util.Set;
+
+import org.aspectj.weaver.ResolvedTypeMunger.Kind;
+
+public class NewConstructorTypeMunger extends ResolvedTypeMunger {
+ private ResolvedMember syntheticConstructor;
+ private ResolvedMember explicitConstructor;
+
+
+ public NewConstructorTypeMunger(
+ ResolvedMember signature,
+ ResolvedMember syntheticConstructor,
+ ResolvedMember explicitConstructor,
+ Set superMethodsCalled)
+ {
+ super(Constructor, signature);
+ this.syntheticConstructor = syntheticConstructor;
+ this.explicitConstructor = explicitConstructor;
+ this.setSuperMethodsCalled(superMethodsCalled);
+
+ }
+
+ //XXX horrible name clash here
+ public ResolvedMember getDispatchMethod(TypeX 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);
+ }
+
+ public static ResolvedTypeMunger readConstructor(DataInputStream s, ISourceContext context) throws IOException {
+ return new NewConstructorTypeMunger(
+ ResolvedMember.readResolvedMember(s, context),
+ ResolvedMember.readResolvedMember(s, context),
+ ResolvedMember.readResolvedMember(s, context),
+ readSuperMethodsCalled(s));
+ }
+
+ public ResolvedMember getExplicitConstructor() {
+ return explicitConstructor;
+ }
+
+ public ResolvedMember getSyntheticConstructor() {
+ return syntheticConstructor;
+ }
+
+ public void setExplicitConstructor(ResolvedMember explicitConstructor) {
+ this.explicitConstructor = explicitConstructor;
+ }
+
+ public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedTypeX aspectType) {
+ ResolvedMember ret = getSyntheticConstructor();
+ if (ResolvedTypeX.matches(ret, member)) return getSignature();
+ return null;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java b/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java
new file mode 100644
index 000000000..f30db0970
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java
@@ -0,0 +1,43 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.Set;
+
+import org.aspectj.weaver.ResolvedTypeMunger.Kind;
+
+public class NewFieldTypeMunger extends ResolvedTypeMunger {
+ public NewFieldTypeMunger(ResolvedMember signature, Set superMethodsCalled) {
+ super(Field, signature);
+ this.setSuperMethodsCalled(superMethodsCalled);
+ }
+
+ public ResolvedMember getInitMethod(TypeX aspectType) {
+ return AjcMemberMaker.interFieldInitializer(signature, aspectType);
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ kind.write(s);
+ signature.write(s);
+ writeSuperMethodsCalled(s);
+ }
+
+ public static ResolvedTypeMunger readField(DataInputStream s, ISourceContext context) throws IOException {
+ return new NewFieldTypeMunger(
+ ResolvedMember.readResolvedMember(s, context),
+ readSuperMethodsCalled(s));
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java b/weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java
new file mode 100644
index 000000000..32d77aea6
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+import java.util.Set;
+
+import org.aspectj.weaver.ResolvedTypeMunger.Kind;
+
+public class NewMethodTypeMunger extends ResolvedTypeMunger {
+ public NewMethodTypeMunger(
+ ResolvedMember signature,
+ Set superMethodsCalled)
+ {
+ super(Method, signature);
+ this.setSuperMethodsCalled(superMethodsCalled);
+
+ }
+
+ //XXX horrible name clash here
+ public ResolvedMember getDispatchMethod(TypeX aspectType) {
+ return AjcMemberMaker.interMethodBody(signature, aspectType);
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ kind.write(s);
+ signature.write(s);
+ writeSuperMethodsCalled(s);
+ }
+
+ public static ResolvedTypeMunger readMethod(DataInputStream s, ISourceContext context) throws IOException {
+ return new NewMethodTypeMunger(
+ ResolvedMember.readResolvedMember(s, context),
+ readSuperMethodsCalled(s));
+ }
+
+ public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedTypeX aspectType) {
+ ResolvedMember ret = AjcMemberMaker.interMethodDispatcher(getSignature(), aspectType);
+ if (ResolvedTypeX.matches(ret, member)) return getSignature();
+ return null;
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/PerObjectInterfaceTypeMunger.java b/weaver/src/org/aspectj/weaver/PerObjectInterfaceTypeMunger.java
new file mode 100644
index 000000000..7f5096882
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/PerObjectInterfaceTypeMunger.java
@@ -0,0 +1,68 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+import java.util.Set;
+
+import org.aspectj.weaver.ResolvedTypeMunger.Kind;
+import org.aspectj.weaver.patterns.Pointcut;
+
+public class PerObjectInterfaceTypeMunger extends ResolvedTypeMunger {
+ private ResolvedMember getMethod;
+ private ResolvedMember setMethod;
+ private TypeX aspectType;
+ private TypeX interfaceType;
+ private Pointcut testPointcut;
+
+
+ public PerObjectInterfaceTypeMunger(TypeX aspectType, Pointcut testPointcut) {
+ super(PerObjectInterface, null);
+ this.aspectType = aspectType;
+ this.testPointcut = testPointcut;
+ this.interfaceType = AjcMemberMaker.perObjectInterfaceType(aspectType);
+ this.getMethod = AjcMemberMaker.perObjectInterfaceGet(aspectType);
+ this.setMethod = AjcMemberMaker.perObjectInterfaceSet(aspectType);
+ }
+
+
+ public void write(DataOutputStream s) throws IOException {
+ throw new RuntimeException("shouldn't be serialized");
+ }
+ public TypeX getAspectType() {
+ return aspectType;
+ }
+
+ public ResolvedMember getGetMethod() {
+ return getMethod;
+ }
+
+ public TypeX getInterfaceType() {
+ return interfaceType;
+ }
+
+ public ResolvedMember getSetMethod() {
+ return setMethod;
+ }
+
+ public Pointcut getTestPointcut() {
+ return testPointcut;
+ }
+
+ public boolean matches(ResolvedTypeX matchType) {
+ //??? this matches many more types than are needed
+ return !matchType.isInterface();
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/PrivilegedAccessMunger.java b/weaver/src/org/aspectj/weaver/PrivilegedAccessMunger.java
new file mode 100644
index 000000000..c957a5656
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/PrivilegedAccessMunger.java
@@ -0,0 +1,36 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+import java.util.Set;
+
+import org.aspectj.weaver.ResolvedTypeMunger.Kind;
+import org.aspectj.weaver.patterns.Pointcut;
+
+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();
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/ResolvedMember.java b/weaver/src/org/aspectj/weaver/ResolvedMember.java
new file mode 100644
index 000000000..e7d007cde
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ResolvedMember.java
@@ -0,0 +1,156 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+
+import org.aspectj.bridge.ISourceLocation;
+
+/**
+ * This is the declared member, i.e. it will always correspond to an
+ * actual method/... declaration
+ */
+public class ResolvedMember extends Member implements IHasPosition {
+
+ protected String[] parameterNames = null;
+ protected TypeX[] checkedExceptions = TypeX.NONE;
+
+
+ // these three fields hold the source location of this member
+ protected int start, end;
+ protected ISourceContext sourceContext = null;
+
+ // ----
+
+ public ResolvedMember(
+ Kind kind,
+ TypeX declaringType,
+ int modifiers,
+ TypeX returnType,
+ String name,
+ TypeX[] parameterTypes)
+ {
+ super(kind, declaringType, modifiers, returnType, name, parameterTypes);
+ }
+
+ public ResolvedMember(
+ Kind kind,
+ TypeX declaringType,
+ int modifiers,
+ String name,
+ String signature)
+ {
+ super(kind, declaringType, modifiers, name, signature);
+ }
+
+ public static final ResolvedMember[] NONE = new ResolvedMember[0];
+
+ // ----
+
+ public final int getModifiers(World world) {
+ return modifiers;
+ }
+ public final int getModifiers() {
+ return modifiers;
+ }
+
+ // ----
+
+
+ public final TypeX[] getExceptions(World world) {
+ return getExceptions();
+ }
+
+ public TypeX[] getExceptions() {
+ return checkedExceptions;
+ }
+
+ public ShadowMunger getAssociatedShadowMunger() {
+ return null;
+ }
+
+ // ??? true or false?
+ public boolean isAjSynthetic() {
+ return true;
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ getKind().write(s);
+ getDeclaringType().write(s);
+ s.writeInt(modifiers);
+ s.writeUTF(getName());
+ s.writeUTF(getSignature());
+ TypeX.write(getExceptions(), s);
+
+ s.writeInt(getStart());
+ s.writeInt(getEnd());
+
+ }
+
+ public static ResolvedMember readResolvedMember(DataInputStream s, ISourceContext sourceContext) throws IOException {
+ ResolvedMember m = new ResolvedMember(Kind.read(s), TypeX.read(s), s.readInt(), s.readUTF(), s.readUTF());
+ m.checkedExceptions = TypeX.readArray(s);
+ m.start = s.readInt();
+ m.end = s.readInt();
+ m.sourceContext = sourceContext;
+ return m;
+ }
+
+ public ResolvedMember resolve(World world) {
+ return this;
+ }
+
+ public ISourceContext getSourceContext(World world) {
+ return getDeclaringType().resolve(world).getSourceContext();
+ }
+
+ public final String[] getParameterNames() {
+ return parameterNames;
+ }
+ 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 (sourceContext == null) {
+ //System.err.println("no context: " + this);
+ return null;
+ }
+ return sourceContext.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;
+ }
+
+}
+
diff --git a/weaver/src/org/aspectj/weaver/ResolvedPointcutDefinition.java b/weaver/src/org/aspectj/weaver/ResolvedPointcutDefinition.java
new file mode 100644
index 000000000..8c38d6a99
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ResolvedPointcutDefinition.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+
+import org.aspectj.weaver.patterns.Pointcut;
+
+
+public class ResolvedPointcutDefinition extends ResolvedMember {
+ private Pointcut pointcut;
+
+ public ResolvedPointcutDefinition(
+ TypeX declaringType,
+ int modifiers,
+ String name,
+ TypeX[] parameterTypes,
+ Pointcut pointcut)
+ {
+ super(
+ POINTCUT,
+ declaringType,
+ modifiers,
+ ResolvedTypeX.VOID,
+ name,
+ parameterTypes);
+ this.pointcut = pointcut;
+ //XXXpointcut.assertState(Pointcut.RESOLVED);
+ checkedExceptions = TypeX.NONE;
+ }
+
+ // ----
+
+ public void write(DataOutputStream s) throws IOException {
+ getDeclaringType().write(s);
+ s.writeInt(getModifiers());
+ s.writeUTF(getName());
+ TypeX.write(getParameterTypes(), s);
+ pointcut.write(s);
+ }
+
+ public static ResolvedPointcutDefinition read(DataInputStream s, ISourceContext context) throws IOException {
+ return new ResolvedPointcutDefinition(
+ TypeX.read(s),
+ s.readInt(),
+ s.readUTF(),
+ TypeX.readArray(s),
+ Pointcut.read(s, context));
+ }
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("poincut ");
+ 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;
+ }
+
+ // for testing
+ public static final ResolvedPointcutDefinition DUMMY =
+ new ResolvedPointcutDefinition(TypeX.OBJECT, 0, "missing",
+ TypeX.NONE, Pointcut.makeMatchesNothing(Pointcut.RESOLVED));
+
+
+}
diff --git a/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java
new file mode 100644
index 000000000..27c0435b7
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java
@@ -0,0 +1,162 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+import java.util.*;
+import java.util.Set;
+
+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;
+
+ private Set /* resolvedMembers */ superMethodsCalled = Collections.EMPTY_SET;
+
+ public ResolvedTypeMunger(Kind kind, ResolvedMember signature) {
+ this.kind = kind;
+ this.signature = signature;
+ }
+
+ // ----
+
+ // fromType is guaranteed to be a non-abstract aspect
+ public ConcreteTypeMunger concretize(World world, ResolvedTypeX aspectType) {
+ ConcreteTypeMunger munger = world.concreteTypeMunger(this, aspectType);
+ return munger;
+ }
+
+
+ public boolean matches(ResolvedTypeX matchType) {
+ ResolvedTypeX onType = matchType.getWorld().resolve(signature.getDeclaringType());
+ if (matchType.equals(onType)) return true;
+
+ if (onType.isInterface()) {
+ return matchType.isTopmostImplementor(onType);
+ } else {
+ return false;
+ }
+ }
+
+ // ----
+
+ public String toString() {
+ return "ResolvedTypeMunger(" + getKind() + ", " + getSignature() +")";
+ //.superMethodsCalled + ")";
+ }
+
+ // ----
+
+ public static ResolvedTypeMunger read(DataInputStream 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 {
+ throw new RuntimeException("unimplemented");
+ }
+ }
+
+ protected static Set readSuperMethodsCalled(DataInputStream s) throws IOException {
+ Set ret = new HashSet();
+ int n = s.readInt();
+ for (int i=0; i < n; i++) {
+ ret.add(ResolvedMember.readResolvedMember(s, null));
+ }
+ return ret;
+ }
+
+ protected void writeSuperMethodsCalled(DataOutputStream s) throws IOException {
+ if (superMethodsCalled == null) {
+ 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);
+ }
+ }
+
+
+ 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;
+ }
+ throw new BCException("bad kind: " + key);
+ }
+ }
+
+ // ---- 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 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, ResolvedTypeX aspectType) {
+ return null;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/ResolvedTypeX.java b/weaver/src/org/aspectj/weaver/ResolvedTypeX.java
new file mode 100644
index 000000000..b23dbe58f
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ResolvedTypeX.java
@@ -0,0 +1,975 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.weaver.bcel.BcelObjectType;
+import org.aspectj.weaver.patterns.*;
+import org.aspectj.weaver.patterns.PerClause;
+
+public abstract class ResolvedTypeX extends TypeX {
+
+ protected World world;
+
+ ResolvedTypeX(String signature, World world) {
+ super(signature);
+ this.world = world;
+ }
+
+ // ---- things that don't require a world
+
+
+ /** returns Iterator&lt;ResolvedTypeX&gt;
+ */
+ public final Iterator getDirectSupertypes() {
+ Iterator ifacesIterator = Iterators.array(getDeclaredInterfaces());
+ ResolvedTypeX superclass = getSuperclass();
+ if (superclass == null) {
+ return ifacesIterator;
+ } else {
+ return Iterators.snoc(ifacesIterator, superclass);
+ }
+ }
+
+ public abstract ResolvedMember[] getDeclaredFields();
+ public abstract ResolvedMember[] getDeclaredMethods();
+ public abstract ResolvedTypeX[] getDeclaredInterfaces();
+ public abstract ResolvedMember[] getDeclaredPointcuts();
+ public abstract ResolvedTypeX getSuperclass();
+ public abstract int getModifiers();
+
+
+ public abstract boolean needsNoConversionFrom(TypeX other);
+ public abstract boolean isCoerceableFrom(TypeX other);
+ public abstract boolean isAssignableFrom(TypeX other);
+
+ // ---- things that would require a world if I weren't resolved
+ public final Iterator getDirectSupertypes(World world) {
+ return getDirectSupertypes();
+ }
+
+ public final ResolvedMember[] getDeclaredFields(World world) {
+ return getDeclaredFields();
+ }
+ public final ResolvedMember[] getDeclaredMethods(World world) {
+ return getDeclaredMethods();
+ }
+ public final TypeX[] getDeclaredInterfaces(World world) {
+ return getDeclaredInterfaces();
+ }
+ public final ResolvedMember[] getDeclaredPointcuts(World world) {
+ return getDeclaredPointcuts();
+ }
+
+ public final int getModifiers(World world) {
+ return getModifiers();
+ }
+ public final TypeX getSuperclass(World world) {
+ return getSuperclass();
+ }
+
+ // conversions
+ public final boolean isAssignableFrom(TypeX other, World world) {
+ return isAssignableFrom(other);
+ }
+ public final boolean isCoerceableFrom(TypeX other, World world) {
+ return isCoerceableFrom(other);
+ }
+ public boolean needsNoConversionFrom(TypeX other, World world) {
+ return needsNoConversionFrom(other);
+ }
+ public final boolean isConvertableFrom(TypeX other) {
+ if (this.equals(OBJECT) || other.equals(OBJECT)) return true;
+ return this.isCoerceableFrom(other);
+ }
+
+ // utilities
+ public ResolvedTypeX getResolvedComponentType() {
+ return null;
+ }
+ public ResolvedTypeX resolve(World world) {
+ return this;
+ }
+ public World getWorld() {
+ return world;
+ }
+
+ // ---- things from object
+
+ public final boolean equals(Object other) {
+ if (other instanceof ResolvedTypeX) {
+ 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
+ *
+ * <ul><li> fields from current class </li>
+ * <li> recur into direct superinterfaces </li>
+ * <li> recur into superclass </li>
+ * </ul>
+ *
+ * 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(
+ ((ResolvedTypeX)o).getDirectSupertypes());
+ }
+ };
+ Iterators.Getter fieldGetter = new Iterators.Getter() {
+ public Iterator get(Object o) {
+ return Iterators.array(((ResolvedTypeX)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
+ *
+ * <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>
+ *
+ * We keep a hashSet of interfaces that we've visited so we don't spiral
+ * out into 2^n land.
+ */
+ 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(((ResolvedTypeX)o).getDeclaredInterfaces())
+ );
+ }
+ };
+ Iterators.Getter methodGetter = new Iterators.Getter() {
+ public Iterator get(Object o) {
+ return Iterators.array(((ResolvedTypeX)o).getDeclaredMethods());
+ }
+ };
+ return
+ Iterators.mapOver(
+ Iterators.append(
+ new Iterator() {
+ ResolvedTypeX curr = ResolvedTypeX.this;
+ public boolean hasNext() {
+ return curr != null;
+ }
+ public Object next() {
+ ResolvedTypeX ret = curr;
+ curr = curr.getSuperclass();
+ return ret;
+ }
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ },
+ Iterators.recur(this, ifaceGetter)),
+ methodGetter);
+ }
+
+ /**
+ * 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
+ */
+ public ResolvedMember lookupMethod(Member m) {
+ return lookupMember(m, getMethods());
+ }
+
+ /** 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;
+ }
+ 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;
+ }
+
+
+ public static boolean matches(Member m1, Member m2) {
+ return m1.getName().equals(m2.getName()) && m1.getSignature().equals(m2.getSignature());
+ }
+
+
+ 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());
+ }
+
+ TypeX[] p1 = m1.getParameterTypes();
+ TypeX[] 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
+ *
+ * <ul><li> pointcuts from current class </li>
+ * <li> recur into direct superinterfaces </li>
+ * <li> recur into superclass </li>
+ * </ul>
+ *
+ * We keep a hashSet of interfaces that we've visited so we don't spiral
+ * out into 2^n land.
+ */
+ private 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(
+ ((ResolvedTypeX)o).getDirectSupertypes());
+ }
+ };
+ Iterators.Getter pointcutGetter = new Iterators.Getter() {
+ public Iterator get(Object o) {
+ //System.err.println("getting for " + o);
+ return Iterators.array(((ResolvedTypeX)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;
+ }
+ }
+ return null; // should we throw an exception here?
+ }
+
+
+ // all about collecting CrosscuttingMembers
+
+ //??? collecting data-structure, shouldn't really be a field
+ public CrosscuttingMembers crosscuttingMembers;
+
+//
+// private List extraConcreteShadowMungers = new ArrayList(); //XXX makes testing easier...
+// public void addExtraConcreteShadowMunger(ShadowMunger munger) {
+// munger.pointcut.assertState(Pointcut.CONCRETE);
+// extraConcreteShadowMungers.add(munger);
+// }
+// public List getExtraConcreteShadowMungers() {
+// return extraConcreteShadowMungers;
+// }
+//
+// private List extraConcreteTypeMungers = new ArrayList(); //XXX makes testing easier...Collections.EMPTY_LIST;
+// public void addExtraConcreteTypeMunger(ConcreteTypeMunger munger) {
+// //munger.pointcut.assertState(Pointcut.CONCRETE);
+// extraConcreteTypeMungers.add(munger);
+// }
+// public List getExtraConcreteTypeMungers() {
+// return extraConcreteTypeMungers;
+// }
+
+
+ public CrosscuttingMembers collectCrosscuttingMembers() {
+ crosscuttingMembers = new CrosscuttingMembers(this);
+ crosscuttingMembers.setPerClause(getPerClause());
+ crosscuttingMembers.addShadowMungers(collectShadowMungers());
+ crosscuttingMembers.addTypeMungers(getTypeMungers());
+ crosscuttingMembers.addDeclares(collectDeclares());
+ crosscuttingMembers.addPrivilegedAccesses(getPrivilegedAccesses());
+
+ //System.err.println("collected cc members: " + this + ", " + collectDeclares());
+ return crosscuttingMembers;
+ }
+
+ private final Collection collectDeclares() {
+ 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 (!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(
+ ((ResolvedTypeX)o).getDirectSupertypes());
+ }
+ };
+ Iterator typeIterator = Iterators.recur(this, typeGetter);
+
+ while (typeIterator.hasNext()) {
+ ResolvedTypeX ty = (ResolvedTypeX) typeIterator.next();
+ //System.out.println("super: " + ty + ", " + );
+ for (Iterator i = ty.getDeclares().iterator(); i.hasNext();) {
+ Declare dec = (Declare) i.next();
+ if (dec.isAdviceLike()) ret.add(dec);
+ }
+ }
+ }
+
+ return ret;
+ }
+
+
+
+
+ private final Collection collectShadowMungers() {
+ if (! this.isAspect() || this.isAbstract()) 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(
+ ((ResolvedTypeX)o).getDirectSupertypes());
+ }
+ };
+ Iterator typeIterator = Iterators.recur(this, typeGetter);
+
+ while (typeIterator.hasNext()) {
+ ResolvedTypeX ty = (ResolvedTypeX) typeIterator.next();
+ acc.addAll(ty.getDeclaredShadowMungers());
+ }
+
+ return acc;
+ }
+
+ public PerClause getPerClause() { return null; }
+ protected 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 final boolean isFinal() {
+ return Modifier.isFinal(getModifiers());
+ }
+
+ public Collection getDeclaredAdvice() {
+ List l = new ArrayList();
+ ResolvedMember[] methods = getDeclaredMethods();
+ for (int i=0, len = methods.length; i < len; i++) {
+ ShadowMunger munger = methods[i].getAssociatedShadowMunger();
+ if (munger != null) l.add(munger);
+ }
+ return l;
+ }
+
+ private List shadowMungers = new ArrayList(0);
+
+ public Collection getDeclaredShadowMungers() {
+ Collection c = getDeclaredAdvice();
+ c.addAll(shadowMungers);
+ return c;
+ }
+
+
+ public void addShadowMunger(ShadowMunger munger) {
+ shadowMungers.add(munger);
+ }
+
+
+ // ---- 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 ResolvedTypeX[] NONE = new ResolvedTypeX[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();
+
+ // ---- types
+
+ public static abstract class Name extends ResolvedTypeX {
+ protected ISourceContext sourceContext;
+
+ public Name(String signature, World world) {
+ super(signature, world);
+ }
+
+ public final boolean isClass() {
+ return !isAspect() && !isInterface();
+ }
+
+ public abstract boolean isAspect();
+ public final boolean isAssignableFrom(TypeX o) {
+ if (o.isPrimitive()) return false;
+ ResolvedTypeX other = o.resolve(world);
+
+ return isAssignableFrom(other);
+ }
+ private boolean isAssignableFrom(ResolvedTypeX other) {
+ if (this == other) return true;
+ for(Iterator i = other.getDirectSupertypes(); i.hasNext(); ) {
+ if (this.isAssignableFrom((ResolvedTypeX) i.next())) return true;
+ }
+ return false;
+ }
+ public final boolean isCoerceableFrom(TypeX o) {
+ ResolvedTypeX other = o.resolve(world);
+
+ if (this.isAssignableFrom(other) || other.isAssignableFrom(this)) {
+ return true;
+ }
+ 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 = ((Name)other).getDeclaredMethods();
+ 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;
+ }
+ public final boolean needsNoConversionFrom(TypeX o) {
+ return isAssignableFrom(o);
+ }
+
+ public ResolvedMember addPerSingletonField() {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public ISourceContext getSourceContext() {
+ return sourceContext;
+ }
+
+ }
+
+ static class Array extends ResolvedTypeX {
+ ResolvedTypeX componentType;
+ Array(String s, World world, ResolvedTypeX componentType) {
+ super(s, world);
+ this.componentType = componentType;
+ }
+ public final ResolvedMember[] getDeclaredFields() {
+ return ResolvedMember.NONE;
+ }
+ public final ResolvedMember[] getDeclaredMethods() {
+ // ??? should this return clone? Probably not...
+ return ResolvedMember.NONE;
+ }
+ public final ResolvedTypeX[] getDeclaredInterfaces() {
+ return
+ new ResolvedTypeX[] {
+ world.resolve(CLONEABLE),
+ world.resolve(SERIALIZABLE)
+ };
+ }
+ public final ResolvedMember[] getDeclaredPointcuts() {
+ return ResolvedMember.NONE;
+ }
+
+ public final ResolvedTypeX getSuperclass() {
+ return world.resolve(OBJECT);
+ }
+ public final boolean isAssignableFrom(TypeX o) {
+ if (! o.isArray()) return false;
+ if (o.getComponentType().isPrimitive()) {
+ return o.equals(this);
+ } else {
+ return getComponentType().isAssignableFrom(o.getComponentType(), world);
+ }
+ }
+ public final boolean isCoerceableFrom(TypeX o) {
+ if (o.equals(TypeX.OBJECT) ||
+ o.equals(TypeX.SERIALIZABLE) ||
+ o.equals(TypeX.CLONEABLE)) {
+ return true;
+ }
+ if (! o.isArray()) return false;
+ if (o.getComponentType().isPrimitive()) {
+ return o.equals(this);
+ } else {
+ return getComponentType().isCoerceableFrom(o.getComponentType(), world);
+ }
+ }
+ public final boolean needsNoConversionFrom(TypeX o) {
+ return isAssignableFrom(o);
+ }
+ public final int getModifiers() {
+ int mask = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
+ return (componentType.getModifiers() & mask) | Modifier.FINAL;
+ }
+ public TypeX getComponentType() {
+ return componentType;
+ }
+ public ResolvedTypeX getResolvedComponentType() {
+ return componentType;
+ }
+ public ISourceContext getSourceContext() {
+ return getResolvedComponentType().getSourceContext();
+ }
+ }
+
+ static class Primitive extends ResolvedTypeX {
+ private int size;
+ private int index;
+ Primitive(String signature, int size, int index) {
+ super(signature, null);
+ this.size = size;
+ this.index = index;
+ }
+ public final int getSize() {
+ return size;
+ }
+ public final int getModifiers() {
+ return Modifier.PUBLIC | Modifier.FINAL;
+ }
+ public final boolean isPrimitive() {
+ return true;
+ }
+ public final boolean isAssignableFrom(TypeX other) {
+ if (! other.isPrimitive()) return false;
+ return assignTable[((Primitive)other).index][index];
+ }
+ public final boolean isCoerceableFrom(TypeX other) {
+ if (this == other) return true;
+ if (! other.isPrimitive()) return false;
+ if (index > 6 || ((Primitive)other).index > 6) return false;
+ return true;
+ }
+ public final boolean needsNoConversionFrom(TypeX other) {
+ if (! other.isPrimitive()) 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 ResolvedTypeX[] getDeclaredInterfaces() {
+ return ResolvedTypeX.NONE;
+ }
+ public final ResolvedMember[] getDeclaredPointcuts() {
+ return ResolvedMember.NONE;
+ }
+
+ public final ResolvedTypeX getSuperclass() {
+ return null;
+ }
+
+ public ISourceContext getSourceContext() {
+ return null;
+ }
+
+ }
+
+ static class Missing extends ResolvedTypeX {
+ Missing() {
+ super(MISSING_NAME, null);
+ }
+// public final String toString() {
+// return "<missing>";
+// }
+ public final String getName() {
+ return MISSING_NAME;
+ }
+ public final ResolvedMember[] getDeclaredFields() {
+ return ResolvedMember.NONE;
+ }
+ public final ResolvedMember[] getDeclaredMethods() {
+ return ResolvedMember.NONE;
+ }
+ public final ResolvedTypeX[] getDeclaredInterfaces() {
+ return ResolvedTypeX.NONE;
+ }
+
+ public final ResolvedMember[] getDeclaredPointcuts() {
+ return ResolvedMember.NONE;
+ }
+ public final ResolvedTypeX getSuperclass() {
+ return null;
+ }
+ public final int getModifiers() {
+ return 0;
+ }
+ public final boolean isAssignableFrom(TypeX other) {
+ return false;
+ }
+ public final boolean isCoerceableFrom(TypeX other) {
+ return false;
+ }
+ public boolean needsNoConversionFrom(TypeX other) {
+ return false;
+ }
+ public ISourceContext getSourceContext() {
+ return null;
+ }
+
+ }
+
+ /** return null if not found */
+ public ResolvedMember lookupMemberNoSupers(Member member) {
+ if (member.getKind() == Member.FIELD) {
+ return lookupMember(member, getDeclaredFields());
+ } else {
+ // assert member.getKind() == Member.METHOD || member.getKind() == Member.CONSTRUCTOR
+ return lookupMember(member, getDeclaredMethods());
+ }
+ }
+
+ protected List interTypeMungers = new ArrayList(0);
+
+ public List getInterTypeMungers() {
+ return interTypeMungers;
+ }
+
+ private static ResolvedTypeX getOutermostType(ResolvedTypeX t) {
+ TypeX dec = t.getDeclaringType();
+ if (dec == null) return t;
+ return getOutermostType(dec.resolve(t.getWorld()));
+ }
+
+ public static boolean isVisible(int modifiers, ResolvedTypeX targetType, ResolvedTypeX fromType) {
+ //System.err.println("mod: " + modifiers + ", " + targetType + " and " + fromType);
+
+ if (Modifier.isPublic(modifiers)) {
+ return true;
+ } else if (Modifier.isPrivate(modifiers)) {
+ return getOutermostType(targetType).equals(getOutermostType(fromType));
+ } else if (Modifier.isProtected(modifiers)) {
+ return samePackage(targetType, fromType) || targetType.isAssignableFrom(fromType);
+ } else { // package-visible
+ return samePackage(targetType, fromType);
+ }
+ }
+
+ private static boolean samePackage(
+ ResolvedTypeX targetType,
+ ResolvedTypeX fromType)
+ {
+ String p1 = targetType.getPackageName();
+ String p2 = fromType.getPackageName();
+ if (p1 == null) return p2 == null;
+ if (p2 == null) return false;
+ return p1.equals(p2);
+ }
+
+ public void addInterTypeMunger(ConcreteTypeMunger munger) {
+ ResolvedMember sig = munger.getSignature();
+ if (sig == null) {
+ interTypeMungers.add(munger);
+ return;
+ }
+
+ //System.err.println("add: " + munger + " to " + this.getClassName() + " with " + interTypeMungers);
+ if (sig.getKind() == Member.METHOD) {
+ if (!compareToExistingMembers(munger, getMethods())) return;
+ if (this.isInterface()) {
+ if (!compareToExistingMembers(munger,
+ Arrays.asList(world.resolve(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().comparePrecedence(munger.getAspectType(), existingMunger.getAspectType());
+ }
+ //System.err.println(" compare: " + c);
+ if (c < 0) {
+ // the existing munger dominates the new munger
+ return;
+ } else if (c > 0) {
+ // the new munger dominates the existing one
+ i.remove();
+ break;
+ } else {
+ interTypeConflictError(munger, existingMunger);
+ interTypeConflictError(existingMunger, munger);
+ return;
+ }
+ }
+ }
+ }
+ //System.err.println("adding: " + munger + " to " + this);
+ interTypeMungers.add(munger);
+ }
+
+
+ //??? returning too soon
+ private boolean compareToExistingMembers(ConcreteTypeMunger munger, Iterator existingMembers) {
+ ResolvedMember sig = munger.getSignature();
+ while (existingMembers.hasNext()) {
+ ResolvedMember existingMember = (ResolvedMember)existingMembers.next();
+
+ if (conflictingSignature(existingMember, munger.getSignature())) {
+ //System.err.println("conflict: " + existingMember + " with " + munger);
+ if (isVisible(existingMember.getModifiers(), this, munger.getAspectType())) {
+ int c = compareMemberPrecedence(sig, existingMember);
+ //System.err.println(" c: " + c);
+ if (c < 0) return false;
+ else if (c > 0) {
+ //interTypeMungers.add(munger);
+ //??? might need list of these overridden abstracts
+ continue;
+ } else {
+ if (this instanceof BcelObjectType) return false; //XXX ignores separate comp
+ getWorld().getMessageHandler().handleMessage(
+ MessageUtil.error("inter-type declaration from " + munger.getAspectType() +
+ " conflicts with existing member: " + existingMember,
+ munger.getSourceLocation())
+ );
+ }
+ } else {
+ //interTypeMungers.add(munger);
+ }
+ //return;
+ }
+ }
+ return true;
+ }
+
+
+
+
+ private int compareMemberPrecedence(ResolvedMember m1, ResolvedMember m2) {
+ if (!m1.getReturnType().equals(m2.getReturnType())) return 0;
+
+ if (Modifier.isAbstract(m1.getModifiers())) return -1;
+ if (Modifier.isAbstract(m2.getModifiers())) return +1;
+
+ if (m1.getDeclaringType().equals(m2.getDeclaringType())) return 0;
+
+ ResolvedTypeX t1 = m1.getDeclaringType().resolve(world);
+ ResolvedTypeX t2 = m2.getDeclaringType().resolve(world);
+ if (t1.isAssignableFrom(t2)) {
+ checkVisibility(m1.getModifiers(), m2.getModifiers()); //XXX needs to be before abstract
+ return -1;
+ }
+ if (t2.isAssignableFrom(t1)) {
+ checkVisibility(m2.getModifiers(), m1.getModifiers());
+ return +1;
+ }
+ return 0;
+ }
+
+
+ private void checkVisibility(int parentMods, int childMods) {
+ //childMods must be equal to or greater than parentMods visibility
+
+ }
+
+
+
+ private void interTypeConflictError(
+ ConcreteTypeMunger m1,
+ ConcreteTypeMunger m2)
+ {
+ //XXX this works only if we ignore separate compilation issues
+ if (this instanceof BcelObjectType) return;
+
+ //System.err.println("conflict at " + m2.getSourceLocation());
+ getWorld().getMessageHandler().handleMessage(MessageUtil.error(
+ "intertype declaration from "
+ + m1.getAspectType().getClassName()
+ + " conflicts with intertype declaration: "
+ + m2.getSignature()
+ + " from "
+ + m2.getAspectType().getClassName(),
+ m2.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;
+ }
+ }
+ return null;
+ }
+
+ public void clearInterTypeMungers() {
+ interTypeMungers = new ArrayList();
+ }
+
+
+ public boolean isTopmostImplementor(ResolvedTypeX interfaceType) {
+ if (isInterface()) return false;
+ if (!interfaceType.isAssignableFrom(this)) return false;
+ // check that I'm truly the topmost implementor
+ if (interfaceType.isAssignableFrom(this.getSuperclass())) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/Shadow.java b/weaver/src/org/aspectj/weaver/Shadow.java
new file mode 100644
index 000000000..22f86deb9
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/Shadow.java
@@ -0,0 +1,233 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.Field;
+import org.aspectj.weaver.ast.Var;
+import org.aspectj.weaver.patterns.IScope;
+import org.aspectj.bridge.*;
+import org.aspectj.bridge.SourceLocation;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.util.*;
+
+/*
+ * 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 {
+ private final Kind kind;
+ private final Member signature;
+ protected List mungers = new ArrayList(1);
+
+ // ----
+
+ protected Shadow(Kind kind, Member signature) {
+ this.kind = kind;
+ this.signature = signature;
+ }
+
+ // ----
+
+ public abstract World getIWorld();
+
+ public final boolean hasTarget() {
+ return !(getSignature().isStatic() || (getKind() == ConstructorCall)
+ || (getKind() == PreInitialization));
+ }
+
+ public final TypeX getTargetType() {
+ if (!hasTarget()) return ResolvedTypeX.MISSING;
+ return getSignature().getDeclaringType();
+ }
+ public TypeX 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;
+ }
+
+ public abstract boolean hasThis();
+ public abstract TypeX getThisType();
+ public abstract TypeX getEnclosingType();
+ public abstract Var getThisVar();
+ public abstract Var getTargetVar();
+ public abstract Var getArgVar(int i);
+
+ public abstract Var getThisJoinPointVar();
+ public abstract Var getThisJoinPointStaticPartVar();
+ public abstract Var getThisEnclosingJoinPointStaticPartVar();
+
+ 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;
+ }
+
+
+ public TypeX getReturnType() {
+ if (kind == ConstructorCall) return getSignature().getDeclaringType();
+ return getSignature().getReturnType();
+ }
+
+
+ /**
+ * 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(JoinPoint.METHOD_CALL, 1, true);
+ public static final Kind ConstructorCall = new Kind(JoinPoint.CONSTRUCTOR_CALL, 2, true);
+ public static final Kind MethodExecution = new Kind(JoinPoint.METHOD_EXECUTION, 3, false);
+ public static final Kind ConstructorExecution = new Kind(JoinPoint.CONSTRUCTOR_EXECUTION, 4, false);
+ public static final Kind FieldGet = new Kind(JoinPoint.FIELD_GET, 5, true);
+ public static final Kind FieldSet = new Kind(JoinPoint.FIELD_SET, 6, true);
+ public static final Kind StaticInitialization = new Kind(JoinPoint.STATICINITIALIZATION, 7, false);
+ public static final Kind PreInitialization = new Kind(JoinPoint.PREINTIALIZATION, 8, false);
+ public static final Kind AdviceExecution = new Kind(JoinPoint.ADVICE_EXECUTION, 9, false);
+ public static final Kind Initialization = new Kind(JoinPoint.INITIALIZATION, 10, false);
+ public static final Kind ExceptionHandler = new Kind(JoinPoint.EXCEPTION_HANDLER, 11, true);
+
+
+ /** A type-safe enum representing the kind of shadows
+ */
+ public static final class Kind extends TypeSafeEnum {
+ private boolean argsOnStack;
+
+ public Kind(String name, int key, boolean argsOnStack) {
+ super(name, key);
+ this.argsOnStack = argsOnStack;
+ }
+
+ public String toLegalJavaIdentifier() {
+ return getName().replace('-', '_');
+ }
+
+ public boolean argsOnStack() {
+ return argsOnStack;
+ }
+
+ // !!! this is false for handlers!
+ public boolean allowsExtraction() {
+ return true;
+ }
+
+ 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;
+ }
+ throw new BCException("unknown kind: " + key);
+ }
+ }
+
+ public void addMunger(ShadowMunger munger) {
+ this.mungers.add(munger);
+ }
+
+ public final void implement() {
+ sortMungers();
+ if (mungers == null) return;
+ prepareForMungers();
+ implementMungers();
+ }
+
+ private void sortMungers() {
+ List sorted = PartialOrder.sort(mungers);
+ 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("circular dependency at " + this, m.getSourceLocation()));
+ }
+ }
+ mungers = sorted;
+ }
+
+ /** 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);
+ if (world.getModel() != null) {
+ System.err.println("munger: " + munger + " on " + this);
+ AsmAdaptor.noteMunger(world.getModel(), this, munger);
+ }
+ }
+ }
+
+ public String makeReflectiveFactoryString() {
+ return null; //XXX
+ }
+
+ public abstract SourceLocation getSourceLocation();
+
+ // ---- utility
+
+ public String toString() {
+ return getKind() + "(" + getSignature() + ")"; // + getSourceLines();
+ }
+
+
+
+
+
+ // ---- type access methods
+
+
+
+}
diff --git a/weaver/src/org/aspectj/weaver/ShadowMunger.java b/weaver/src/org/aspectj/weaver/ShadowMunger.java
new file mode 100644
index 000000000..4cce6743b
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ShadowMunger.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.util.PartialOrder;
+import org.aspectj.weaver.patterns.*;
+import org.aspectj.weaver.patterns.PerClause;
+
+/**
+ * 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;
+
+
+ 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(ResolvedTypeX 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 int fallbackCompareTo(Object other) {
+ return toString().compareTo(toString());
+ }
+
+ public int getEnd() {
+ return end;
+ }
+
+ public int getStart() {
+ return start;
+ }
+
+ 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);
+ }
+
+ // ---- fields
+
+ public static final ShadowMunger[] NONE = new ShadowMunger[0];
+
+
+
+}
diff --git a/weaver/src/org/aspectj/weaver/StaticJoinPointFactory.java b/weaver/src/org/aspectj/weaver/StaticJoinPointFactory.java
new file mode 100644
index 000000000..d0f5ab4f1
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/StaticJoinPointFactory.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.StringReader;
+import java.util.*;
+
+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/weaver/src/org/aspectj/weaver/TypeX.java b/weaver/src/org/aspectj/weaver/TypeX.java
new file mode 100644
index 000000000..94c86201c
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/TypeX.java
@@ -0,0 +1,683 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+
+import org.aspectj.weaver.patterns.PerClause;
+
+public class TypeX {
+ /**
+ * This is the bytecode string representation of this Type
+ */
+ protected String signature;
+
+ /**
+ * @param signature the bytecode string representation of this Type
+ */
+ protected TypeX(String signature) {
+ super();
+ this.signature = signature;
+ }
+
+ // ---- Things we can do without a world
+
+ /**
+ * This is the size of this type as used in JVM.
+ */
+ public int getSize() {
+ return 1;
+ }
+
+ /**
+ * Equality is checked based on the underlying signature.
+ * {@link ResolvedType} objects' equals is by reference.
+ */
+ public boolean equals(Object other) {
+ if (! (other instanceof TypeX)) return false;
+ return signature.equals(((TypeX) 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();
+ }
+
+ /**
+ * Constructs a TypeX for a java language type name. For example:
+ *
+ * <blockquote><pre>
+ * TypeX.forName("java.lang.Thread[]")
+ * TypeX.forName("int")
+ * </pre></blockquote>
+ *
+ * Types may equivalently be produced by this or by {@link #forSignature(String)}.
+ *
+ * <blockquote><pre>
+ * TypeX.forName("java.lang.Thread[]").equals(Type.forSignature("[Ljava/lang/Thread;")
+ * TypeX.forName("int").equals(Type.forSignature("I"))
+ * </pre></blockquote>
+ *
+ * @param name the java language type name in question.
+ * @return a type object representing that java language type.
+ */
+ public static TypeX forName(String name) {
+ return forSignature(nameToSignature(name));
+ }
+
+ /** Constructs a TypeX for each java language type name in an incoming array.
+ *
+ * @param names an array of java language type names.
+ * @return an array of TypeX objects.
+ * @see #forName(String)
+ */
+ public static TypeX[] forNames(String[] names) {
+ TypeX[] ret = new TypeX[names.length];
+ for (int i = 0, len = names.length; i < len; i++) {
+ ret[i] = TypeX.forName(names[i]);
+ }
+ 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 TypeX[] add(TypeX[] types, TypeX end) {
+ int len = types.length;
+ TypeX[] ret = new TypeX[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 TypeX[] insert(TypeX start, TypeX[] types) {
+ int len = types.length;
+ TypeX[] ret = new TypeX[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>
+ * TypeX.forSignature("[Ljava/lang/Thread;")
+ * TypeX.forSignature("I");
+ * </pre></blockquote>
+ *
+ * Types may equivalently be produced by this or by {@link #forName(String)}.
+ *
+ * <blockquote><pre>
+ * TypeX.forName("java.lang.Thread[]").equals(Type.forSignature("[Ljava/lang/Thread;")
+ * TypeX.forName("int").equals(Type.forSignature("I"))
+ * </pre></blockquote>
+ *
+ * @param signature the JVM bytecode signature string for the desired type.
+ * @return a type object represnting that JVM bytecode signature.
+ */
+ public static TypeX forSignature(String signature) {
+ switch (signature.charAt(0)) {
+ case 'B': return ResolvedTypeX.BYTE;
+ case 'C': return ResolvedTypeX.CHAR;
+ case 'D': return ResolvedTypeX.DOUBLE;
+ case 'F': return ResolvedTypeX.FLOAT;
+ case 'I': return ResolvedTypeX.INT;
+ case 'J': return ResolvedTypeX.LONG;
+ case 'L':
+ return new TypeX(signature);
+ case 'S': return ResolvedTypeX.SHORT;
+ case 'V': return ResolvedTypeX.VOID;
+ case 'Z': return ResolvedTypeX.BOOLEAN;
+ case '[':
+ return new TypeX(signature);
+ default:
+ throw new BCException("Bad type signature " + signature);
+ }
+ }
+
+ /** Constructs a TypeX for each JVM bytecode type signature in an incoming array.
+ *
+ * @param names an array of JVM bytecode type signatures
+ * @return an array of TypeX objects.
+ * @see #forSignature(String)
+ */
+ public static TypeX[] forSignatures(String[] sigs) {
+ TypeX[] ret = new TypeX[sigs.length];
+ for (int i = 0, len = sigs.length; i < len; i++) {
+ ret[i] = TypeX.forSignature(sigs[i]);
+ }
+ return ret;
+ }
+
+ /**
+ * Returns the name of this type in java language form. For all
+ * TypeX t:
+ *
+ * <blockquote><pre>
+ * TypeX.forName(t.getName()).equals(t)
+ * </pre></blockquote>
+ *
+ * and for all String s where s is a lexically valid java language typename:
+ *
+ * <blockquote><pre>
+ * TypeX.forName(s).getName().equals(s)
+ * </pre></blockquote>
+ *
+ * This produces a more esthetically pleasing string than
+ * {@link java.lang.Class#getName()}.
+ *
+ * @return the java language name of this type.
+ */
+ public String getName() {
+ return signatureToName(signature);
+ }
+
+ /**
+ * Returns an array of strings representing the java langauge names of
+ * an array of types.
+ *
+ * @param types an array of TypeX objects
+ * @return an array of Strings fo the java language names of types.
+ * @see #getName()
+ */
+ public static String[] getNames(TypeX[] 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
+ * TypeX t:
+ *
+ * <blockquote><pre>
+ * TypeX.forSignature(t.getSignature()).equals(t)
+ * </pre></blockquote>
+ *
+ * and for all String s where s is a lexically valid JVM type signature string:
+ *
+ * <blockquote><pre>
+ * TypeX.forSignature(s).getSignature().equals(s)
+ * </pre></blockquote>
+ *
+ * @return the java JVM signature string for this type.
+ */
+ public String getSignature() {
+ return signature;
+ }
+
+ /**
+ * Determins if this represents an array type.
+ *
+ * @return true iff this represents an array type.
+ */
+ public final boolean isArray() {
+ return signature.startsWith("[");
+ }
+
+ /**
+ * Returns a TypeX object representing the declaring type of this type, or
+ * null if this type does not represent a non-package-level-type.
+ *
+ * <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 TypeX object, or null.
+ */
+ public TypeX getDeclaringType() {
+ if (isArray()) return null;
+ String name = getName();
+ int lastDollar = name.lastIndexOf('$');
+ if (lastDollar != -1) {
+ return TypeX.forName(name.substring(0, lastDollar));
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns a TypeX object representing the component type of this array, or
+ * null if this type does not represent an array type.
+ *
+ * @return the component TypeX object, or null.
+ */
+ public TypeX getComponentType() {
+ if (isArray()) {
+ return forSignature(signature.substring(1));
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Determines if this represents a primitive type. A primitive type
+ * is one of nine predefined resolved types.
+ *
+ * @return true iff this type represents a primitive type
+ *
+ * @see ResolvedTypeX#Boolean
+ * @see ResolvedTypeX#Character
+ * @see ResolvedTypeX#Byte
+ * @see ResolvedTypeX#Short
+ * @see ResolvedTypeX#Integer
+ * @see ResolvedTypeX#Long
+ * @see ResolvedTypeX#Float
+ * @see ResolvedTypeX#Double
+ * @see ResolvedTypeX#Void
+ */
+ public boolean isPrimitive() {
+ return false;
+ }
+
+
+ /**
+ * Returns a java language string representation of this type.
+ */
+ public String toString() {
+ return getName();
+ }
+
+ // ---- requires worlds
+
+ /**
+ * Types may have pointcuts just as they have methods and fields.
+ */
+ public ResolvedPointcutDefinition findPointcut(String name, World world) {
+ return world.findPointcut(this, name);
+ }
+
+ /**
+ * Determines if variables of this type could be assigned values of another
+ * with lots of help. This is the same as isCoercableFrom, but java.lang.Object
+ * is convertable from and to all types.
+ *
+ * @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(TypeX other, World world) {
+ if (this.equals(OBJECT) || other.equals(OBJECT)) return true;
+ return this.isCoerceableFrom(other, world);
+ }
+
+ /**
+ * Determines if variables of this type could be assigned values of another
+ * without any conversion computation of any kind. For primitive types
+ * this means equality, and for reference types it means assignability.
+ *
+ * @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 any conversion computation
+ */
+ public boolean needsNoConversionFrom(TypeX other, World world) {
+ // primitives override this method, so we know we're not primitive.
+ // So if the other is primitive, don't bother asking the world anything.
+ if (other.isPrimitive()) return false;
+ return world.needsNoConversionFrom(this, 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.
+ *
+ * @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
+ * @exception NullPointerException if other is null
+ */
+ public boolean isAssignableFrom(TypeX other, World world) {
+ // primitives override this method, so we know we're not primitive.
+ // So if the other is primitive, don't bother asking the world anything.
+ if (other.isPrimitive()) return false;
+ return world.isAssignableFrom(this, other);
+ }
+
+ /**
+ * 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> This method should be commutative, i.e., for all TypeX a, b and all World w:
+ *
+ * <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.
+ * @exception NullPointerException if other is null.
+ */
+ public boolean isCoerceableFrom(TypeX other, World world) {
+ // primitives override this method, so we know we're not primitive.
+ // So if the other is primitive, don't bother asking the world anything.
+ if (other.isPrimitive()) return false;
+ return world.isCoerceableFrom(this, other);
+ }
+
+ /**
+ * Determines if this represents an interface type.
+ *
+ * @param world the {@link World} in which we should check.
+ * @return true iff this represents an interface type.
+ */
+ public final boolean isInterface(World world) {
+ return world.resolve(this).isInterface();
+ }
+
+ /**
+ * Determines if this represents a class type.
+ *
+ * @param world the {@link World} in which we should check.
+ * @return true iff this represents a class type.
+ */
+ public final boolean isClass(World world) {
+ return world.resolve(this).isClass();
+ }
+
+
+ /**
+ * Determines if this represents an aspect type.
+ *
+ * @param world the {@link World} in which we should check.
+ * @return true iff this represents an aspect type.
+ */
+ public final boolean isAspect(World world) {
+ return world.resolve(this).isAspect();
+ }
+
+
+ /**
+ * Returns a TypeX 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.
+ *
+ * <p>
+ * This differs from {@link java.lang.class#getSuperclass()} in that
+ * this returns a TypeX object representing java.lang.Object for interfaces instead
+ * of returning null.
+ *
+ * @param world the {@link World} in which the lookup should be made.
+ * @return this type's superclass, or null if none exists.
+ */
+ public TypeX getSuperclass(World world) {
+ return world.getSuperclass(this);
+ }
+
+ /**
+ * Returns an array of TypeX objects representing the declared interfaces
+ * of this type.
+ *
+ * <p>
+ * If this object represents a class, the declared interfaces are those it
+ * implements. If this object represents an interface, the declared interfaces
+ * are those it extends. If this object represents a primitive, an empty
+ * array is returned. If this object represents an array, an array
+ * containing types for java.lang.Cloneable and java.io.Serializable is returned.
+ *
+ * @param world the {@link World} in which the lookup should be made.
+ * @return an iterator through the declared interfaces of this type.
+ */
+ public TypeX[] getDeclaredInterfaces(World world) {
+ return world.getDeclaredInterfaces(this);
+ }
+
+ /**
+ * Returns an iterator through TypeX objects representing all the direct
+ * supertypes of this type. That is, through the superclass, if any, and
+ * all declared interfaces.
+ *
+ * @param world the {@link World} in which the lookup should be made.
+ * @return an iterator through the direct supertypes of this type.
+ */
+ public Iterator getDirectSupertypes(World world) {
+ return world.resolve(this).getDirectSupertypes();
+ }
+
+ /**
+ * Returns the modifiers for this type.
+ *
+ * See {@link java.lang.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 int getModifiers(World world) {
+ return world.getModifiers(this);
+ }
+
+ /**
+ * Returns an array representing the declared fields of this object. This may include
+ * non-user-visible fields.
+ * This method returns an
+ * empty array if it represents an array type or a primitive type, so
+ * the implicit length field of arrays is just that, implicit.
+ *
+ * @param world the {@link World} in which the lookup is done.
+ * @return the array representing the declared fields of this type
+ */
+ public ResolvedMember[] getDeclaredFields(World world) {
+ return world.getDeclaredFields(this);
+ }
+
+ /**
+ * Returns an array representing the declared methods of this object. This includes
+ * constructors and the static initialzation method. This also includes all
+ * shadowMungers in an aspect. So it may include more than the user-visible methods.
+ * This method returns an
+ * empty array if it represents an array type or a primitive type.
+ *
+ * @param world the {@link World} in which the lookup is done.
+ * @return the array representing the declared methods of this type
+ */
+ public ResolvedMember[] getDeclaredMethods(World world) {
+ return world.getDeclaredMethods(this);
+ }
+
+
+ /**
+ * Returns an array representing the declared pointcuts of this object.
+ * This method returns an
+ * empty array if it represents an array type or a primitive type.
+ *
+ * @param world the {@link World} in which the lookup is done.
+ * @return the array representing the declared pointcuts of this type
+ */
+ public ResolvedMember[] getDeclaredPointcuts(World world) {
+ return world.getDeclaredPointcuts(this);
+ }
+
+ /**
+ * 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 ResolvedTypeX resolve(World world) {
+ return world.resolve(this);
+ }
+
+ // ---- fields
+
+ public static final TypeX[] NONE = new TypeX[0];
+ public static final TypeX OBJECT = forSignature("Ljava/lang/Object;");
+ public static final TypeX OBJECTARRAY = forSignature("[Ljava/lang/Object;");
+ public static final TypeX CLONEABLE = forSignature("Ljava/lang/Cloneable;");
+ public static final TypeX SERIALIZABLE = forSignature("Ljava/io/Serializable;");
+ public static final TypeX THROWABLE = forSignature("Ljava/lang/Throwable;");
+
+ // ---- 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':
+ return signature.substring(1, signature.length() - 1).replace('/', '.');
+ case 'S': return "short";
+ case 'V': return "void";
+ case 'Z': return "boolean";
+ case '[':
+ return signatureToName(signature.substring(1, signature.length())) + "[]";
+ 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.endsWith("[]"))
+ return "[" + nameToSignature(name.substring(0, name.length() - 2));
+ if (name.length() != 0) // lots more tests could be made here...
+ return "L" + name.replace('.', '/') + ";";
+ else
+ throw new BCException("Bad type name: " + name);
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ s.writeUTF(signature);
+ }
+
+ public static TypeX read(DataInputStream s) throws IOException {
+ String sig = s.readUTF();
+ if (sig.equals(MISSING_NAME)) {
+ return ResolvedTypeX.MISSING;
+ } else {
+ return TypeX.forSignature(sig);
+ }
+ }
+
+ public static void write(TypeX[] 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 TypeX[] readArray(DataInputStream s) throws IOException {
+ int len = s.readShort();
+ TypeX[] types = new TypeX[len];
+ for (int i=0; i < len; i++) {
+ types[i] = TypeX.read(s);
+ }
+ return types;
+ }
+
+
+ /**
+ * For debugging purposes
+ */
+ public void dump(World world) {
+ if (isAspect(world)) System.out.print("aspect ");
+ else if (isInterface(world)) System.out.print("interface ");
+ else if (isClass(world)) System.out.print("class ");
+
+ System.out.println(toString());
+ dumpResolvedMembers("fields", getDeclaredFields(world));
+ dumpResolvedMembers("methods", getDeclaredMethods(world));
+ dumpResolvedMembers("pointcuts", getDeclaredPointcuts(world));
+ }
+
+ private void dumpResolvedMembers(String label, ResolvedMember[] l) {
+ final String indent = " ";
+ System.out.println(label);
+ if (l == null) {
+ System.out.println(indent + "null");
+ return;
+ }
+
+ for (int i=0, len=l.length; i < len; i++) {
+ System.out.println(indent + l[i]);
+ }
+ }
+
+ // ----
+
+ 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();
+ int index = name.lastIndexOf('.');
+ if (index == -1) {
+ return null;
+ } else {
+ return name.substring(0, index);
+ }
+ }
+
+ public String getClassName() {
+ String name = getName();
+ int index = name.lastIndexOf('.');
+ if (index == -1) {
+ return name;
+ } else {
+ return name.substring(index+1);
+ }
+ }
+
+
+
+
+
+ public static final String MISSING_NAME = "<missing>";
+
+}
+
diff --git a/weaver/src/org/aspectj/weaver/WeaverStateKind.java b/weaver/src/org/aspectj/weaver/WeaverStateKind.java
new file mode 100644
index 000000000..da3fd35f3
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/WeaverStateKind.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.io.*;
+
+import org.aspectj.util.TypeSafeEnum;
+
+public class WeaverStateKind extends TypeSafeEnum {
+ private WeaverStateKind(String name, int key) {
+ super(name, key);
+ }
+
+ public static final WeaverStateKind read(DataInputStream s) throws IOException {
+ byte b = s.readByte();
+ switch(b) {
+ case 0: return Untouched;
+ case 2: return Woven;
+ }
+ throw new RuntimeException("bad WeaverState.Kind: " + b);
+ }
+
+
+ public static final WeaverStateKind Untouched = new WeaverStateKind("Untouched", 0);
+ public static final WeaverStateKind Woven = new WeaverStateKind("Woven", 2);
+
+
+ public byte[] getBytes() {
+ return new byte[] { getKey(), };
+ }
+
+ public boolean isWoven() {
+ return this == Woven;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java
new file mode 100644
index 000000000..c12acf985
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/World.java
@@ -0,0 +1,320 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.util.*;
+
+import org.aspectj.weaver.patterns.*;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.asm.StructureModel;
+import org.aspectj.bridge.*;
+import org.aspectj.bridge.IMessageHandler;
+
+public abstract class World {
+ protected IMessageHandler messageHandler = IMessageHandler.SYSTEM_ERR;
+
+ protected Map typeMap = new HashMap(); // Signature to ResolvedType
+
+ protected CrosscuttingMembersSet crosscuttingMembersSet = new CrosscuttingMembersSet(this);
+
+ protected StructureModel model = null;
+
+ protected Lint lint = new Lint(this);
+
+ protected World() {
+ super();
+ typeMap.put("B", ResolvedTypeX.BYTE);
+ typeMap.put("S", ResolvedTypeX.SHORT);
+ typeMap.put("I", ResolvedTypeX.INT);
+ typeMap.put("J", ResolvedTypeX.LONG);
+ typeMap.put("F", ResolvedTypeX.FLOAT);
+ typeMap.put("D", ResolvedTypeX.DOUBLE);
+ typeMap.put("C", ResolvedTypeX.CHAR);
+ typeMap.put("Z", ResolvedTypeX.BOOLEAN);
+ typeMap.put("V", ResolvedTypeX.VOID);
+ }
+
+ public ResolvedTypeX[] resolve(TypeX[] types) {
+ int len = types.length;
+ ResolvedTypeX[] ret = new ResolvedTypeX[len];
+ for (int i=0; i<len; i++) {
+ ret[i] = resolve(types[i]);
+ }
+ return ret;
+ }
+
+ public ResolvedTypeX resolve(TypeX ty) {
+ return resolve(ty, false);
+ }
+
+ public ResolvedTypeX resolve(TypeX ty, boolean allowMissing) {
+ //System.out.println("resolve: " + ty + " world " + typeMap.keySet());
+ String signature = ty.getSignature();
+ ResolvedTypeX ret = (ResolvedTypeX)typeMap.get(signature);
+ if (ret != null) return ret;
+
+ if (ty.isArray()) {
+ ret = new ResolvedTypeX.Array(signature, this, resolve(ty.getComponentType(), allowMissing));
+ } else {
+ ret = resolveObjectType(ty);
+ if (!allowMissing && ret == ResolvedTypeX.MISSING) {
+ //Thread.currentThread().dumpStack();
+ MessageUtil.error(messageHandler, "can't find type " + ty.getName());
+ // + " on classpath " + classPath);
+ }
+ }
+ //System.out.println("ret: " + ret);
+ typeMap.put(signature, ret);
+ return ret;
+ }
+
+ //XXX helper method might be bad
+ public ResolvedTypeX resolve(String name) {
+ return resolve(TypeX.forName(name));
+ }
+ protected abstract ResolvedTypeX resolveObjectType(TypeX ty);
+
+ protected final boolean isCoerceableFrom(TypeX type, TypeX other) {
+ return resolve(type).isCoerceableFrom(other);
+ }
+
+ protected final boolean isAssignableFrom(TypeX type, TypeX other) {
+ return resolve(type).isAssignableFrom(other);
+ }
+
+ public boolean needsNoConversionFrom(TypeX type, TypeX other) {
+ return resolve(type).needsNoConversionFrom(other);
+ }
+
+ protected final boolean isInterface(TypeX type) {
+ return resolve(type).isInterface();
+ }
+
+ protected final ResolvedTypeX getSuperclass(TypeX type) {
+ return resolve(type).getSuperclass();
+ }
+
+ protected final TypeX[] getDeclaredInterfaces(TypeX type) {
+ return resolve(type).getDeclaredInterfaces();
+ }
+
+ protected final int getModifiers(TypeX type) {
+ return resolve(type).getModifiers();
+ }
+
+ protected final ResolvedMember[] getDeclaredFields(TypeX type) {
+ return resolve(type).getDeclaredFields();
+ }
+
+ protected final ResolvedMember[] getDeclaredMethods(TypeX type) {
+ return resolve(type).getDeclaredMethods();
+ }
+
+ protected final ResolvedMember[] getDeclaredPointcuts(TypeX type) {
+ return resolve(type).getDeclaredPointcuts();
+ }
+
+ // ---- members
+
+
+ // XXX should we worry about dealing with context and looking up access?
+ public ResolvedMember resolve(Member member) {
+ ResolvedTypeX declaring = member.getDeclaringType().resolve(this);
+ 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);
+ }
+
+ protected int getModifiers(Member member) {
+ return resolve(member).getModifiers();
+ }
+
+ protected String[] getParameterNames(Member member) {
+ return resolve(member).getParameterNames();
+ }
+
+ protected TypeX[] getExceptions(Member member) {
+ return resolve(member).getExceptions();
+ }
+
+ // ---- pointcuts
+
+ public ResolvedPointcutDefinition findPointcut(TypeX typeX, String name) {
+ throw new RuntimeException("not implemented yet");
+ }
+
+ /**
+ * Get the shadow mungers of this world.
+ *
+ * @return a list of {@link IShadowMunger}s appropriate for this world.
+ */
+ //public abstract List getShadowMungers();
+
+ // ---- empty world
+
+ public static final World EMPTY = new World() {
+ public List getShadowMungers() { return Collections.EMPTY_LIST; }
+ public ResolvedTypeX resolveObjectType(TypeX ty) {
+ return ResolvedTypeX.MISSING;
+ }
+ public Advice concreteAdvice(AdviceKind kind, Pointcut p, Member m, int extraMods,
+ int start, int end, ISourceContext context) {
+ throw new RuntimeException("unimplemented");
+ }
+ public ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedTypeX aspectType) {
+ throw new RuntimeException("unimplemented");
+ }
+ };
+
+
+ public abstract Advice concreteAdvice(
+ AdviceKind kind,
+ Pointcut p,
+ Member signature,
+ int extraParameterFlags,
+ int start, int end, ISourceContext context);
+
+ public final Advice concreteAdvice(
+ AdviceKind kind,
+ Pointcut p,
+ Member signature,
+ int extraParameterFlags,
+ IHasSourceLocation loc)
+ {
+ return concreteAdvice(kind, p, signature, extraParameterFlags, loc.getStart(), loc.getEnd(), loc.getSourceContext());
+ }
+
+
+
+ public ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField) {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public abstract ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedTypeX aspectType);
+
+ /**
+ * 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) {
+ this.messageHandler = messageHandler;
+ }
+
+// public void addDeclare(ResolvedTypeX onType, Declare declare, boolean forWeaving) {
+// // this is not extensible, oh well
+// if (declare instanceof DeclareErrorOrWarning) {
+// ShadowMunger m = new Checker((DeclareErrorOrWarning)declare);
+// onType.addShadowMunger(m);
+// } else if (declare instanceof DeclareDominates) {
+// declareDominates.add(declare);
+// } else if (declare instanceof DeclareParents) {
+// declareParents.add(declare);
+// } else if (declare instanceof DeclareSoft) {
+// DeclareSoft d = (DeclareSoft)declare;
+// declareSoft.add(d);
+// if (forWeaving) {
+// ShadowMunger m = Advice.makeSoftener(this, d.getPointcut().concretize(onType, 0), d.getException());
+// onType.addShadowMunger(m);
+// }
+// } else {
+// throw new RuntimeException("unimplemented");
+// }
+// }
+
+
+ /**
+ * Same signature as org.aspectj.util.PartialOrder.PartialComparable.compareTo
+ */
+ public int compareByDominates(ResolvedTypeX aspect1, ResolvedTypeX aspect2) {
+ //System.out.println("dom compare: " + aspect1 + " with " + aspect2);
+ //System.out.println(crosscuttingMembersSet.getDeclareDominates());
+
+ //??? We probably want to cache this result. This is order N where N is the
+ //??? number of dominates declares in the whole system.
+ //??? This method can be called a large number of times.
+ int order = 0;
+ for (Iterator i = crosscuttingMembersSet.getDeclareDominates().iterator(); i.hasNext(); ) {
+ DeclareDominates d = (DeclareDominates)i.next();
+ int thisOrder = d.compare(aspect1, aspect2);
+ //System.out.println("comparing: " + thisOrder + ": " + d);
+ if (thisOrder != 0) {
+ if (order != 0 && order != thisOrder) {
+ throw new BCException("conflicting dominates orders");
+ } else {
+ order = thisOrder;
+ }
+ }
+ }
+
+
+ return order;
+ }
+
+
+ public int comparePrecedence(ResolvedTypeX aspect1, ResolvedTypeX aspect2) {
+ //System.err.println("compare precedence " + aspect1 + ", " + aspect2);
+ if (aspect1.equals(aspect2)) return 0;
+
+ int ret = compareByDominates(aspect1, aspect2);
+ if (ret != 0) return ret;
+
+ if (aspect1.isAssignableFrom(aspect2)) return -1;
+ else if (aspect2.isAssignableFrom(aspect1)) return +1;
+
+ return 0;
+ }
+
+
+
+
+ public List getDeclareParents() {
+ return crosscuttingMembersSet.getDeclareParents();
+ }
+
+ public List getDeclareSoft() {
+ return crosscuttingMembersSet.getDeclareSofts();
+ }
+
+ public CrosscuttingMembersSet getCrosscuttingMembersSet() {
+ return crosscuttingMembersSet;
+ }
+
+ public StructureModel getModel() {
+ return model;
+ }
+
+ public void setModel(StructureModel model) {
+ this.model = model;
+ }
+
+ public Lint getLint() {
+ return lint;
+ }
+
+ public void setLint(Lint lint) {
+ this.lint = lint;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/XlintDefault.properties b/weaver/src/org/aspectj/weaver/XlintDefault.properties
new file mode 100644
index 000000000..eb5944dfa
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/XlintDefault.properties
@@ -0,0 +1,4 @@
+invalidAbsoluteTypeName = warning
+invalidWildcardTypeName = ignore
+
+unresolvableMember = warning \ No newline at end of file
diff --git a/weaver/src/org/aspectj/weaver/ast/ASTNode.java b/weaver/src/org/aspectj/weaver/ast/ASTNode.java
new file mode 100644
index 000000000..261605b10
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/ASTNode.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+public abstract class ASTNode {
+
+ public ASTNode() {
+ super();
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/ast/And.java b/weaver/src/org/aspectj/weaver/ast/And.java
new file mode 100644
index 000000000..1dc00be7f
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/And.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/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/weaver/src/org/aspectj/weaver/ast/Call.java b/weaver/src/org/aspectj/weaver/ast/Call.java
new file mode 100644
index 000000000..b521c1199
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/Call.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/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/weaver/src/org/aspectj/weaver/ast/CallExpr.java b/weaver/src/org/aspectj/weaver/ast/CallExpr.java
new file mode 100644
index 000000000..19fe73b6b
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/CallExpr.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.Member;
+
+public class CallExpr extends Expr {
+ // assert m.return value is boolean
+ private final Member method;
+ private final Expr[] args;
+ private final ResolvedTypeX returnType; // yes, stored in method as well, but that one isn't resolved
+
+ public CallExpr(Member m, Expr[] args, ResolvedTypeX 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 ResolvedTypeX getType() {
+ return returnType;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/ast/Expr.java b/weaver/src/org/aspectj/weaver/ast/Expr.java
new file mode 100644
index 000000000..372c88114
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/Expr.java
@@ -0,0 +1,36 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.*;
+
+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 ResolvedTypeX getType();
+
+ public static FieldGet makeFieldGet(Member myField, ResolvedTypeX inAspect) {
+ return new FieldGet(myField, inAspect);
+ }
+ public static Expr makeCallExpr(Member member, Expr[] exprs, ResolvedTypeX returnType) {
+ return new CallExpr(member, exprs, returnType);
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/ast/FieldGet.java b/weaver/src/org/aspectj/weaver/ast/FieldGet.java
new file mode 100644
index 000000000..89253b103
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/FieldGet.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.*;
+
+
+public class FieldGet extends Expr {
+ Member field;
+ ResolvedTypeX resolvedType;
+
+ public FieldGet(Member field, ResolvedTypeX resolvedType) {
+ super();
+ this.field = field;
+ this.resolvedType = resolvedType;
+ }
+
+ public ResolvedTypeX getType() {
+ return resolvedType;
+ }
+
+ public String toString() {
+ return "(FieldGet " + field + ")";
+ }
+
+ public void accept(IExprVisitor v) {
+ v.visit(this);
+ }
+ public Member getField() {
+ return field;
+ }
+
+ public ResolvedTypeX getResolvedType() {
+ return resolvedType;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/ast/FieldGetCall.java b/weaver/src/org/aspectj/weaver/ast/FieldGetCall.java
new file mode 100644
index 000000000..e3d19938b
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/FieldGetCall.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/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/weaver/src/org/aspectj/weaver/ast/IExprVisitor.java b/weaver/src/org/aspectj/weaver/ast/IExprVisitor.java
new file mode 100644
index 000000000..38b53ffb3
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/IExprVisitor.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/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/weaver/src/org/aspectj/weaver/ast/ITestVisitor.java b/weaver/src/org/aspectj/weaver/ast/ITestVisitor.java
new file mode 100644
index 000000000..1787ea62e
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/ITestVisitor.java
@@ -0,0 +1,27 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+
+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);
+
+}
diff --git a/weaver/src/org/aspectj/weaver/ast/Instanceof.java b/weaver/src/org/aspectj/weaver/ast/Instanceof.java
new file mode 100644
index 000000000..ad2d85ecb
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/Instanceof.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.TypeX;
+
+public class Instanceof extends Test {
+ Var var;
+ TypeX type;
+
+ public Instanceof(Var left, TypeX 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 Var getVar() {
+ return var;
+ }
+
+ public TypeX getType() {
+ return type;
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/ast/Literal.java b/weaver/src/org/aspectj/weaver/ast/Literal.java
new file mode 100644
index 000000000..ed7388fa2
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/Literal.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+
+public 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/weaver/src/org/aspectj/weaver/ast/Not.java b/weaver/src/org/aspectj/weaver/ast/Not.java
new file mode 100644
index 000000000..7333e8a87
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/Not.java
@@ -0,0 +1,45 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+
+public class Not extends Test {
+ Test body;
+
+ public Not(Test left) {
+ super();
+ this.body = left;
+ }
+
+ public void accept(ITestVisitor v) {
+ v.visit(this);
+ }
+
+ public Test getBody() {
+ return body;
+ }
+
+ public String toString() {
+ return "!" + body;
+ }
+
+ public boolean equals(Object other) {
+ if (other instanceof Not) {
+ Not o = (Not) other;
+ return o.body.equals(body);
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/ast/Or.java b/weaver/src/org/aspectj/weaver/ast/Or.java
new file mode 100644
index 000000000..0f9575dbb
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/Or.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/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 Test getLeft() {
+ return left;
+ }
+
+ public Test getRight() {
+ return right;
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/ast/Test.java b/weaver/src/org/aspectj/weaver/ast/Test.java
new file mode 100644
index 000000000..d7385a547
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/Test.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ResolvedTypeX;
+
+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, ResolvedTypeX ty) {
+ if (ty.equals(ResolvedTypeX.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 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/weaver/src/org/aspectj/weaver/ast/Var.java b/weaver/src/org/aspectj/weaver/ast/Var.java
new file mode 100644
index 000000000..52246f3c6
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ast/Var.java
@@ -0,0 +1,38 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.*;
+
+
+public class Var extends Expr {
+ ResolvedTypeX type;
+
+ public Var(ResolvedTypeX type) {
+ super();
+ this.type = type;
+ }
+
+ public ResolvedTypeX getType() {
+ return type;
+ }
+
+ public String toString() {
+ return "(Var " + type + ")";
+ }
+
+ public void accept(IExprVisitor v) {
+ v.visit(this);
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java b/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java
new file mode 100644
index 000000000..b3a42edf3
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java
@@ -0,0 +1,312 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.weaver.patterns.*;
+
+/**
+ * Advice implemented for bcel.
+ *
+ * @author Erik Hilsdale
+ * @author Jim Hugunin
+ */
+public class BcelAdvice extends Advice {
+ private Test pointcutTest;
+ private ExposedState exposedState;
+
+ public BcelAdvice(AdviceKind kind, Pointcut pointcut, Member signature,
+ int extraArgumentFlags,
+ int start, int end, ISourceContext sourceContext, ResolvedTypeX concreteAspect)
+ {
+ super(kind, pointcut, signature, extraArgumentFlags, start, end, sourceContext);
+ this.concreteAspect = concreteAspect;
+ }
+
+ // ---- implementations of ShadowMunger's methods
+
+ public void specializeOn(Shadow shadow) {
+ if (getKind() == AdviceKind.Around) {
+ ((BcelShadow)shadow).initializeForAroundClosure();
+ }
+
+ //XXX this case is just here for supporting lazy test code
+ if (getKind() == null) {
+ exposedState = new ExposedState(0);
+ return;
+ }
+ if (getKind().isPerEntry()) {
+ exposedState = new ExposedState(0);
+ } else if (getKind().isCflow()) {
+ exposedState = new ExposedState(nFreeVars);
+ } else if (getSignature() != null) {
+ exposedState = new ExposedState(getSignature());
+ } else {
+ exposedState = new ExposedState(0);
+ return; //XXX this case is just here for supporting lazy test code
+ }
+ pointcutTest = getPointcut().findResidue(shadow, exposedState);
+
+ // make sure thisJoinPoint parameters are initialized
+ if ((extraParameterFlags & ThisJoinPoint) != 0) {
+ ((BcelShadow)shadow).getThisJoinPointVar();
+ }
+
+ if ((extraParameterFlags & ThisJoinPointStaticPart) != 0) {
+ ((BcelShadow)shadow).getThisJoinPointStaticPartVar();
+ }
+
+ if ((extraParameterFlags & ThisEnclosingJoinPointStaticPart) != 0) {
+ ((BcelShadow)shadow).getThisEnclosingJoinPointStaticPartVar();
+ }
+ }
+
+ public void implementOn(Shadow s) {
+ BcelShadow shadow = (BcelShadow) s;
+ if (getKind() == AdviceKind.Before) {
+ shadow.weaveBefore(this);
+ } else if (getKind() == AdviceKind.AfterReturning) {
+ shadow.weaveAfterReturning(this);
+ } else if (getKind() == AdviceKind.AfterThrowing) {
+ TypeX catchType =
+ hasExtraParameter()
+ ? getExtraParameterType()
+ : TypeX.THROWABLE;
+ shadow.weaveAfterThrowing(this, catchType);
+ } else if (getKind() == AdviceKind.After) {
+ shadow.weaveAfter(this);
+ } else if (getKind() == AdviceKind.Around) {
+ shadow.weaveAroundClosure(this, hasDynamicTests());
+ } else if (getKind() == AdviceKind.InterInitializer) {
+ shadow.weaveAfterReturning(this);
+ } else if (getKind().isCflow()) {
+ shadow.weaveCflowEntry(this, getSignature());
+ } else if (getKind() == AdviceKind.PerThisEntry) {
+ shadow.weavePerObjectEntry(this, (BcelVar)shadow.getThisVar());
+ } else if (getKind() == AdviceKind.PerTargetEntry) {
+ shadow.weavePerObjectEntry(this, (BcelVar)shadow.getTargetVar());
+ } else if (getKind() == AdviceKind.Softener) {
+ shadow.weaveSoftener(this, ((ExactTypePattern)exceptionType).getType());
+ } else {
+ throw new BCException("unimplemented kind: " + getKind());
+ }
+ }
+
+ // ---- implementations
+
+ // only call me after prepare has been called
+ public boolean hasDynamicTests() {
+// if (hasExtraParameter() && getKind() == AdviceKind.AfterReturning) {
+// TypeX extraParameterType = getExtraParameterType();
+// if (! extraParameterType.equals(TypeX.OBJECT)
+// && ! extraParameterType.isPrimitive())
+// return true;
+// }
+
+
+ return pointcutTest != null &&
+ !(pointcutTest == Literal.TRUE);// || pointcutTest == Literal.NO_TEST);
+ }
+
+
+ /**
+ * get the instruction list for the really simple version of this advice.
+ * Is broken apart
+ * for other advice, but if you want it in one block, this is the method to call.
+ *
+ * @param s The shadow around which these instructions will eventually live.
+ * @param extraArgVar The var that will hold the return value or thrown exception
+ * for afterX advice
+ * @param ifNoAdvice The instructionHandle to jump to if the dynamic
+ * tests for this munger fails.
+ */
+ InstructionList getAdviceInstructions(
+ BcelShadow s,
+ BcelVar extraArgVar,
+ InstructionHandle ifNoAdvice)
+ {
+ BcelShadow shadow = (BcelShadow) s;
+ InstructionFactory fact = shadow.getFactory();
+ BcelWorld world = shadow.getWorld();
+
+ InstructionList il = new InstructionList();
+
+ // we test to see if we have the right kind of thing...
+ // after throwing does this just by the exception mechanism.
+ if (hasExtraParameter() && getKind() == AdviceKind.AfterReturning) {
+ TypeX extraParameterType = getExtraParameterType();
+ if (! extraParameterType.equals(TypeX.OBJECT)
+ && ! extraParameterType.isPrimitive()) {
+ il.append(
+ BcelRenderer.renderTest(
+ fact,
+ world,
+ Test.makeInstanceof(
+ extraArgVar, getExtraParameterType().resolve(world)),
+ null,
+ ifNoAdvice,
+ null));
+ }
+ }
+ il.append(getAdviceArgSetup(shadow, extraArgVar, null));
+ il.append(getNonTestAdviceInstructions(shadow));
+
+ InstructionHandle ifYesAdvice = il.getStart();
+ il.insert(getTestInstructions(shadow, ifYesAdvice, ifNoAdvice, ifYesAdvice));
+ return il;
+ }
+
+ public InstructionList getAdviceArgSetup(
+ BcelShadow shadow,
+ BcelVar extraVar,
+ InstructionList closureInstantiation)
+ {
+ InstructionFactory fact = shadow.getFactory();
+ BcelWorld world = shadow.getWorld();
+ InstructionList il = new InstructionList();
+
+// if (targetAspectField != null) {
+// il.append(fact.createFieldAccess(
+// targetAspectField.getDeclaringType().getName(),
+// targetAspectField.getName(),
+// BcelWorld.makeBcelType(targetAspectField.getType()),
+// Constants.GETSTATIC));
+// }
+//
+ //System.err.println("BcelAdvice: " + exposedState);
+
+
+ if (exposedState.getAspectInstance() != null) {
+ il.append(
+ BcelRenderer.renderExpr(fact, world, exposedState.getAspectInstance()));
+ }
+ for (int i = 0, len = exposedState.size(); i < len; i++) {
+ BcelVar v = (BcelVar) exposedState.get(i);
+ if (v == null) continue;
+ TypeX desiredTy = getSignature().getParameterTypes()[i];
+ v.appendLoadAndConvert(il, fact, desiredTy.resolve(world));
+ }
+
+
+ if (getKind() == AdviceKind.Around) {
+ il.append(closureInstantiation);
+ } else if (hasExtraParameter()) {
+ extraVar.appendLoadAndConvert(
+ il,
+ fact,
+ getExtraParameterType().resolve(world));
+ }
+
+ // handle thisJoinPoint parameters
+ if ((extraParameterFlags & ThisJoinPoint) != 0) {
+ shadow.getThisJoinPointBcelVar().appendLoad(il, fact);
+ }
+
+ if ((extraParameterFlags & ThisJoinPointStaticPart) != 0) {
+ shadow.getThisJoinPointStaticPartBcelVar().appendLoad(il, fact);
+ }
+
+ if ((extraParameterFlags & ThisEnclosingJoinPointStaticPart) != 0) {
+ shadow.getThisEnclosingJoinPointStaticPartBcelVar().appendLoad(il, fact);
+ }
+
+
+ return il;
+ }
+
+ public InstructionList getNonTestAdviceInstructions(BcelShadow shadow) {
+ return new InstructionList(
+ Utility.createInvoke(shadow.getFactory(), shadow.getWorld(), getSignature()));
+ }
+
+ public InstructionList getTestInstructions(
+ BcelShadow shadow,
+ InstructionHandle sk,
+ InstructionHandle fk,
+ InstructionHandle next)
+ {
+ //System.err.println("test: " + pointcutTest);
+ return BcelRenderer.renderTest(
+ shadow.getFactory(),
+ shadow.getWorld(),
+ pointcutTest,
+ sk,
+ fk,
+ next);
+ }
+
+ public int compareTo(Object other) {
+ if (!(other instanceof BcelAdvice)) return 0;
+ BcelAdvice o = (BcelAdvice)other;
+
+ //System.err.println("compareTo: " + this + ", " + o);
+ if (kind.getPrecedence() != o.kind.getPrecedence()) {
+ if (kind.getPrecedence() > o.kind.getPrecedence()) return +1;
+ else return -1;
+ }
+
+ if (kind.isCflow()) {
+ if (this.innerCflowEntries.contains(o)) return -1;
+ else if (o.innerCflowEntries.contains(this)) return +1;
+ else return 0;
+ }
+
+
+ if (kind.isPerEntry() || kind == AdviceKind.Softener) {
+ return 0;
+ }
+
+ //System.out.println("compare: " + this + " with " + other);
+ World world = concreteAspect.getWorld();
+
+ int ret =
+ concreteAspect.getWorld().compareByDominates(
+ concreteAspect,
+ o.concreteAspect);
+ if (ret != 0) return ret;
+
+
+ ResolvedTypeX declaringAspect = getDeclaringAspect().resolve(world);
+ ResolvedTypeX o_declaringAspect = o.getDeclaringAspect().resolve(world);
+
+
+ if (declaringAspect == o_declaringAspect) {
+ if (kind.isAfter() || o.kind.isAfter()) {
+ return this.lexicalPosition < o.lexicalPosition ? -1: +1;
+ } else {
+ return this.lexicalPosition < o.lexicalPosition ? +1: -1;
+ }
+ } else if (declaringAspect.isAssignableFrom(o_declaringAspect)) {
+ return -1;
+ } else if (o_declaringAspect.isAssignableFrom(declaringAspect)) {
+ return +1;
+ } else {
+ return 0;
+ }
+ }
+
+ public BcelVar[] getExposedStateAsBcelVars() {
+ //System.out.println("vars: " + Arrays.asList(exposedState.vars));
+ if (exposedState == null) return BcelVar.NONE;
+ int len = exposedState.vars.length;
+ BcelVar[] ret = new BcelVar[len];
+ for (int i=0; i < len; i++) {
+ ret[i] = (BcelVar)exposedState.vars[i];
+ }
+ return ret; //(BcelVar[]) exposedState.vars;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelAttributes.java b/weaver/src/org/aspectj/weaver/bcel/BcelAttributes.java
new file mode 100644
index 000000000..840d7b04b
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelAttributes.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.util.*;
+
+import org.apache.bcel.classfile.*;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.AjAttribute;
+
+
+// this is a class o' static methods for reading attributes. It's pretty much a bridge from
+// bcel to AjAttribute.
+class BcelAttributes {
+
+ public static List readAjAttributes(Attribute[] as, ISourceContext context) {
+ List l = new ArrayList();
+ for (int i = as.length - 1; i >= 0; i--) {
+ Attribute a = as[i];
+ if (a instanceof Unknown) {
+ Unknown u = (Unknown) a;
+ String name = u.getName();
+ if (name.startsWith(AjAttribute.AttributePrefix)) {
+ l.add(AjAttribute.read(name, u.getBytes(), context));
+ }
+ }
+ }
+ return l;
+ }
+
+ public static Attribute bcelAttribute(AjAttribute a, ConstantPoolGen pool) {
+ int nameIndex = pool.addUtf8(a.getNameString());
+ byte[] bytes = a.getBytes();
+ int length = bytes.length;
+
+ return new Unknown(nameIndex, length, bytes, pool.getConstantPool());
+
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelCflowAccessVar.java b/weaver/src/org/aspectj/weaver/bcel/BcelCflowAccessVar.java
new file mode 100644
index 000000000..a04bcc292
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelCflowAccessVar.java
@@ -0,0 +1,92 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ResolvedTypeX;
+import org.aspectj.weaver.ast.Var;
+
+/**
+ * XXX Erik and I need to discuss this hierarchy. Having FieldRef
+ * extend Var is convenient, but hopefully there's a better design.
+ *
+ * This is always a static reference.
+ */
+public class BcelCflowAccessVar extends BcelVar {
+
+
+ private Member stackField;
+ private int index;
+
+ /**
+ * @param type The type to convert to from Object
+ * @param stackField the member containing the CFLOW_STACK_TYPE
+ * @param index yeah yeah
+ */
+ public BcelCflowAccessVar(ResolvedTypeX type, Member stackField, int index) {
+ super(type, 0);
+ this.stackField = stackField;
+ this.index = index;
+ }
+
+ public String toString() {
+ return "BcelCflowAccessVar(" + getType() + " " + stackField + "." + index + ")";
+ }
+
+ public Instruction createLoad(InstructionFactory fact) {
+ throw new RuntimeException("unimplemented");
+ }
+ public Instruction createStore(InstructionFactory fact) {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public void appendLoad(InstructionList il, InstructionFactory fact) {
+ il.append(createLoadInstructions(getType(), fact));
+ }
+
+ public InstructionList createLoadInstructions(ResolvedTypeX toType, InstructionFactory fact) {
+ InstructionList il = new InstructionList();
+
+ il.append(Utility.createGet(fact, stackField));
+ il.append(Utility.createConstant(fact, index));
+ il.append(
+ fact.createInvoke(
+ NameMangler.CFLOW_STACK_TYPE, "get",
+ Type.OBJECT, new Type[] { Type.INT },
+ Constants.INVOKEVIRTUAL));
+ il.append(Utility.createConversion(fact, Type.OBJECT, BcelWorld.makeBcelType(toType)));
+
+ return il;
+
+ }
+
+ public void appendLoadAndConvert(
+ InstructionList il,
+ InstructionFactory fact,
+ ResolvedTypeX toType) {
+ il.append(createLoadInstructions(toType, fact));
+
+ }
+
+ public void insertLoad(InstructionList il, InstructionFactory fact) {
+ il.insert(createLoadInstructions(getType(), fact));
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelCflowStackFieldAdder.java b/weaver/src/org/aspectj/weaver/bcel/BcelCflowStackFieldAdder.java
new file mode 100644
index 000000000..c398cec63
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelCflowStackFieldAdder.java
@@ -0,0 +1,72 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.Field;
+import org.apache.bcel.generic.*;
+import org.apache.bcel.generic.FieldGen;
+import org.aspectj.weaver.*;
+
+public class BcelCflowStackFieldAdder extends BcelTypeMunger {
+ private ResolvedMember cflowStackField;
+ public BcelCflowStackFieldAdder(ResolvedMember cflowStackField) {
+ super(null, null);
+ this.cflowStackField = cflowStackField;
+ }
+
+ public boolean munge(BcelClassWeaver weaver) {
+ LazyClassGen gen = weaver.getLazyClassGen();
+ if (!gen.getType().equals(cflowStackField.getDeclaringType())) return false;
+
+ Field f = new FieldGen(cflowStackField.getModifiers(),
+ BcelWorld.makeBcelType(cflowStackField.getReturnType()),
+ cflowStackField.getName(),
+ gen.getConstantPoolGen()).getField();
+ gen.addField(f);
+
+ LazyMethodGen clinit = gen.getStaticInitializer();
+ InstructionList setup = new InstructionList();
+ InstructionFactory fact = gen.getFactory();
+
+ setup.append(fact.createNew(new ObjectType(NameMangler.CFLOW_STACK_TYPE)));
+ setup.append(fact.createDup(1));
+ setup.append(fact.createInvoke(
+ NameMangler.CFLOW_STACK_TYPE,
+ "<init>",
+ Type.VOID,
+ new Type[0],
+ Constants.INVOKESPECIAL));
+
+
+ setup.append(Utility.createSet(fact, cflowStackField));
+ clinit.getBody().insert(setup);
+
+ return true;
+ }
+
+
+ public ResolvedMember getMatchingSyntheticMember(Member member) {
+ return null;
+ }
+
+ public ResolvedMember getSignature() {
+ return cflowStackField;
+ }
+
+ public boolean matches(ResolvedTypeX onType) {
+ return onType.equals(cflowStackField.getDeclaringType());
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
new file mode 100644
index 000000000..74d2ace0f
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
@@ -0,0 +1,889 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.util.*;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.generic.*;
+import org.aspectj.util.PartialOrder;
+import org.aspectj.weaver.*;
+
+class BcelClassWeaver implements IClassWeaver {
+
+ /**
+ * This is called from {@link BcelWeaver} to perform the per-class weaving process.
+ */
+ public static boolean weave(
+ BcelWorld world,
+ LazyClassGen clazz,
+ List shadowMungers,
+ List typeMungers)
+ {
+ boolean b = new BcelClassWeaver(world, clazz, shadowMungers, typeMungers).weave();
+ //clazz.print();
+ return b;
+ }
+
+ // --------------------------------------------
+
+ private final LazyClassGen clazz;
+ private final List shadowMungers;
+ private final List typeMungers;
+
+ private final BcelObjectType ty; // alias of clazz.getType()
+ private final BcelWorld world; // alias of ty.getWorld()
+ private final ConstantPoolGen cpg; // alias of clazz.getConstantPoolGen()
+ private final InstructionFactory fact; // alias of clazz.getFactory();
+
+
+ private final List addedLazyMethodGens = new ArrayList();
+ private final Set addedDispatchTargets = new HashSet();
+
+
+ private List addedSuperInitializersAsList = null; // List<IfaceInitList>
+ private final Map addedSuperInitializers = new HashMap(); // Interface -> IfaceInitList
+ private List addedThisInitializers = new ArrayList(); // List<NewFieldMunger>
+ private List addedClassInitializers = new ArrayList(); // List<NewFieldMunger>
+
+ private BcelShadow clinitShadow = null;
+
+
+
+ /**
+ * This holds the initialization and pre-initialization shadows for this class
+ * that were actually matched by mungers (if no match, then we don't even create the
+ * shadows really).
+ */
+ private final List initializationShadows = new ArrayList(1);
+
+ private BcelClassWeaver(
+ BcelWorld world,
+ LazyClassGen clazz,
+ List shadowMungers,
+ List typeMungers)
+ {
+ super();
+ // assert world == clazz.getType().getWorld()
+ this.world = world;
+ this.clazz = clazz;
+ this.shadowMungers = shadowMungers;
+ this.typeMungers = typeMungers;
+ this.ty = clazz.getType();
+ this.cpg = clazz.getConstantPoolGen();
+ this.fact = clazz.getFactory();
+ initializeSuperInitializerMap(ty);
+ }
+
+ // --------------------------------------------
+
+ private void initializeSuperInitializerMap(ResolvedTypeX child) {
+ ResolvedTypeX[] superInterfaces = child.getDeclaredInterfaces();
+ for (int i=0, len=superInterfaces.length; i < len; i++) {
+ if (ty.isTopmostImplementor(superInterfaces[i])) {
+ if (addSuperInitializer(superInterfaces[i])) {
+ initializeSuperInitializerMap(superInterfaces[i]);
+ }
+ }
+ }
+ }
+
+ private boolean addSuperInitializer(ResolvedTypeX onType) {
+ IfaceInitList l = (IfaceInitList) addedSuperInitializers.get(onType);
+ if (l != null) return false;
+ l = new IfaceInitList(onType);
+ addedSuperInitializers.put(onType, l);
+ return true;
+ }
+
+ public void addInitializer(ConcreteTypeMunger cm) {
+ NewFieldTypeMunger m = (NewFieldTypeMunger) cm.getMunger();
+ ResolvedTypeX onType = m.getSignature().getDeclaringType().resolve(world);
+ if (m.getSignature().isStatic()) {
+ addedClassInitializers.add(cm);
+ } else {
+ if (onType == ty) {
+ addedThisInitializers.add(cm);
+ } else {
+ IfaceInitList l = (IfaceInitList) addedSuperInitializers.get(onType);
+ l.list.add(cm);
+ }
+ }
+ }
+
+ private static class IfaceInitList implements PartialOrder.PartialComparable {
+ final ResolvedTypeX onType;
+ List list = new ArrayList();
+ IfaceInitList(ResolvedTypeX onType) {
+ this.onType = onType;
+ }
+
+ public int compareTo(Object other) {
+ IfaceInitList o = (IfaceInitList)other;
+ if (onType.isAssignableFrom(o.onType)) return +1;
+ else if (o.onType.isAssignableFrom(onType)) return -1;
+ else return 0;
+ }
+
+ public int fallbackCompareTo(Object other) {
+ return 0;
+ }
+ }
+
+ // XXX this is being called, but the result doesn't seem to be being used
+ public boolean addDispatchTarget(ResolvedMember m) {
+ return addedDispatchTargets.add(m);
+ }
+
+ public void addLazyMethodGen(LazyMethodGen gen) {
+ addedLazyMethodGens.add(gen);
+ }
+
+ public void addOrReplaceLazyMethodGen(LazyMethodGen mg) {
+ if (alreadyDefined(clazz, mg)) return;
+
+ for (Iterator i = addedLazyMethodGens.iterator(); i.hasNext(); ) {
+ LazyMethodGen existing = (LazyMethodGen)i.next();
+ if (signaturesMatch(mg, existing)) {
+ if (existing.definingType == null) {
+ // this means existing was introduced on the class itself
+ return;
+ } else if (mg.definingType.isAssignableFrom(existing.definingType)) {
+ // existing is mg's subtype and dominates mg
+ return;
+ } else if (existing.definingType.isAssignableFrom(mg.definingType)) {
+ // mg is existing's subtype and dominates existing
+ i.remove();
+ addedLazyMethodGens.add(mg);
+ return;
+ } else {
+ throw new BCException("conflict between: " + mg + " and " + existing);
+ }
+ }
+ }
+ addedLazyMethodGens.add(mg);
+ }
+
+ private boolean alreadyDefined(LazyClassGen clazz, LazyMethodGen mg) {
+ for (Iterator i = clazz.getMethodGens().iterator(); i.hasNext(); ) {
+ if (signaturesMatch(mg, (LazyMethodGen)i.next())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean signaturesMatch(LazyMethodGen mg, LazyMethodGen existing) {
+ return mg.getName().equals(existing.getName()) &&
+ mg.getSignature().equals(existing.getSignature());
+ }
+
+ // ----
+
+ public boolean weave() {
+ if (clazz.getWeaverState().isWoven()) {
+ throw new RuntimeException("already woven: " + clazz);
+ }
+
+ boolean isChanged = false;
+
+ // we want to "touch" all aspects
+ if (clazz.getType().isAspect()) isChanged = true;
+
+
+ // start by munging all typeMungers
+ for (Iterator i = typeMungers.iterator(); i.hasNext(); ) {
+ BcelTypeMunger munger = (BcelTypeMunger)i.next();
+ isChanged |= munger.munge(this);
+ }
+
+ // XXX do major sort of stuff
+ // sort according to: Major: type hierarchy
+ // within each list: dominates
+ // don't forget to sort addedThisInitialiers according to dominates
+ addedSuperInitializersAsList = new ArrayList(addedSuperInitializers.values());
+ addedSuperInitializersAsList = PartialOrder.sort(addedSuperInitializersAsList);
+ if (addedSuperInitializersAsList == null) {
+ throw new BCException("circularity in inter-types");
+ }
+
+ // this will create a static initializer if there isn't one
+ // this is in just as bad taste as NOPs
+ LazyMethodGen staticInit = clazz.getStaticInitializer();
+ staticInit.getBody().insert(genInitInstructions(addedClassInitializers, true));
+
+
+ // now go through each method, and match against each method. This
+ // sets up each method's {@link LazyMethodGen#matchedShadows} field,
+ // and it also possibly adds to {@link #initializationShadows}.
+ List methodGens = new ArrayList(clazz.getMethodGens());
+ for (Iterator i = methodGens.iterator(); i.hasNext();) {
+ LazyMethodGen mg = (LazyMethodGen)i.next();
+ if (! mg.hasBody()) continue;
+ isChanged |= match(mg);
+ }
+ if (! isChanged) return false;
+
+ // now we weave all but the initialization shadows
+ for (Iterator i = methodGens.iterator(); i.hasNext();) {
+ LazyMethodGen mg = (LazyMethodGen)i.next();
+ if (! mg.hasBody()) continue;
+ implement(mg);
+ }
+
+
+ // if we matched any initialization shadows, we inline and weave
+ if (! initializationShadows.isEmpty()) {
+ inlineSelfConstructors(methodGens);
+ positionAndImplement(initializationShadows);
+ }
+
+
+ // finally, if we changed, we add in the introduced methods.
+ if (isChanged) {
+ clazz.setWeaverState(WeaverStateKind.Woven);
+ weaveInAddedMethods();
+ }
+
+ return isChanged;
+ }
+
+
+ private void inlineSelfConstructors(List methodGens) {
+ for (Iterator i = methodGens.iterator(); i.hasNext();) {
+ LazyMethodGen mg = (LazyMethodGen) i.next();
+ if (! mg.getName().equals("<init>")) continue;
+ InstructionHandle ih = findSuperOrThisCall(mg);
+ if (ih != null && isThisCall(ih)) {
+ LazyMethodGen donor = getCalledMethod(ih);
+ inlineMethod(donor, mg, ih);
+ }
+ }
+ }
+
+ private void positionAndImplement(List initializationShadows) {
+ for (Iterator i = initializationShadows.iterator(); i.hasNext(); ) {
+ BcelShadow s = (BcelShadow) i.next();
+ positionInitializationShadow(s);
+ //s.getEnclosingMethod().print();
+ s.implement();
+ }
+ }
+
+ private void positionInitializationShadow(BcelShadow s) {
+ LazyMethodGen mg = s.getEnclosingMethod();
+ InstructionHandle call = findSuperOrThisCall(mg);
+ InstructionList body = mg.getBody();
+ ShadowRange r = new ShadowRange(body);
+ r.associateWithShadow((BcelShadow) s);
+ if (s.getKind() == Shadow.PreInitialization) {
+ // XXX assert first instruction is an ALOAD_0.
+ // a pre shadow goes from AFTER the first instruction (which we believe to
+ // be an ALOAD_0) to just before the call to super
+ r.associateWithTargets(
+ Range.genStart(body, body.getStart().getNext()),
+ Range.genEnd(body, call.getPrev()));
+ } else {
+ // assert s.getKind() == Shadow.Initialization
+ r.associateWithTargets(
+ Range.genStart(body, call.getNext()),
+ Range.genEnd(body));
+ }
+ }
+
+ private boolean isThisCall(InstructionHandle ih) {
+ INVOKESPECIAL inst = (INVOKESPECIAL) ih.getInstruction();
+ return inst.getClassName(cpg).equals(clazz.getName());
+ }
+
+
+ /** inline a particular call in bytecode.
+ *
+ * @param donor the method we want to inline
+ * @param recipient the method containing the call we want to inline
+ * @param call the instructionHandle in recipient's body holding the call we want to
+ * inline.
+ */
+ public static void inlineMethod(
+ LazyMethodGen donor,
+ LazyMethodGen recipient,
+ InstructionHandle call)
+ {
+ // assert recipient.contains(call)
+
+ /* Implementation notes:
+ *
+ * We allocate two slots for every tempvar so we don't screw up
+ * longs and doubles which may share space. This could be conservatively avoided
+ * (no reference to a long/double instruction, don't do it) or packed later.
+ * Right now we don't bother to pack.
+ *
+ * Allocate a new var for each formal param of the inlined. Fill with stack
+ * contents. Then copy the inlined instructions in with the appropriate remap
+ * table. Any framelocs used by locals in inlined are reallocated to top of
+ * frame,
+ */
+ final InstructionFactory fact = recipient.getEnclosingClass().getFactory();
+
+ IntMap frameEnv = new IntMap();
+
+ // this also sets up the initial environment
+ InstructionList argumentStores =
+ genArgumentStores(donor, recipient, frameEnv, fact);
+
+ InstructionList inlineInstructions =
+ genInlineInstructions(donor, recipient, frameEnv, fact);
+
+ inlineInstructions.insert(argumentStores);
+
+ recipient.getBody().append(call, inlineInstructions);
+ Utility.deleteInstruction(call, recipient);
+ }
+
+ /** generate the instructions to be inlined.
+ *
+ * @param donor the method from which we will copy (and adjust frame and jumps)
+ * instructions.
+ * @param recipient the method the instructions will go into. Used to get the frame
+ * size so we can allocate new frame locations for locals in donor.
+ * @param frameEnv an environment to map from donor frame to recipient frame,
+ * initially populated with argument locations.
+ * @param fact an instruction factory for recipient
+ */
+ private static InstructionList genInlineInstructions(
+ LazyMethodGen donor,
+ LazyMethodGen recipient,
+ IntMap frameEnv,
+ InstructionFactory fact)
+ {
+ InstructionList footer = new InstructionList();
+ InstructionHandle end = footer.append(fact.NOP);
+
+ InstructionList ret = new InstructionList();
+ InstructionList sourceList = donor.getBody();
+
+ Map srcToDest = new HashMap();
+ ConstantPoolGen donorCpg = donor.getEnclosingClass().getConstantPoolGen();
+ ConstantPoolGen recipientCpg = recipient.getEnclosingClass().getConstantPoolGen();
+
+ boolean isAcrossClass = donorCpg != recipientCpg;
+
+ // first pass: copy the instructions directly, populate the srcToDest map,
+ // fix frame instructions
+ for (InstructionHandle src = sourceList.getStart();
+ src != null;
+ src = src.getNext())
+ {
+ Instruction fresh = src.getInstruction().copy();
+ InstructionHandle dest;
+ if (fresh instanceof CPInstruction) {
+ // need to reset index to go to new constant pool. This is totally
+ // a computation leak... we're testing this LOTS of times. Sigh.
+ if (isAcrossClass) {
+ CPInstruction cpi = (CPInstruction) fresh;
+ cpi.setIndex(recipientCpg.addConstant(donorCpg.getConstant(cpi.getIndex()), donorCpg));
+ }
+ }
+ if (src.getInstruction() == Range.RANGEINSTRUCTION) {
+ dest = ret.append(Range.RANGEINSTRUCTION);
+ } else if (fresh instanceof ReturnInstruction) {
+ dest = ret.append(fact.createBranchInstruction(Constants.GOTO, end));
+ } else if (fresh instanceof BranchInstruction) {
+ dest = ret.append((BranchInstruction) fresh);
+ } else if (
+ fresh instanceof LocalVariableInstruction || fresh instanceof RET) {
+ IndexedInstruction indexed = (IndexedInstruction) fresh;
+ int oldIndex = indexed.getIndex();
+ int freshIndex;
+ if (!frameEnv.hasKey(oldIndex)) {
+ freshIndex = recipient.allocateLocal(2);
+ frameEnv.put(oldIndex, freshIndex);
+ } else {
+ freshIndex = frameEnv.get(oldIndex);
+ }
+ indexed.setIndex(freshIndex);
+ dest = ret.append(fresh);
+ } else {
+ dest = ret.append(fresh);
+ }
+ srcToDest.put(src, dest);
+ }
+
+ // second pass: retarget branch instructions, copy ranges and tags
+ Map tagMap = new HashMap();
+ Map shadowMap = new HashMap();
+ for (InstructionHandle dest = ret.getStart(), src = sourceList.getStart();
+ dest != null;
+ dest = dest.getNext(), src = src.getNext()) {
+ Instruction inst = dest.getInstruction();
+
+ // retarget branches
+ if (inst instanceof BranchInstruction) {
+ BranchInstruction branch = (BranchInstruction) inst;
+ InstructionHandle oldTarget = branch.getTarget();
+ InstructionHandle newTarget =
+ (InstructionHandle) srcToDest.get(oldTarget);
+ if (newTarget == null) {
+ // assert this is a GOTO
+ // this was a return instruction we previously replaced
+ } else {
+ branch.setTarget(newTarget);
+ if (branch instanceof Select) {
+ Select select = (Select) branch;
+ InstructionHandle[] oldTargets = select.getTargets();
+ for (int k = oldTargets.length - 1; k >= 0; k--) {
+ select.setTarget(
+ k,
+ (InstructionHandle) srcToDest.get(oldTargets[k]));
+ }
+ }
+ }
+ }
+
+ //copy over tags and range attributes
+ InstructionTargeter[] srcTargeters = src.getTargeters();
+ if (srcTargeters != null) {
+ for (int j = srcTargeters.length - 1; j >= 0; j--) {
+ InstructionTargeter old = srcTargeters[j];
+ if (old instanceof Tag) {
+ Tag oldTag = (Tag) old;
+ Tag fresh = (Tag) tagMap.get(oldTag);
+ if (fresh == null) {
+ fresh = oldTag.copy();
+ tagMap.put(oldTag, fresh);
+ }
+ dest.addTargeter(fresh);
+ } else if (old instanceof ExceptionRange) {
+ ExceptionRange er = (ExceptionRange) old;
+ if (er.getStart() == src) {
+ ExceptionRange freshEr =
+ new ExceptionRange(
+ recipient.getBody(),
+ er.getCatchType(),
+ er.getPriority());
+ freshEr.associateWithTargets(
+ dest,
+ (InstructionHandle)srcToDest.get(er.getEnd()),
+ (InstructionHandle)srcToDest.get(er.getHandler()));
+ }
+ } else if (old instanceof ShadowRange) {
+ ShadowRange oldRange = (ShadowRange) old;
+ if (oldRange.getStart() == src) {
+ BcelShadow oldShadow = oldRange.getShadow();
+ BcelShadow freshEnclosing =
+ oldShadow.getEnclosingShadow() == null
+ ? null
+ : (BcelShadow) shadowMap.get(oldShadow.getEnclosingShadow());
+ BcelShadow freshShadow =
+ oldShadow.copyInto(recipient, freshEnclosing);
+ ShadowRange freshRange = new ShadowRange(recipient.getBody());
+ freshRange.associateWithShadow(freshShadow);
+ freshRange.associateWithTargets(
+ dest,
+ (InstructionHandle) srcToDest.get(oldRange.getEnd()));
+ shadowMap.put(oldRange, freshRange);
+ //recipient.matchedShadows.add(freshShadow);
+ }
+ }
+ }
+ }
+ }
+ ret.append(footer);
+ return ret;
+ }
+
+ /** generate the argument stores in preparation for inlining.
+ *
+ * @param donor the method we will inline from. Used to get the signature.
+ * @param recipient the method we will inline into. Used to get the frame size
+ * so we can allocate fresh locations.
+ * @param frameEnv an empty environment we populate with a map from donor frame to
+ * recipient frame.
+ * @param fact an instruction factory for recipient
+ */
+ private static InstructionList genArgumentStores(
+ LazyMethodGen donor,
+ LazyMethodGen recipient,
+ IntMap frameEnv,
+ InstructionFactory fact)
+ {
+ InstructionList ret = new InstructionList();
+
+ int donorFramePos = 0;
+
+ // writing ret back to front because we're popping.
+ if (! donor.isStatic()) {
+ int targetSlot = recipient.allocateLocal(Type.OBJECT);
+ ret.insert(fact.createStore(Type.OBJECT, targetSlot));
+ frameEnv.put(donorFramePos, targetSlot);
+ donorFramePos += 1;
+ }
+ Type[] argTypes = donor.getArgumentTypes();
+ for (int i = 0, len = argTypes.length; i < len; i++) {
+ Type argType = argTypes[i];
+ int argSlot = recipient.allocateLocal(argType);
+ ret.insert(fact.createStore(argType, argSlot));
+ frameEnv.put(donorFramePos, argSlot);
+ donorFramePos += argType.getSize();
+ }
+ return ret;
+ }
+
+ /** get a called method: Assumes the called method is in this class,
+ * and the reference to it is exact (a la INVOKESPECIAL).
+ *
+ * @param ih The InvokeInstruction instructionHandle pointing to the called method.
+ */
+ private LazyMethodGen getCalledMethod(
+ InstructionHandle ih)
+ {
+ InvokeInstruction inst = (InvokeInstruction) ih.getInstruction();
+
+ String methodName = inst.getName(cpg);
+ String signature = inst.getSignature(cpg);
+
+ return clazz.getLazyMethodGen(methodName, signature);
+ }
+
+ private void weaveInAddedMethods() {
+ Collections.sort(addedLazyMethodGens,
+ new Comparator() {
+ public int compare(Object a, Object b) {
+ LazyMethodGen aa = (LazyMethodGen) a;
+ LazyMethodGen bb = (LazyMethodGen) b;
+ int i = aa.getName().compareTo(bb.getName());
+ if (i != 0) return i;
+ return aa.getSignature().compareTo(bb.getSignature());
+ }
+ }
+ );
+
+ for (Iterator i = addedLazyMethodGens.iterator(); i.hasNext(); ) {
+ clazz.addMethodGen((LazyMethodGen)i.next());
+ }
+ }
+
+ void addPerSingletonField(Member field) {
+ ObjectType aspectType = (ObjectType) BcelWorld.makeBcelType(field.getReturnType());
+ String aspectName = field.getReturnType().getName();
+
+ LazyMethodGen clinit = clazz.getStaticInitializer();
+ InstructionList setup = new InstructionList();
+ InstructionFactory fact = clazz.getFactory();
+
+ setup.append(fact.createNew(aspectType));
+ setup.append(fact.createDup(1));
+ setup.append(fact.createInvoke(
+ aspectName,
+ "<init>",
+ Type.VOID,
+ new Type[0],
+ Constants.INVOKESPECIAL));
+ setup.append(fact.createFieldAccess(aspectName, field.getName(), aspectType, Constants.PUTSTATIC));
+ clinit.getBody().insert(setup);
+ }
+
+ /**
+ * Returns null if this is not a Java constructor, and then we won't
+ * weave into it at all
+ */
+ private InstructionHandle findSuperOrThisCall(LazyMethodGen mg) {
+ int depth = 1;
+ InstructionHandle start = mg.getBody().getStart();
+ while (true) {
+ if (start == null) return null;
+
+ Instruction inst = start.getInstruction();
+ if (inst instanceof INVOKESPECIAL
+ && ((INVOKESPECIAL) inst).getName(cpg).equals("<init>")) {
+ depth--;
+ if (depth == 0) return start;
+ } else if (inst instanceof NEW) {
+ depth++;
+ }
+ start = start.getNext();
+ }
+ }
+
+ // ----
+
+ private boolean match(LazyMethodGen mg) {
+ BcelShadow enclosingShadow;
+
+ List shadowAccumulator = new ArrayList();
+ // we want to match ajsynthetic constructors...
+ if (mg.getName().equals("<init>")) {
+ // XXX the enclosing join point is wrong for things before ignoreMe.
+ InstructionHandle superOrThisCall = findSuperOrThisCall(mg);
+
+ // we don't walk bodies of things where it's a wrong constructor thingie
+ if (superOrThisCall == null) return false;
+
+ enclosingShadow = BcelShadow.makeConstructorExecution(world, mg, superOrThisCall);
+
+ // walk the body
+ if (shouldWeaveBody(mg)) { //!mg.isAjSynthetic()) {
+ for (InstructionHandle h = mg.getBody().getStart();
+ h != null;
+ h = h.getNext()) {
+ if (h == superOrThisCall)
+ continue;
+ match(mg, h, enclosingShadow, shadowAccumulator);
+ }
+ match(enclosingShadow, shadowAccumulator);
+ }
+
+ // XXX we don't do pre-inits of interfaces
+
+ // now add interface inits and cexecs
+ if (superOrThisCall != null && ! isThisCall(superOrThisCall)) {
+ InstructionHandle curr = enclosingShadow.getRange().getStart();
+ for (Iterator i = addedSuperInitializersAsList.iterator(); i.hasNext(); ) {
+ IfaceInitList l = (IfaceInitList) i.next();
+ // generate the cexec jp
+ Member ifaceInitSig = AjcMemberMaker.interfaceConstructor(l.onType);
+ BcelShadow cexecShadow =
+ BcelShadow.makeIfaceConstructorExecution(
+ world,
+ mg,
+ curr,
+ ifaceInitSig);
+ if (match(cexecShadow, shadowAccumulator)) {
+ cexecShadow.getRange().getBody().append(cexecShadow.getRange().getStart(), fact.NOP);
+ }
+ // generate the init jp around it
+ BcelShadow initShadow =
+ BcelShadow.makeIfaceInitialization(
+ world,
+ mg,
+ cexecShadow,
+ ifaceInitSig);
+ match(initShadow, shadowAccumulator);
+ // insert code in place
+ InstructionList inits = genInitInstructions(l.list, false);
+ initShadow.getRange().insert(inits, Range.InsideAfter);
+ }
+
+ // now we add our initialization code
+ InstructionList inits = genInitInstructions(addedThisInitializers, false);
+ enclosingShadow.getRange().insert(inits, Range.OutsideBefore);
+ }
+
+ // actually, you only need to inline the self constructors that are
+ // in a particular group (partition the constructors into groups where members
+ // call or are called only by those in the group). Then only inline
+ // constructors
+ // in groups where at least one initialization jp matched. Future work.
+ boolean addedInitialization =
+ match(
+ BcelShadow.makeUnfinishedInitialization(world, mg),
+ initializationShadows);
+ addedInitialization |=
+ match(
+ BcelShadow.makeUnfinishedPreinitialization(world, mg),
+ initializationShadows);
+ mg.matchedShadows = shadowAccumulator;
+ return addedInitialization || !shadowAccumulator.isEmpty();
+ } else if (!shouldWeaveBody(mg)) { //.isAjSynthetic()) {
+ return false;
+ } else {
+ if (mg.getName().equals("<clinit>")) {
+ clinitShadow = enclosingShadow = BcelShadow.makeStaticInitialization(world, mg);
+ //System.err.println(enclosingShadow);
+ } else if (mg.isAdviceMethod()) {
+ enclosingShadow = BcelShadow.makeAdviceExecution(world, mg);
+ } else {
+ AjAttribute.EffectiveSignatureAttribute effective = mg.getEffectiveSignature();
+ if (effective == null) {
+ enclosingShadow = BcelShadow.makeMethodExecution(world, mg);
+ } else if (effective.isWeaveBody()) {
+ enclosingShadow = BcelShadow.makeShadowForMethod(world, mg, effective.getShadowKind(), effective.getEffectiveSignature());
+ } else {
+ return false;
+ }
+ }
+
+ for (InstructionHandle h = mg.getBody().getStart();
+ h != null;
+ h = h.getNext()) {
+ match(mg, h, enclosingShadow, shadowAccumulator);
+ }
+ match(enclosingShadow, shadowAccumulator);
+ mg.matchedShadows = shadowAccumulator;
+ return !shadowAccumulator.isEmpty();
+ }
+ }
+
+ private boolean shouldWeaveBody(LazyMethodGen mg) {
+ if (mg.isAjSynthetic()) return mg.getName().equals("<clinit>");
+ AjAttribute.EffectiveSignatureAttribute a = mg.getEffectiveSignature();
+ if (a != null) return a.isWeaveBody();
+ return true;
+ }
+
+
+ /**
+ * first sorts the mungers, then gens the initializers in the right order
+ */
+ private InstructionList genInitInstructions(List list, boolean isStatic) {
+ list = PartialOrder.sort(list);
+ if (list == null) {
+ throw new BCException("circularity in inter-types");
+ }
+
+ InstructionList ret = new InstructionList();
+
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ ConcreteTypeMunger cmunger = (ConcreteTypeMunger) i.next();
+ NewFieldTypeMunger munger = (NewFieldTypeMunger) cmunger.getMunger();
+ ResolvedMember initMethod = munger.getInitMethod(cmunger.getAspectType());
+ if (!isStatic) ret.append(fact.ALOAD_0);
+ ret.append(Utility.createInvoke(fact, world, initMethod));
+ }
+ return ret;
+ }
+
+
+ private void match(
+ LazyMethodGen mg,
+ InstructionHandle ih,
+ BcelShadow enclosingShadow,
+ List shadowAccumulator)
+ {
+ Instruction i = ih.getInstruction();
+ if (i instanceof FieldInstruction) {
+ FieldInstruction fi = (FieldInstruction) i;
+ if (i instanceof PUTFIELD || i instanceof PUTSTATIC) {
+ match(
+ BcelShadow.makeFieldSet(world, mg, ih, enclosingShadow),
+ shadowAccumulator);
+ } else {
+ match(
+ BcelShadow.makeFieldGet(world, mg, ih, enclosingShadow),
+ shadowAccumulator);
+ }
+ } else if (i instanceof InvokeInstruction) {
+ InvokeInstruction ii = (InvokeInstruction) i;
+ if (ii.getMethodName(clazz.getConstantPoolGen()).equals("<init>")) {
+ match(
+ BcelShadow.makeConstructorCall(world, mg, ih, enclosingShadow),
+ shadowAccumulator);
+ } else if (ii instanceof INVOKESPECIAL) {
+ String onTypeName = ii.getClassName(cpg);
+ if (onTypeName.equals(mg.getEnclosingClass().getName())) {
+ // we are private
+ matchInvokeInstruction(mg, ih, ii, enclosingShadow, shadowAccumulator);
+ } else {
+ // we are a super call, and this is not a join point in AspectJ-1.{0,1}
+ }
+ } else {
+ matchInvokeInstruction(mg, ih, ii, enclosingShadow, shadowAccumulator);
+ }
+ }
+ // performance optimization... we only actually care about ASTORE instructions,
+ // since that's what every javac type thing ever uses to start a handler, but for
+ // now we'll do this for everybody.
+ if (Range.isRangeHandle(ih)) return;
+ InstructionTargeter[] targeters = ih.getTargeters();
+ if (targeters != null) {
+ for (int j = 0; j < targeters.length; j++) {
+ InstructionTargeter t = targeters[j];
+ if (t instanceof ExceptionRange) {
+ // assert t.getHandler() == ih
+ ExceptionRange er = (ExceptionRange) t;
+ if (er.getCatchType() == null) continue;
+ match(
+ BcelShadow.makeExceptionHandler(
+ world,
+ er,
+ mg, ih, enclosingShadow),
+ shadowAccumulator);
+ }
+ }
+ }
+ }
+
+ private void matchInvokeInstruction(LazyMethodGen mg,
+ InstructionHandle ih,
+ InvokeInstruction invoke,
+ BcelShadow enclosingShadow,
+ List shadowAccumulator)
+ {
+ String methodName = invoke.getName(cpg);
+ if (methodName.startsWith(NameMangler.PREFIX)) {
+ Member method =
+ world.makeMethodSignature(clazz, invoke);
+ ResolvedMember declaredSig = method.resolve(world);
+ if (declaredSig == null) return;
+ AjAttribute.EffectiveSignatureAttribute effectiveSig = declaredSig.getEffectiveSignature();
+ if (effectiveSig == null) return;
+ //System.err.println("call to inter-type member: " + effectiveSig);
+ if (effectiveSig.isWeaveBody()) return;
+
+ match(BcelShadow.makeShadowForMethodCall(world, mg, ih, enclosingShadow,
+ effectiveSig.getShadowKind(), effectiveSig.getEffectiveSignature()),
+ shadowAccumulator);
+ } else {
+ match(
+ BcelShadow.makeMethodCall(world, mg, ih, enclosingShadow),
+ shadowAccumulator);
+ }
+ }
+
+ private boolean match(BcelShadow shadow, List shadowAccumulator) {
+ //System.err.println("match: " + shadow);
+ boolean isMatched = false;
+ for (Iterator i = shadowMungers.iterator(); i.hasNext(); ) {
+ ShadowMunger munger = (ShadowMunger)i.next();
+ if (munger.match(shadow, world)) {
+ shadow.addMunger(munger);
+ isMatched = true;
+ }
+ }
+ if (isMatched) shadowAccumulator.add(shadow);
+ return isMatched;
+ }
+
+ // ----
+
+ private void implement(LazyMethodGen mg) {
+ List shadows = mg.matchedShadows;
+ if (shadows == null) return;
+ // We depend on a partial order such that inner shadows are earlier on the list
+ // than outer shadows. That's fine. This order is preserved if:
+
+ // A preceeds B iff B.getStart() is LATER THAN A.getStart().
+
+ for (Iterator i = shadows.iterator(); i.hasNext(); ) {
+ BcelShadow shadow = (BcelShadow)i.next();
+ shadow.implement();
+ }
+ mg.matchedShadows = null;
+ }
+
+ // ----
+
+ public LazyClassGen getLazyClassGen() {
+ return clazz;
+ }
+
+ public List getShadowMungers() {
+ return shadowMungers;
+ }
+
+ public BcelWorld getWorld() {
+ return world;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelField.java b/weaver/src/org/aspectj/weaver/bcel/BcelField.java
new file mode 100644
index 000000000..aa9d4cec6
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelField.java
@@ -0,0 +1,60 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.util.*;
+
+import org.apache.bcel.classfile.Field;
+import org.aspectj.weaver.*;
+
+final class BcelField extends ResolvedMember {
+
+ private Field field;
+ private boolean isAjSynthetic;
+
+ BcelField(BcelObjectType declaringType, Field field) {
+ super(
+ FIELD,
+ declaringType,
+ field.getAccessFlags(),
+ field.getName(),
+ field.getSignature());
+ this.field = field;
+ unpackAttributes(declaringType.getWorld());
+ checkedExceptions = TypeX.NONE;
+ }
+
+ // ----
+
+ BcelObjectType getBcelDeclaringType() {
+ return (BcelObjectType) getDeclaringType(); // I want covariant return types.
+ }
+
+ private void unpackAttributes(World world) {
+ List as = BcelAttributes.readAjAttributes(field.getAttributes(), getSourceContext(world));
+ for (Iterator iter = as.iterator(); iter.hasNext();) {
+ AjAttribute a = (AjAttribute) iter.next();
+ if (a instanceof AjAttribute.AjSynthetic) {
+ isAjSynthetic = true;
+ } else {
+ throw new BCException("weird field attribute " + a);
+ }
+ }
+ isAjSynthetic = false;
+ }
+
+ public boolean isAjSynthetic() {
+ return isAjSynthetic; // || getName().startsWith(NameMangler.PREFIX);
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelFieldRef.java b/weaver/src/org/aspectj/weaver/bcel/BcelFieldRef.java
new file mode 100644
index 000000000..6896f0ba4
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelFieldRef.java
@@ -0,0 +1,103 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ResolvedTypeX;
+import org.aspectj.weaver.ast.Var;
+
+/**
+ * XXX Erik and I need to discuss this hierarchy. Having FieldRef
+ * extend Var is convenient, but hopefully there's a better design.
+ *
+ * This is always a static reference.
+ */
+public class BcelFieldRef extends BcelVar {
+
+ private String className, fieldName;
+
+ public BcelFieldRef(ResolvedTypeX type, String className, String fieldName) {
+ super(type, 0);
+ this.className = className;
+ this.fieldName = fieldName;
+ }
+
+ public String toString() {
+ return "BcelFieldRef(" + getType() + " " + className + "." + fieldName + ")";
+ }
+
+ //public int getSlot() { return slot; }
+
+ public Instruction createLoad(InstructionFactory fact) {
+ return fact.createFieldAccess(className, fieldName,
+ BcelWorld.makeBcelType(getType()), Constants.GETSTATIC);
+ }
+ public Instruction createStore(InstructionFactory fact) {
+ return fact.createFieldAccess(className, fieldName,
+ BcelWorld.makeBcelType(getType()), Constants.PUTSTATIC);
+ }
+
+ public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) {
+ throw new RuntimeException("unimplemented");
+ }
+
+ // this is an array var
+// void appendConvertableArrayLoad(
+// InstructionList il,
+// InstructionFactory fact,
+// int index,
+// ResolvedTypeX convertTo)
+// {
+// ResolvedTypeX convertFromType = getType().getResolvedComponentType();
+// appendLoad(il, fact);
+// il.append(Utility.createConstant(fact, index));
+// il.append(fact.createArrayLoad(BcelWorld.makeBcelType(convertFromType)));
+// Utility.appendConversion(il, fact, convertFromType, convertTo);
+// }
+//
+// void appendConvertableArrayStore(
+// InstructionList il,
+// InstructionFactory fact,
+// int index,
+// BcelFieldRef storee)
+// {
+// ResolvedTypeX convertToType = getType().getResolvedComponentType();
+// appendLoad(il, fact);
+// il.append(Utility.createConstant(fact, index));
+// storee.appendLoad(il, fact);
+// Utility.appendConversion(il, fact, storee.getType(), convertToType);
+// il.append(fact.createArrayStore(BcelWorld.makeBcelType(convertToType)));
+// }
+//
+// InstructionList createConvertableArrayStore(
+// InstructionFactory fact,
+// int index,
+// BcelFieldRef storee)
+// {
+// InstructionList il = new InstructionList();
+// appendConvertableArrayStore(il, fact, index, storee);
+// return il;
+// }
+// InstructionList createConvertableArrayLoad(
+// InstructionFactory fact,
+// int index,
+// ResolvedTypeX convertTo)
+// {
+// InstructionList il = new InstructionList();
+// appendConvertableArrayLoad(il, fact, index, convertTo);
+// return il;
+// }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java b/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java
new file mode 100644
index 000000000..c43ae2241
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import org.apache.bcel.classfile.*;
+import org.aspectj.weaver.*;
+
+final class BcelMethod extends ResolvedMember {
+
+ private Method method;
+ private boolean isAjSynthetic;
+ private ShadowMunger associatedShadowMunger;
+ private AjAttribute.EffectiveSignatureAttribute effectiveSignature;
+
+ BcelMethod(BcelObjectType declaringType, Method method) {
+ super(
+ method.getName().equals("<init>") ? CONSTRUCTOR : METHOD,
+ declaringType,
+ declaringType.isInterface()
+ ? method.getAccessFlags() | Modifier.INTERFACE
+ : method.getAccessFlags(),
+ method.getName(),
+ method.getSignature());
+ this.method = method;
+ unpackAjAttributes(declaringType.getWorld());
+ unpackJavaAttributes();
+ }
+
+ // ----
+
+ BcelObjectType getBcelDeclaringType() {
+ return (BcelObjectType) getDeclaringType(); // I want covariant return types.
+ }
+
+ private void unpackJavaAttributes() {
+ ExceptionTable exnTable = method.getExceptionTable();
+ checkedExceptions = (exnTable == null)
+ ? TypeX.NONE
+ : TypeX.forNames(exnTable.getExceptionNames());
+
+ LocalVariableTable varTable = method.getLocalVariableTable();
+ int len = getArity();
+ if (varTable == null) {
+ this.parameterNames = Utility.makeArgNames(len);
+ } else {
+ TypeX[] paramTypes = getParameterTypes();
+ String[] paramNames = new String[len];
+ int index = isStatic() ? 0 : 1;
+ for (int i = 0; i < len; i++) {
+ LocalVariable lv = varTable.getLocalVariable(index);
+ if (lv == null) {
+ paramNames[i] = "arg" + i;
+ } else {
+ paramNames[i] = lv.getName();
+ }
+ index += paramTypes[i].getSize();
+ }
+ this.parameterNames = paramNames;
+ }
+ }
+
+ private void unpackAjAttributes(World world) {
+ List as = BcelAttributes.readAjAttributes(method.getAttributes(), getSourceContext(world));
+ //System.out.println("unpack: " + this + ", " + as);
+ for (Iterator iter = as.iterator(); iter.hasNext();) {
+ AjAttribute a = (AjAttribute) iter.next();
+ if (a instanceof AjAttribute.AdviceAttribute) {
+ associatedShadowMunger = ((AjAttribute.AdviceAttribute)a).reify(this, world);
+ return;
+ } else if (a instanceof AjAttribute.AjSynthetic) {
+ isAjSynthetic = true;
+ } else if (a instanceof AjAttribute.EffectiveSignatureAttribute) {
+ //System.out.println("found effective: " + this);
+ effectiveSignature = (AjAttribute.EffectiveSignatureAttribute)a;
+ } else {
+ throw new BCException("weird method attribute " + a);
+ }
+ }
+ associatedShadowMunger = null;
+ }
+
+ public boolean isAjSynthetic() {
+ return isAjSynthetic; // || getName().startsWith(NameMangler.PREFIX);
+ }
+
+ public ShadowMunger getAssociatedShadowMunger() {
+ return associatedShadowMunger;
+ }
+
+ public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature() {
+ return effectiveSignature;
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
new file mode 100644
index 000000000..303e12561
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
@@ -0,0 +1,236 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.PrintStream;
+import java.util.*;
+
+import org.apache.bcel.classfile.*;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.patterns.*;
+import org.aspectj.weaver.patterns.PerClause;
+
+// ??? exposed for testing
+public class BcelObjectType extends ResolvedTypeX.Name {
+ private JavaClass javaClass;
+ private boolean isObject = false; // set upon construction
+ private LazyClassGen lazyClassGen = null; // set lazily if it's an aspect
+
+ // lazy, for no particular reason I can discern
+ private ResolvedTypeX[] interfaces = null;
+ private ResolvedTypeX superClass = null;
+ private ResolvedMember[] fields = null;
+ private ResolvedMember[] methods = null;
+
+ // strangely non-lazy
+ private ResolvedPointcutDefinition[] pointcuts = null;
+ private PerClause perClause = null;
+ private WeaverStateKind weaverState = null;
+ private List typeMungers = Collections.EMPTY_LIST;
+ private List declares = Collections.EMPTY_LIST;
+ private ResolvedMember[] privilegedAccess = null;
+
+
+ public Collection getTypeMungers() {
+ return typeMungers;
+ }
+
+
+ public Collection getDeclares() {
+ return declares;
+ }
+
+ public Collection getPrivilegedAccesses() {
+ if (privilegedAccess == null) return Collections.EMPTY_LIST;
+ return Arrays.asList(privilegedAccess);
+ }
+
+
+ // IMPORTANT! THIS DOESN'T do real work on the java class, just stores it away.
+ BcelObjectType(String signature, World world, JavaClass javaClass) {
+ super(signature, world);
+ this.javaClass = javaClass;
+
+ sourceContext = new BcelSourceContext(this);
+
+ // this should only ever be java.lang.Object which is
+ // the only class in Java-1.4 with no superclasses
+ isObject = (javaClass.getSuperclassNameIndex() == 0);
+ unpackAspectAttributes();
+ }
+
+ public int getModifiers() {
+ return javaClass.getAccessFlags();
+ }
+
+ public ResolvedTypeX getSuperclass() {
+ if (isObject) return null;
+ if (superClass == null) {
+ superClass = world.resolve(TypeX.forName(javaClass.getSuperclassName()));
+ }
+ return superClass;
+ }
+
+ public ResolvedTypeX[] getDeclaredInterfaces() {
+ if (interfaces == null) {
+ String[] ifaceNames = javaClass.getInterfaceNames();
+ interfaces = new ResolvedTypeX[ifaceNames.length];
+ for (int i = 0, len = ifaceNames.length; i < len; i++) {
+ interfaces[i] = world.resolve(TypeX.forName(ifaceNames[i]));
+ }
+ }
+ return interfaces;
+ }
+
+ public ResolvedMember[] getDeclaredMethods() {
+ if (methods == null) {
+ Method[] ms = javaClass.getMethods();
+ ResolvedMember[] ret = new ResolvedMember[ms.length];
+ for (int i = ms.length - 1; i >= 0; i--) {
+ ret[i] = new BcelMethod(this, ms[i]);
+ }
+ methods = ret;
+ }
+ return methods;
+ }
+
+ public ResolvedMember[] getDeclaredFields() {
+ if (fields == null) {
+ Field[] fs = javaClass.getFields();
+ ResolvedMember[] ret = new ResolvedMember[fs.length];
+ for (int i = 0, len = fs.length; i < len; i++) {
+ ret[i] = new BcelField(this, fs[i]);
+ }
+ fields = ret;
+ }
+ return fields;
+ }
+
+ // ----
+ // fun based on the aj attributes
+
+ public ResolvedMember[] getDeclaredPointcuts() {
+ return pointcuts;
+ }
+
+ //??? method only used for testing
+ public void addPointcutDefinition(ResolvedPointcutDefinition d) {
+ int len = pointcuts.length;
+ ResolvedPointcutDefinition[] ret = new ResolvedPointcutDefinition[len+1];
+ System.arraycopy(pointcuts, 0, ret, 0, len);
+ ret[len] = d;
+ pointcuts = ret;
+ }
+
+
+
+ public boolean isAspect() {
+ return perClause != null;
+ }
+
+ private void unpackAspectAttributes() {
+ List pointcuts = new ArrayList();
+ typeMungers = new ArrayList();
+ declares = new ArrayList();
+ List l = BcelAttributes.readAjAttributes(javaClass.getAttributes(), getSourceContext());
+ for (Iterator iter = l.iterator(); iter.hasNext();) {
+ AjAttribute a = (AjAttribute) iter.next();
+ if (a instanceof AjAttribute.Aspect) {
+ perClause = ((AjAttribute.Aspect)a).reify(this);
+ } else if (a instanceof AjAttribute.PointcutDeclarationAttribute) {
+ pointcuts.add(((AjAttribute.PointcutDeclarationAttribute)a).reify());
+ } else if (a instanceof AjAttribute.WeaverState) {
+ weaverState = ((AjAttribute.WeaverState)a).reify();
+ } else if (a instanceof AjAttribute.TypeMunger) {
+ typeMungers.add(((AjAttribute.TypeMunger)a).reify(getWorld(), this));
+ } else if (a instanceof AjAttribute.DeclareAttribute) {
+ declares.add(((AjAttribute.DeclareAttribute)a).getDeclare());
+ } else if (a instanceof AjAttribute.PrivilegedAttribute) {
+ privilegedAccess = ((AjAttribute.PrivilegedAttribute)a).getAccessedMembers();
+ } else if (a instanceof AjAttribute.SourceContextAttribute) {
+ ((BcelSourceContext)sourceContext).addAttributeInfo((AjAttribute.SourceContextAttribute)a);
+ } else {
+ throw new BCException("bad attribute " + a);
+ }
+ }
+ this.pointcuts = (ResolvedPointcutDefinition[])
+ pointcuts.toArray(new ResolvedPointcutDefinition[pointcuts.size()]);
+// this.typeMungers = (BcelTypeMunger[])
+// typeMungers.toArray(new BcelTypeMunger[typeMungers.size()]);
+// this.declares = (Declare[])
+// declares.toArray(new Declare[declares.size()]);
+ }
+
+ public PerClause getPerClause() {
+ return perClause;
+ }
+
+
+ JavaClass getJavaClass() {
+ return javaClass;
+ }
+
+ /**
+ * Switch to a new JavaClass and clear all caches
+ */
+ void replaceJavaClass(JavaClass jc) {
+ if (this.javaClass == jc) return;
+
+ this.javaClass = jc;
+ this.interfaces = null;
+ this.superClass = null;
+ this.fields = null;
+ this.methods = null;
+ this.pointcuts = null;
+ this.perClause = null;
+ this.weaverState = null;
+ this.lazyClassGen = null;
+ //XXX is clearing these caches sufficient
+ }
+
+ public WeaverStateKind getWeaverState() {
+ return weaverState;
+ }
+
+ public void setWeaverState(WeaverStateKind weaverState) {
+ this.weaverState = weaverState;
+ }
+
+ public void printWackyStuff(PrintStream out) {
+ if (typeMungers.size() > 0) {
+ out.println(" TypeMungers: " + typeMungers);
+ }
+ if (declares.size() > 0) {
+ out.println(" declares: " + declares);
+ }
+ }
+
+ /**
+ * Return the lazyClassGen associated with this type. For aspect types, this
+ * value will be cached, since it is used to inline advice. For non-aspect
+ * types, this lazyClassGen is always newly constructed.
+ */
+ public LazyClassGen getLazyClassGen() {
+ LazyClassGen ret = lazyClassGen;
+ if (ret == null) {
+ ret = new LazyClassGen(this);
+ if (isAspect()) {
+ lazyClassGen = ret;
+ }
+ }
+ return ret;
+ }
+}
+
+
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelRenderer.java b/weaver/src/org/aspectj/weaver/bcel/BcelRenderer.java
new file mode 100644
index 000000000..ab5595916
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelRenderer.java
@@ -0,0 +1,232 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.BCException;
+import org.aspectj.weaver.ast.*;
+
+// we generate right to left, btw.
+public class BcelRenderer implements ITestVisitor, IExprVisitor {
+
+ private InstructionList instructions;
+ private InstructionFactory fact;
+ private BcelWorld world;
+
+ InstructionHandle sk, fk, next = null;
+
+ private BcelRenderer(InstructionFactory fact, BcelWorld world) {
+ super();
+ this.fact = fact;
+ this.world = world;
+ this.instructions = new InstructionList();
+ }
+
+ // ---- renderers
+
+ public static InstructionList renderExpr(
+ InstructionFactory fact,
+ BcelWorld world,
+ Expr e)
+ {
+ BcelRenderer renderer = new BcelRenderer(fact, world);
+ e.accept(renderer);
+ return renderer.instructions;
+ }
+ public static InstructionList renderExpr(
+ InstructionFactory fact,
+ BcelWorld world,
+ Expr e,
+ Type desiredType)
+ {
+ BcelRenderer renderer = new BcelRenderer(fact, world);
+ e.accept(renderer);
+ InstructionList il = renderer.instructions;
+ il.append(Utility.createConversion(fact, world.makeBcelType(e.getType()), desiredType));
+ return il;
+ }
+
+ public static InstructionList renderExprs(
+ InstructionFactory fact,
+ BcelWorld world,
+ Expr[] es)
+ {
+ BcelRenderer renderer = new BcelRenderer(fact, world);
+ for (int i = es.length - 1; i >= 0; i--) {
+ es[i].accept(renderer);
+ }
+ return renderer.instructions;
+ }
+
+ /*
+ * Get the instructions representing this test.
+ *
+ * @param e test to render
+ * @param sk instructionHandle to jump to if our rendered check succeeds (typically start of advice)
+ * @param fk instructionHandle to jump to if our rendered check fails (typically after end of advice)
+ * @param next instructionHandle that will follow this generated code. Passing in null will generate
+ * one unnecessary GOTO instruction.
+ *
+ * @returns the instruction list representing this expression
+ */
+ public static InstructionList renderTest(
+ InstructionFactory fact,
+ BcelWorld world,
+ Test e,
+ InstructionHandle sk,
+ InstructionHandle fk,
+ InstructionHandle next)
+ {
+ BcelRenderer renderer = new BcelRenderer(fact, world);
+ renderer.recur(e, sk, fk, next);
+ return renderer.instructions;
+ }
+
+ /*
+ * Get the instructions representing this test.
+ *
+ * @param e test to render
+ * @param sk instructionHandle to jump to if our rendered check succeeds (typically start of advice)
+ * @param fk instructionHandle to jump to if our rendered check fails (typically after end of advice)
+ *
+ * @returns the instruction list representing this expression
+ */
+ public static InstructionList renderTest(
+ InstructionFactory fact,
+ BcelWorld world,
+ Test e,
+ InstructionHandle sk,
+ InstructionHandle fk)
+ {
+ return renderTest(fact, world, e, sk, fk, null);
+ }
+
+ // ---- recurrers
+
+ private void recur(
+ Test e,
+ InstructionHandle sk,
+ InstructionHandle fk,
+ InstructionHandle next)
+ {
+ this.sk = sk;
+ this.fk = fk;
+ this.next = next;
+ e.accept(this);
+ }
+
+ // ---- test visitors
+
+ public void visit(And e) {
+ InstructionHandle savedFk = fk;
+ recur(e.getRight(), sk, fk, next);
+ InstructionHandle ning = instructions.getStart();
+ recur(e.getLeft(), ning, savedFk, ning);
+ }
+
+ public void visit(Or e) {
+ InstructionHandle savedSk = sk;
+ recur(e.getRight(), sk, fk, next);
+ recur(e.getLeft(), savedSk, instructions.getStart(), instructions.getStart());
+ }
+
+ public void visit(Not e) {
+ recur(e.getBody(), fk, sk, next);
+ }
+
+ public void visit(Instanceof i) {
+ instructions.insert(createJumpBasedOnBooleanOnStack());
+ instructions.insert(
+ Utility.createInstanceof(fact, (ObjectType) world.makeBcelType(i.getType())));
+ i.getVar().accept(this);
+ }
+
+ private InstructionList createJumpBasedOnBooleanOnStack() {
+ InstructionList il = new InstructionList();
+ if (sk == fk) {
+ // don't bother generating if it doesn't matter
+ if (sk != next) {
+ il.insert(fact.createBranchInstruction(Constants.GOTO, sk));
+ }
+ return il;
+ }
+
+ if (fk == next) {
+ il.insert(fact.createBranchInstruction(Constants.IFNE, sk));
+ } else if (sk == next) {
+ il.insert(fact.createBranchInstruction(Constants.IFEQ, fk));
+ } else {
+ il.insert(fact.createBranchInstruction(Constants.GOTO, sk));
+ il.insert(fact.createBranchInstruction(Constants.IFEQ, fk));
+ }
+ return il;
+ }
+
+
+ public void visit(Literal literal) {
+ if (literal == Literal.FALSE)
+ throw new BCException("bad");
+ }
+
+ public void visit(Call call) {
+ Member method = call.getMethod();
+ // assert method.isStatic()
+ Expr[] args = call.getArgs();
+ //System.out.println("args: " + Arrays.asList(args));
+ InstructionList callIl = renderExprs(fact, world, args);
+ //System.out.println("rendered args: " + callIl);
+ callIl.append(Utility.createInvoke(fact, world, method));
+ callIl.append(createJumpBasedOnBooleanOnStack());
+ instructions.insert(callIl);
+ }
+
+ public void visit(FieldGetCall fieldGetCall) {
+ Member field = fieldGetCall.getField();
+ Member method = fieldGetCall.getMethod();
+ InstructionList il = new InstructionList();
+ il.append(Utility.createGet(fact, field));
+ // assert !method.isStatic()
+ Expr[] args = fieldGetCall.getArgs();
+ //System.out.println("args: " + Arrays.asList(args));
+ il.append(renderExprs(fact, world, args));
+ //System.out.println("rendered args: " + callIl);
+ il.append(Utility.createInvoke(fact, world, method));
+ il.append(createJumpBasedOnBooleanOnStack());
+ instructions.insert(il);
+ }
+
+ // ---- expr visitors
+
+ public void visit(Var var) {
+ BcelVar bvar = (BcelVar) var;
+ bvar.insertLoad(instructions, fact);
+ }
+
+ public void visit(FieldGet fieldGet) {
+ Member field = fieldGet.getField();
+ // assert field.isStatic()
+ instructions.insert(Utility.createGet(fact, field));
+ }
+
+ public void visit(CallExpr call) {
+ Member method = call.getMethod();
+ // assert method.isStatic()
+ Expr[] args = call.getArgs();
+ InstructionList callIl = renderExprs(fact, world, args);
+ callIl.append(Utility.createInvoke(fact, world, method));
+ instructions.insert(callIl);
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
new file mode 100644
index 000000000..432acd17b
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
@@ -0,0 +1,1731 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.File;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.Field;
+import org.apache.bcel.generic.*;
+import org.aspectj.bridge.SourceLocation;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.Shadow.Kind;
+import org.aspectj.weaver.ast.Var;
+
+
+/*
+ * Some fun implementation stuff:
+ *
+ * * expressionKind advice is non-execution advice
+ * * may have a target.
+ * * if the body is extracted, it will be extracted into
+ * a static method. The first argument to the static
+ * method is the target
+ * * advice may expose a this object, but that's the advice's
+ * consideration, not ours. This object will NOT be cached in another
+ * local, but will always come from frame zero.
+ *
+ * * non-expressionKind advice is execution advice
+ * * may have a this.
+ * * target is same as this, and is exposed that way to advice
+ * (i.e., target will not be cached, will always come from frame zero)
+ * * if the body is extracted, it will be extracted into a method
+ * with same static/dynamic modifier as enclosing method. If non-static,
+ * target of callback call will be this.
+ *
+ * * because of these two facts, the setup of the actual arguments (including
+ * possible target) callback method is the same for both kinds of advice:
+ * push the targetVar, if it exists (it will not exist for advice on static
+ * things), then push all the argVars.
+ *
+ * Protected things:
+ *
+ * * the above is sufficient for non-expressionKind advice for protected things,
+ * since the target will always be this.
+ *
+ * * For expressionKind things, we have to modify the signature of the callback
+ * method slightly. For non-static expressionKind things, we modify
+ * the first argument of the callback method NOT to be the type specified
+ * by the method/field signature (the owner), but rather we type it to
+ * the currentlyEnclosing type. We are guaranteed this will be fine,
+ * since the verifier verifies that the target is a subtype of the currently
+ * enclosingType.
+ *
+ * Worries:
+ *
+ * * ConstructorCalls will be weirder than all of these, since they
+ * supposedly don't have a target (according to AspectJ), but they clearly
+ * do have a target of sorts, just one that needs to be pushed on the stack,
+ * dupped, and not touched otherwise until the constructor runs.
+ *
+ */
+
+public class BcelShadow extends Shadow {
+
+ private ShadowRange range;
+ private final BcelWorld world;
+ private final LazyMethodGen enclosingMethod;
+ private final BcelShadow enclosingShadow;
+
+ private boolean fallsThrough;
+
+ // ---- initialization
+
+ /**
+ * This generates an unassociated shadow, rooted in a particular method but not rooted
+ * to any particular point in the code. It should be given to a rooted ShadowRange
+ * in the {@link ShadowRange#associateWithShadow(BcelShadow)} method.
+ */
+ public BcelShadow(
+ BcelWorld world,
+ Kind kind,
+ Member signature,
+ LazyMethodGen enclosingMethod,
+ BcelShadow enclosingShadow)
+ {
+ super(kind, signature);
+ this.world = world;
+ this.enclosingMethod = enclosingMethod;
+ this.enclosingShadow = enclosingShadow;
+ fallsThrough = kind.argsOnStack();
+ }
+
+ // ---- copies all state, including Shadow's mungers...
+
+ public BcelShadow copyInto(LazyMethodGen recipient, BcelShadow enclosing) {
+ BcelShadow s = new BcelShadow(world, getKind(), getSignature(), recipient, enclosing);
+ List src = mungers;
+ List dest = s.mungers;
+
+ for (Iterator i = src.iterator(); i.hasNext(); ) {
+ dest.add(i.next());
+ }
+ return s;
+ }
+
+ // ---- overridden behaviour
+
+ public World getIWorld() {
+ return world;
+ }
+
+
+
+ private void deleteNewAndDup() {
+ final ConstantPoolGen cpg = getEnclosingClass().getConstantPoolGen();
+ int depth = 1;
+ InstructionHandle ih = range.getStart();
+
+ while (true) {
+ Instruction inst = ih.getInstruction();
+ if (inst instanceof INVOKESPECIAL
+ && ((INVOKESPECIAL) inst).getName(cpg).equals("<init>")) {
+ depth++;
+ } else if (inst instanceof NEW) {
+ depth--;
+ if (depth == 0) break;
+ }
+ ih = ih.getPrev();
+ }
+ // now IH points to the NEW. We're followed by the DUP, and that is followed
+ // by the actual instruciton we care about.
+ InstructionHandle newHandle = ih;
+ InstructionHandle endHandle = newHandle.getNext();
+ InstructionHandle nextHandle;
+ if (endHandle.getInstruction() instanceof DUP) {
+ nextHandle = endHandle.getNext();
+ retargetFrom(newHandle, nextHandle);
+ retargetFrom(endHandle, nextHandle);
+ } else if (endHandle.getInstruction() instanceof DUP_X1) {
+ InstructionHandle dupHandle = endHandle;
+ endHandle = endHandle.getNext();
+ nextHandle = endHandle.getNext();
+ if (endHandle.getInstruction() instanceof SWAP) {}
+ else {
+ // XXX see next XXX comment
+ throw new RuntimeException("Unhandled kind of new " + endHandle);
+ }
+ retargetFrom(newHandle, nextHandle);
+ retargetFrom(dupHandle, nextHandle);
+ retargetFrom(endHandle, nextHandle);
+ } else {
+ // XXX we want to fail gracefully here. This should not be picked out as a join point,
+ // probably. So change BcelClassWeaver.match appropriately.
+ throw new RuntimeException("Unhandled kind of new");
+ }
+ // assert (dupHandle.getInstruction() instanceof DUP);
+
+ try {
+ range.getBody().delete(newHandle, endHandle);
+ } catch (TargetLostException e) {
+ throw new BCException("shouldn't happen");
+ }
+ }
+ private void retargetFrom(InstructionHandle old, InstructionHandle fresh) {
+ InstructionTargeter[] sources = old.getTargeters();
+ if (sources != null) {
+ for (int i = sources.length - 1; i >= 0; i--) {
+ sources[i].updateTarget(old, fresh);
+ }
+ }
+ }
+
+ protected void prepareForMungers() {
+ // if we're a constructor call, we need to remove the new:dup or the new:dup_x1:swap,
+ // and store all our
+ // arguments on the frame.
+
+ // ??? This is a bit of a hack (for the Java langauge). We do this because
+ // we sometime add code "outsideBefore" when dealing with weaving join points. We only
+ // do this for exposing state that is on the stack. It turns out to just work for
+ // everything except for constructor calls and exception handlers. If we were to clean
+ // this up, every ShadowRange would have three instructionHandle points, the start of
+ // the arg-setup code, the start of the running code, and the end of the running code.
+ if (getKind() == ConstructorCall) {
+ deleteNewAndDup();
+ initializeArgVars();
+ } else if (getKind() == ExceptionHandler) {
+ ShadowRange range = getRange();
+ InstructionList body = range.getBody();
+ InstructionHandle start = range.getStart();
+ InstructionHandle freshIh = body.insert(start, getFactory().NOP);
+ InstructionTargeter[] targeters = start.getTargeters();
+ for (int i = 0; i < targeters.length; i++) {
+ InstructionTargeter t = targeters[i];
+ if (t instanceof ExceptionRange) {
+ ExceptionRange er = (ExceptionRange) t;
+ er.updateTarget(start, freshIh, body);
+ }
+ }
+ }
+
+ // now we ask each munger to request our state
+ for (Iterator iter = mungers.iterator(); iter.hasNext();) {
+ ShadowMunger munger = (ShadowMunger) iter.next();
+ munger.specializeOn(this);
+ }
+
+ // If we are an expression kind, we require our target/arguments on the stack
+ // before we do our actual thing. However, they may have been removed
+ // from the stack as the shadowMungers have requested state.
+ // if any of our shadowMungers requested either the arguments or target,
+ // the munger will have added code
+ // to pop the target/arguments into temporary variables, represented by
+ // targetVar and argVars. In such a case, we must make sure to re-push the
+ // values.
+
+ // If we are nonExpressionKind, we don't expect arguments on the stack
+ // so this is moot. If our argVars happen to be null, then we know that
+ // no ShadowMunger has squirrelled away our arguments, so they're still
+ // on the stack.
+ InstructionFactory fact = getFactory();
+ if (getKind().argsOnStack() && argVars != null) {
+ range.insert(
+ BcelRenderer.renderExprs(fact, world, argVars),
+ Range.InsideBefore);
+ if (targetVar != null) {
+ range.insert(
+ BcelRenderer.renderExpr(fact, world, targetVar),
+ Range.InsideBefore);
+ }
+ if (getKind() == ConstructorCall) {
+ range.insert((Instruction) fact.createDup(1), Range.InsideBefore);
+ range.insert(
+ fact.createNew(
+ (ObjectType) BcelWorld.makeBcelType(
+ getSignature().getDeclaringType())),
+ Range.InsideBefore);
+ }
+ }
+ }
+
+ // ---- getters
+
+ public ShadowRange getRange() {
+ return range;
+ }
+ public void setRange(ShadowRange range) {
+ this.range = range;
+ }
+
+ public int getSourceLine() {
+ if (range == null) return 0;
+ int ret = Utility.getSourceLine(range.getStart());
+ if (ret < 0) return 0;
+ return ret;
+ }
+
+ // overrides
+ public TypeX getEnclosingType() {
+ return world.resolve(getEnclosingClass().getClassName());
+ }
+
+ public LazyClassGen getEnclosingClass() {
+ return enclosingMethod.getEnclosingClass();
+ }
+
+ public BcelWorld getWorld() {
+ return world;
+ }
+
+ // ---- factory methods
+
+ public static BcelShadow makeConstructorExecution(
+ BcelWorld world,
+ LazyMethodGen enclosingMethod,
+ InstructionHandle justBeforeStart)
+ {
+ final InstructionList body = enclosingMethod.getBody();
+ BcelShadow s =
+ new BcelShadow(
+ world,
+ ConstructorExecution,
+ world.makeMethodSignature(enclosingMethod),
+ enclosingMethod,
+ null);
+ ShadowRange r = new ShadowRange(body);
+ r.associateWithShadow(s);
+ r.associateWithTargets(
+ Range.genStart(body, justBeforeStart.getNext()),
+ Range.genEnd(body));
+ return s;
+ }
+
+ public static BcelShadow makeStaticInitialization(
+ BcelWorld world,
+ LazyMethodGen enclosingMethod)
+ {
+ InstructionList body = enclosingMethod.getBody();
+ BcelShadow s =
+ new BcelShadow(
+ world,
+ StaticInitialization,
+ world.makeMethodSignature(enclosingMethod),
+ enclosingMethod,
+ null);
+ ShadowRange r = new ShadowRange(body);
+ r.associateWithShadow(s);
+ r.associateWithTargets(
+ Range.genStart(body),
+ Range.genEnd(body));
+ return s;
+ }
+
+ /** Make the shadow for an exception handler. Currently makes an empty shadow that
+ * only allows before advice to be woven into it.
+ */
+
+
+ public static BcelShadow makeExceptionHandler(
+ BcelWorld world,
+ ExceptionRange exceptionRange,
+ LazyMethodGen enclosingMethod,
+ InstructionHandle startOfHandler,
+ BcelShadow enclosingShadow)
+ {
+ InstructionList body = enclosingMethod.getBody();
+ TypeX catchType = exceptionRange.getCatchType();
+ TypeX inType = enclosingMethod.getEnclosingClass().getType();
+ BcelShadow s =
+ new BcelShadow(
+ world,
+ ExceptionHandler,
+ Member.makeExceptionHandlerSignature(inType, catchType),
+ enclosingMethod,
+ enclosingShadow);
+ ShadowRange r = new ShadowRange(body);
+ r.associateWithShadow(s);
+ InstructionHandle start = Range.genStart(body, startOfHandler);
+ InstructionHandle end = Range.genEnd(body, start);
+
+ r.associateWithTargets(start, end);
+ exceptionRange.updateTarget(startOfHandler, start, body);
+ return s;
+ }
+
+ /** create an init join point associated w/ an interface in the body of a constructor */
+
+ public static BcelShadow makeIfaceInitialization(
+ BcelWorld world,
+ LazyMethodGen constructor,
+ BcelShadow ifaceCExecShadow,
+ Member interfaceConstructorSignature)
+ {
+ InstructionList body = constructor.getBody();
+ TypeX inType = constructor.getEnclosingClass().getType();
+ BcelShadow s =
+ new BcelShadow(
+ world,
+ Initialization,
+ interfaceConstructorSignature,
+ constructor,
+ null);
+ s.fallsThrough = true;
+ ShadowRange r = new ShadowRange(body);
+ r.associateWithShadow(s);
+ InstructionHandle start = Range.genStart(body, ifaceCExecShadow.getRange().getStart());
+ InstructionHandle end = Range.genEnd(body, ifaceCExecShadow.getRange().getEnd());
+
+ r.associateWithTargets(start, end);
+ return s;
+ }
+
+ public static BcelShadow makeIfaceConstructorExecution(
+ BcelWorld world,
+ LazyMethodGen constructor,
+ InstructionHandle next,
+ Member interfaceConstructorSignature)
+ {
+ final InstructionFactory fact = constructor.getEnclosingClass().getFactory();
+ InstructionList body = constructor.getBody();
+ TypeX inType = constructor.getEnclosingClass().getType();
+ BcelShadow s =
+ new BcelShadow(
+ world,
+ ConstructorExecution,
+ interfaceConstructorSignature,
+ constructor,
+ null);
+ s.fallsThrough = true;
+ ShadowRange r = new ShadowRange(body);
+ r.associateWithShadow(s);
+ // ??? this may or may not work
+ InstructionHandle start = Range.genStart(body, next);
+ //InstructionHandle end = Range.genEnd(body, body.append(start, fact.NOP));
+ InstructionHandle end = Range.genStart(body, next);
+ //body.append(start, fact.NOP);
+
+ r.associateWithTargets(start, end);
+ return s;
+ }
+
+
+ /** Create an initialization join point associated with a constructor, but not
+ * with any body of code yet. If this is actually matched, it's range will be set
+ * when we inline self constructors.
+ *
+ * @param constructor The constructor starting this initialization.
+ */
+ public static BcelShadow makeUnfinishedInitialization(
+ BcelWorld world,
+ LazyMethodGen constructor)
+ {
+ return new BcelShadow(
+ world,
+ Initialization,
+ world.makeMethodSignature(constructor),
+ constructor,
+ null);
+ }
+
+ public static BcelShadow makeUnfinishedPreinitialization(
+ BcelWorld world,
+ LazyMethodGen constructor)
+ {
+ BcelShadow ret = new BcelShadow(
+ world,
+ PreInitialization,
+ world.makeMethodSignature(constructor),
+ constructor,
+ null);
+ ret.fallsThrough = true;
+ return ret;
+ }
+
+
+ public static BcelShadow makeMethodExecution(
+ BcelWorld world,
+ LazyMethodGen enclosingMethod)
+ {
+ return makeShadowForMethod(world, enclosingMethod, MethodExecution,
+ world.makeMethodSignature(enclosingMethod));
+ }
+
+
+ public static BcelShadow makeShadowForMethod(BcelWorld world,
+ LazyMethodGen enclosingMethod, Shadow.Kind kind, Member sig)
+ {
+ final InstructionList body = enclosingMethod.getBody();
+ BcelShadow s =
+ new BcelShadow(
+ world,
+ kind,
+ sig,
+ enclosingMethod,
+ null);
+ ShadowRange r = new ShadowRange(body);
+ r.associateWithShadow(s);
+ r.associateWithTargets(
+ Range.genStart(body),
+ Range.genEnd(body));
+ return s;
+ }
+
+
+
+ public static BcelShadow makeAdviceExecution(
+ BcelWorld world,
+ LazyMethodGen enclosingMethod)
+ {
+ final InstructionList body = enclosingMethod.getBody();
+ BcelShadow s =
+ new BcelShadow(
+ world,
+ AdviceExecution,
+ world.makeMethodSignature(enclosingMethod),
+ enclosingMethod,
+ null);
+ ShadowRange r = new ShadowRange(body);
+ r.associateWithShadow(s);
+ r.associateWithTargets(Range.genStart(body), Range.genEnd(body));
+ return s;
+ }
+
+
+ // constructor call shadows are <em>initially</em> just around the
+ // call to the constructor. If ANY advice gets put on it, we move
+ // the NEW instruction inside the join point, which involves putting
+ // all the arguments in temps.
+ public static BcelShadow makeConstructorCall(
+ BcelWorld world,
+ LazyMethodGen enclosingMethod,
+ InstructionHandle callHandle,
+ BcelShadow enclosingShadow)
+ {
+ final InstructionList body = enclosingMethod.getBody();
+
+ Member sig = world.makeMethodSignature(
+ enclosingMethod.getEnclosingClass(),
+ (InvokeInstruction) callHandle.getInstruction());
+
+ BcelShadow s =
+ new BcelShadow(
+ world,
+ ConstructorCall,
+ sig,
+ enclosingMethod,
+ enclosingShadow);
+ ShadowRange r = new ShadowRange(body);
+ r.associateWithShadow(s);
+ r.associateWithTargets(
+ Range.genStart(body, callHandle),
+ Range.genEnd(body, callHandle));
+ retargetAllBranches(callHandle, r.getStart());
+ return s;
+ }
+
+ public static BcelShadow makeMethodCall(
+ BcelWorld world,
+ LazyMethodGen enclosingMethod,
+ InstructionHandle callHandle,
+ BcelShadow enclosingShadow)
+ {
+ final InstructionList body = enclosingMethod.getBody();
+ BcelShadow s =
+ new BcelShadow(
+ world,
+ MethodCall,
+ world.makeMethodSignature(
+ enclosingMethod.getEnclosingClass(),
+ (InvokeInstruction) callHandle.getInstruction()),
+ enclosingMethod,
+ enclosingShadow);
+ ShadowRange r = new ShadowRange(body);
+ r.associateWithShadow(s);
+ r.associateWithTargets(
+ Range.genStart(body, callHandle),
+ Range.genEnd(body, callHandle));
+ retargetAllBranches(callHandle, r.getStart());
+ return s;
+ }
+
+
+ public static BcelShadow makeShadowForMethodCall(
+ BcelWorld world,
+ LazyMethodGen enclosingMethod,
+ InstructionHandle callHandle,
+ BcelShadow enclosingShadow,
+ Kind kind,
+ ResolvedMember sig)
+ {
+ final InstructionList body = enclosingMethod.getBody();
+ BcelShadow s =
+ new BcelShadow(
+ world,
+ kind,
+ sig,
+ enclosingMethod,
+ enclosingShadow);
+ ShadowRange r = new ShadowRange(body);
+ r.associateWithShadow(s);
+ r.associateWithTargets(
+ Range.genStart(body, callHandle),
+ Range.genEnd(body, callHandle));
+ retargetAllBranches(callHandle, r.getStart());
+ return s;
+ }
+
+
+ public static BcelShadow makeFieldGet(
+ BcelWorld world,
+ LazyMethodGen enclosingMethod,
+ InstructionHandle getHandle,
+ BcelShadow enclosingShadow)
+ {
+ final InstructionList body = enclosingMethod.getBody();
+ BcelShadow s =
+ new BcelShadow(
+ world,
+ FieldGet,
+ world.makeFieldSignature(
+ enclosingMethod.getEnclosingClass(),
+ (FieldInstruction) getHandle.getInstruction()),
+ enclosingMethod,
+ enclosingShadow);
+ ShadowRange r = new ShadowRange(body);
+ r.associateWithShadow(s);
+ r.associateWithTargets(
+ Range.genStart(body, getHandle),
+ Range.genEnd(body, getHandle));
+ retargetAllBranches(getHandle, r.getStart());
+ return s;
+ }
+
+ public static BcelShadow makeFieldSet(
+ BcelWorld world,
+ LazyMethodGen enclosingMethod,
+ InstructionHandle setHandle,
+ BcelShadow enclosingShadow)
+ {
+ final InstructionList body = enclosingMethod.getBody();
+ BcelShadow s =
+ new BcelShadow(
+ world,
+ FieldSet,
+ world.makeFieldSignature(
+ enclosingMethod.getEnclosingClass(),
+ (FieldInstruction) setHandle.getInstruction()),
+ enclosingMethod,
+ enclosingShadow);
+ ShadowRange r = new ShadowRange(body);
+ r.associateWithShadow(s);
+ r.associateWithTargets(
+ Range.genStart(body, setHandle),
+ Range.genEnd(body, setHandle));
+ retargetAllBranches(setHandle, r.getStart());
+ return s;
+ }
+
+ public static void retargetAllBranches(InstructionHandle from, InstructionHandle to) {
+ InstructionTargeter[] sources = from.getTargeters();
+ if (sources != null) {
+ for (int i = sources.length - 1; i >= 0; i--) {
+ InstructionTargeter source = sources[i];
+ if (source instanceof BranchInstruction) {
+ source.updateTarget(from, to);
+ }
+ }
+ }
+ }
+
+ // ---- type access methods
+
+ public boolean hasThis() {
+ if (getKind() == PreInitialization) return false;
+ return !getEnclosingCodeSignature().isStatic();
+ //???return !enclosingMethod.isStatic();
+ }
+ public TypeX getThisType() {
+ if (!hasThis()) return ResolvedTypeX.MISSING;
+ return getEnclosingCodeSignature().getDeclaringType();
+ //???return TypeX.forName(getEnclosingClass().getClassName());
+ }
+
+ public boolean hasRealTarget() {
+ return hasTarget() && isExpressionKind();
+ }
+
+
+ private ObjectType getTargetBcelType() {
+ return (ObjectType) world.makeBcelType(getTargetType());
+ }
+ private Type getArgBcelType(int arg) {
+ return world.makeBcelType(getArgType(arg));
+ }
+
+ // ---- kinding
+
+ public boolean isExpressionKind() {
+ if (getKind() == PreInitialization) return true;
+ return getKind().argsOnStack();
+ }
+
+ // ---- argument getting methods
+
+ private BcelVar thisVar = null;
+ private BcelVar targetVar = null;
+ private BcelVar[] argVars = null;
+
+ public Var getThisVar() {
+ if (!hasThis()) {
+ throw new IllegalStateException("no this");
+ }
+ initializeThisVar();
+ return thisVar;
+ }
+ public Var getTargetVar() {
+ if (!hasTarget()) {
+ throw new IllegalStateException("no target");
+ }
+ initializeTargetVar();
+ return targetVar;
+ }
+ public Var getArgVar(int i) {
+ initializeArgVars();
+ return argVars[i];
+ }
+
+ // reflective thisJoinPoint support
+ private BcelVar thisJoinPointVar = null;
+ private BcelVar thisJoinPointStaticPartVar = null; //XXX should be field
+ private BcelVar thisEnclosingJoinPointStaticPartVar = null; //XXX should be field
+
+ public final Var getThisJoinPointVar() {
+ return getThisJoinPointBcelVar();
+ }
+ public final Var getThisJoinPointStaticPartVar() {
+ return getThisJoinPointStaticPartBcelVar();
+ }
+ public final Var getThisEnclosingJoinPointStaticPartVar() {
+ return getThisEnclosingJoinPointStaticPartBcelVar();
+ }
+
+ public BcelVar getThisJoinPointBcelVar() {
+ if (thisJoinPointVar == null) {
+ thisJoinPointVar = genTempVar(TypeX.forName("org.aspectj.lang.JoinPoint"));
+ InstructionFactory fact = getFactory();
+ InstructionList il = new InstructionList();
+ BcelVar staticPart = getThisJoinPointStaticPartBcelVar();
+ staticPart.appendLoad(il, fact);
+ if (hasThis()) {
+ ((BcelVar)getThisVar()).appendLoad(il, fact);
+ } else {
+ il.append(new ACONST_NULL());
+ }
+ if (hasTarget()) {
+ ((BcelVar)getTargetVar()).appendLoad(il, fact);
+ } else {
+ il.append(new ACONST_NULL());
+ }
+ il.append(makeArgsObjectArray());
+
+ il.append(fact.createInvoke("org.aspectj.runtime.reflect.Factory",
+ "makeJP", LazyClassGen.tjpType,
+ new Type[] { LazyClassGen.staticTjpType,
+ Type.OBJECT, Type.OBJECT, new ArrayType(Type.OBJECT, 1)},
+ Constants.INVOKESTATIC));
+ il.append(thisJoinPointVar.createStore(fact));
+ range.insert(il, Range.OutsideBefore);
+ }
+ return thisJoinPointVar;
+ }
+
+ public BcelVar getThisJoinPointStaticPartBcelVar() {
+ if (thisJoinPointStaticPartVar == null) {
+ Field field = getEnclosingClass().getTjpField(this);
+ thisJoinPointStaticPartVar =
+ new BcelFieldRef(
+ world.resolve(TypeX.forName("org.aspectj.lang.JoinPoint$StaticPart")),
+ getEnclosingClass().getClassName(),
+ field.getName());
+ }
+ return thisJoinPointStaticPartVar;
+ }
+
+ public BcelVar getThisEnclosingJoinPointStaticPartBcelVar() {
+ if (enclosingShadow == null) {
+ // the enclosing of an execution is itself
+ return getThisJoinPointStaticPartBcelVar();
+ } else {
+ return enclosingShadow.getThisJoinPointStaticPartBcelVar();
+ }
+ }
+
+ public Member getEnclosingCodeSignature() {
+ if (enclosingShadow == null) {
+ return getSignature();
+ } else {
+ return enclosingShadow.getSignature();
+ }
+ }
+
+
+ private InstructionList makeArgsObjectArray() {
+ InstructionFactory fact = getFactory();
+ BcelVar arrayVar = genTempVar(TypeX.OBJECTARRAY);
+ final InstructionList il = new InstructionList();
+ int alen = getArgCount() ;
+ il.append(Utility.createConstant(fact, alen));
+ il.append((Instruction)fact.createNewArray(Type.OBJECT, (short)1));
+ arrayVar.appendStore(il, fact);
+
+ int stateIndex = 0;
+ for (int i = 0, len = getArgCount(); i<len; i++) {
+ arrayVar.appendConvertableArrayStore(il, fact, stateIndex, (BcelVar)getArgVar(i));
+ stateIndex++;
+ }
+ arrayVar.appendLoad(il, fact);
+ return il;
+ }
+
+ // ---- initializing var tables
+
+ /* initializing this is doesn't do anything, because this
+ * is protected from side-effects, so we don't need to copy its location
+ */
+
+ private void initializeThisVar() {
+ if (thisVar != null) return;
+ thisVar = new BcelVar(getThisType().resolve(world), 0);
+ }
+ public void initializeTargetVar() {
+ InstructionFactory fact = getFactory();
+ if (targetVar != null) return;
+ if (! isExpressionKind()) {
+ initializeThisVar();
+ targetVar = thisVar;
+ } else {
+ initializeArgVars(); // gotta pop off the args before we find the target
+ TypeX type = getTargetType();
+ targetVar = genTempVar(type, "ajc$target");
+ range.insert(targetVar.createStore(fact), Range.OutsideBefore);
+ }
+ targetVar.setPositionInAroundState(0);
+ }
+ public void initializeArgVars() {
+ if (argVars != null) return;
+ InstructionFactory fact = getFactory();
+ int len = getArgCount();
+ argVars = new BcelVar[len];
+
+ if (getKind().argsOnStack()) {
+ // we move backwards because we're popping off the stack
+ for (int i = len - 1; i >= 0; i--) {
+ TypeX type = getArgType(i);
+ BcelVar tmp = genTempVar(type, "ajc$arg" + i);
+ range.insert(tmp.createStore(getFactory()), Range.OutsideBefore);
+ int position = i;
+ if (hasTarget()) position += 1;
+ tmp.setPositionInAroundState(position);
+ argVars[i] = tmp;
+ }
+ } else {
+ int index = 0;
+ if (hasThis()) index++;
+ for (int i = 0; i < len; i++) {
+ TypeX type = getArgType(i);
+ BcelVar tmp = genTempVar(type, "ajc$arg" + i);
+ range.insert(tmp.createCopyFrom(fact, index), Range.OutsideBefore);
+ argVars[i] = tmp;
+ int position = i;
+ if (hasTarget()) position += 1;
+ tmp.setPositionInAroundState(position);
+ index += type.getSize();
+ }
+ }
+ }
+ public void initializeForAroundClosure() {
+ initializeArgVars();
+ if (hasTarget()) initializeTargetVar();
+ }
+
+
+ // ---- weave methods
+
+ void weaveBefore(BcelAdvice munger) {
+ range.insert(
+ munger.getAdviceInstructions(this, null, range.getRealStart()),
+ Range.InsideBefore);
+ }
+
+ public void weaveAfter(BcelAdvice munger) {
+ weaveAfterThrowing(munger, TypeX.THROWABLE);
+ weaveAfterReturning(munger);
+ }
+
+ /**
+ * We guarantee that the return value is on the top of the stack when
+ * munger.getAdviceInstructions() will be run
+ * (Unless we have a void return type in which case there's nothing)
+ */
+ public void weaveAfterReturning(BcelAdvice munger) {
+ InstructionFactory fact = getFactory();
+ List returns = new ArrayList();
+ Instruction ret = null;
+ for (InstructionHandle ih = range.getStart(); ih != range.getEnd(); ih = ih.getNext()) {
+ if (ih.getInstruction() instanceof ReturnInstruction) {
+ returns.add(ih);
+ ret = ih.getInstruction().copy();
+ }
+ }
+ InstructionList retList;
+ InstructionHandle afterAdvice;
+ if (ret != null) {
+ retList = new InstructionList(ret);
+ afterAdvice = retList.getStart();
+ } else /* if (munger.hasDynamicTests()) */ {
+ retList = new InstructionList(fact.NOP);
+ afterAdvice = retList.getStart();
+// } else {
+// retList = new InstructionList();
+// afterAdvice = null;
+ }
+
+ InstructionList advice = new InstructionList();
+ BcelVar tempVar = null;
+ if (munger.hasExtraParameter()) {
+ TypeX tempVarType = getReturnType();
+ if (tempVarType.equals(ResolvedTypeX.VOID)) {
+ tempVar = genTempVar(TypeX.OBJECT);
+ advice.append(getFactory().ACONST_NULL);
+ tempVar.appendStore(advice, getFactory());
+ } else {
+ tempVar = genTempVar(tempVarType);
+ advice.append(getFactory().createDup(tempVarType.getSize()));
+ tempVar.appendStore(advice, getFactory());
+ }
+ }
+ advice.append(munger.getAdviceInstructions(this, tempVar, afterAdvice));
+
+ if (ret != null) {
+ InstructionHandle gotoTarget = advice.getStart();
+ for (Iterator i = returns.iterator(); i.hasNext(); ) {
+ InstructionHandle ih = (InstructionHandle) i.next();
+ Utility.replaceInstruction(ih, fact.createBranchInstruction(Constants.GOTO, gotoTarget), enclosingMethod);
+ }
+ range.append(advice);
+ range.append(retList);
+ } else {
+ range.append(advice);
+ range.append(retList);
+ }
+ }
+
+ public void weaveAfterThrowing(BcelAdvice munger, TypeX catchType) {
+ InstructionFactory fact = getFactory();
+ InstructionList handler = new InstructionList();
+ BcelVar exceptionVar = genTempVar(catchType);
+ exceptionVar.appendStore(handler, fact);
+
+
+ InstructionList endHandler = new InstructionList(
+ exceptionVar.createLoad(fact));
+ handler.append(munger.getAdviceInstructions(this, exceptionVar, endHandler.getStart()));
+ handler.append(endHandler);
+ handler.append(fact.ATHROW);
+ InstructionHandle handlerStart = handler.getStart();
+
+ if (isFallsThrough()) {
+ InstructionHandle jumpTarget = handler.append(fact.NOP);
+ handler.insert(fact.createBranchInstruction(Constants.GOTO, jumpTarget));
+ }
+ InstructionHandle protectedEnd = handler.getStart();
+ range.insert(handler, Range.InsideAfter);
+
+ enclosingMethod.addExceptionHandler(range.getStart().getNext(), protectedEnd.getPrev(),
+ handlerStart, (ObjectType)BcelWorld.makeBcelType(catchType), //???Type.THROWABLE,
+ // high priority if our args are on the stack
+ isExpressionKind());
+ }
+
+
+ public void weaveSoftener(BcelAdvice munger, TypeX catchType) {
+ InstructionFactory fact = getFactory();
+ InstructionList handler = new InstructionList();
+ BcelVar exceptionVar = genTempVar(catchType);
+ exceptionVar.appendStore(handler, fact);
+
+ handler.append(fact.createNew(NameMangler.SOFT_EXCEPTION_TYPE));
+ handler.append(fact.createDup(1));
+ handler.append(exceptionVar.createLoad(fact));
+ handler.append(fact.createInvoke(NameMangler.SOFT_EXCEPTION_TYPE, "<init>",
+ Type.VOID, new Type[] { Type.THROWABLE }, Constants.INVOKESPECIAL)); //??? special
+ handler.append(fact.ATHROW);
+ InstructionHandle handlerStart = handler.getStart();
+
+ if (isFallsThrough()) {
+ InstructionHandle jumpTarget = range.getEnd();//handler.append(fact.NOP);
+ handler.insert(fact.createBranchInstruction(Constants.GOTO, jumpTarget));
+ }
+ InstructionHandle protectedEnd = handler.getStart();
+ range.insert(handler, Range.InsideAfter);
+
+ enclosingMethod.addExceptionHandler(range.getStart().getNext(), protectedEnd.getPrev(),
+ handlerStart, (ObjectType)BcelWorld.makeBcelType(catchType),
+ // high priority if our args are on the stack
+ isExpressionKind());
+ }
+
+
+ public void weavePerObjectEntry(final BcelAdvice munger, final BcelVar onVar) {
+ final InstructionFactory fact = getFactory();
+
+
+ InstructionList entryInstructions = new InstructionList();
+ InstructionList entrySuccessInstructions = new InstructionList();
+ onVar.appendLoad(entrySuccessInstructions, fact);
+
+ entrySuccessInstructions.append(
+ Utility.createInvoke(fact, world,
+ AjcMemberMaker.perObjectBind(munger.getConcreteAspect())));
+
+ InstructionList testInstructions =
+ munger.getTestInstructions(this, entrySuccessInstructions.getStart(),
+ range.getRealStart(),
+ entrySuccessInstructions.getStart());
+
+ entryInstructions.append(testInstructions);
+ entryInstructions.append(entrySuccessInstructions);
+
+ range.insert(entryInstructions, Range.InsideBefore);
+ }
+
+
+ public void weaveCflowEntry(final BcelAdvice munger, final Member cflowStackField) {
+ final boolean isPer = munger.getKind() == AdviceKind.PerCflowBelowEntry ||
+ munger.getKind() == AdviceKind.PerCflowEntry;
+
+ final Type objectArrayType = new ArrayType(Type.OBJECT, 1);
+ final InstructionFactory fact = getFactory();
+
+ final BcelVar testResult = genTempVar(ResolvedTypeX.BOOLEAN);
+
+ InstructionList entryInstructions = new InstructionList();
+ {
+ InstructionList entrySuccessInstructions = new InstructionList();
+
+ if (munger.hasDynamicTests()) {
+ entryInstructions.append(Utility.createConstant(fact, 0));
+ testResult.appendStore(entryInstructions, fact);
+
+ entrySuccessInstructions.append(Utility.createConstant(fact, 1));
+ testResult.appendStore(entrySuccessInstructions, fact);
+ }
+
+ if (isPer) {
+ entrySuccessInstructions.append(
+ fact.createInvoke(munger.getConcreteAspect().getName(),
+ NameMangler.PERCFLOW_PUSH_METHOD,
+ Type.VOID,
+ new Type[] { },
+ Constants.INVOKESTATIC));
+ } else {
+ BcelVar[] cflowStateVars = munger.getExposedStateAsBcelVars();
+
+ BcelVar arrayVar = genTempVar(TypeX.OBJECTARRAY);
+
+ int alen = cflowStateVars.length;
+ entrySuccessInstructions.append(Utility.createConstant(fact, alen));
+ entrySuccessInstructions.append((Instruction)fact.createNewArray(Type.OBJECT, (short)1));
+ arrayVar.appendStore(entrySuccessInstructions, fact);
+
+ for (int i = 0; i < alen; i++) {
+ arrayVar.appendConvertableArrayStore(entrySuccessInstructions, fact, i, cflowStateVars[i]);
+ }
+
+ entrySuccessInstructions.append(
+ Utility.createGet(fact, cflowStackField));
+ arrayVar.appendLoad(entrySuccessInstructions, fact);
+
+ entrySuccessInstructions.append(
+ fact.createInvoke(NameMangler.CFLOW_STACK_TYPE, "push", Type.VOID,
+ new Type[] { objectArrayType },
+ Constants.INVOKEVIRTUAL));
+ }
+
+
+ InstructionList testInstructions =
+ munger.getTestInstructions(this, entrySuccessInstructions.getStart(),
+ range.getRealStart(),
+ entrySuccessInstructions.getStart());
+
+ entryInstructions.append(testInstructions);
+ entryInstructions.append(entrySuccessInstructions);
+ }
+
+ // this is the same for both per and non-per
+ weaveAfter(new BcelAdvice(null, null, null, 0, 0, 0, null, null) {
+ public InstructionList getAdviceInstructions(BcelShadow s, BcelVar extraArgVar, InstructionHandle ifNoAdvice) {
+ InstructionList exitInstructions = new InstructionList();
+ if (munger.hasDynamicTests()) {
+ testResult.appendLoad(exitInstructions, fact);
+ exitInstructions.append(fact.createBranchInstruction(Constants.IFEQ, ifNoAdvice));
+ }
+ exitInstructions.append(
+ Utility.createGet(fact, cflowStackField));
+ exitInstructions.append(
+ fact.createInvoke(NameMangler.CFLOW_STACK_TYPE, "pop", Type.VOID, new Type[] {}, Constants.INVOKEVIRTUAL));
+ return exitInstructions;
+ }});
+
+
+ range.insert(entryInstructions, Range.InsideBefore);
+ }
+
+ public void weaveAroundInline(
+ BcelAdvice munger,
+ boolean hasDynamicTest)
+ {
+ /* Implementation notes:
+ *
+ * AroundInline still extracts the instructions of the original shadow into
+ * an extracted method. This allows inlining of even that advice that doesn't
+ * call proceed or calls proceed more than once.
+ *
+ * It extracts the instructions of the original shadow into a method.
+ *
+ * Then it inlines the instructions of the advice in its place, taking care
+ * to treat the closure argument specially (it doesn't exist).
+ *
+ * Then it searches in the instructions of the advice for any call to the
+ * proceed method.
+ *
+ * At such a call, there is stuff on the stack representing the arguments to
+ * proceed. Pop these into the frame.
+ *
+ * Now build the stack for the call to the extracted method, taking values
+ * either from the join point state or from the new frame locs from proceed.
+ * Now call the extracted method. The right return value should be on the
+ * stack, so no cast is necessary.
+ *
+ * If only one call to proceed is made, we can re-inline the original shadow.
+ * We are not doing that presently.
+ */
+
+ // start by exposing various useful things into the frame
+ final InstructionFactory fact = getFactory();
+
+ // now generate the aroundBody method
+ LazyMethodGen extractedMethod =
+ extractMethod(
+ NameMangler.aroundCallbackMethodName(
+ getSignature(),
+ getEnclosingClass()));
+
+ // the shadow is now empty. First, create a correct call
+ // to the around advice. This includes both the call (which may involve
+ // value conversion of the advice arguments) and the return
+ // (which may involve value conversion of the return value). Right now
+ // we push a null for the unused closure. It's sad, but there it is.
+
+ InstructionList advice = new InstructionList();
+ InstructionHandle adviceMethodInvocation;
+ {
+ // ??? we don't actually need to push NULL for the closure if we take care
+ advice.append(munger.getAdviceArgSetup(this, null, new InstructionList(fact.ACONST_NULL)));
+ adviceMethodInvocation =
+ advice.append(
+ Utility.createInvoke(fact, getWorld(), munger.getSignature()));
+ advice.append(
+ Utility.createConversion(
+ getFactory(),
+ world.makeBcelType(munger.getSignature().getReturnType()),
+ extractedMethod.getReturnType()));
+ if (! isFallsThrough()) {
+ advice.append(fact.createReturn(extractedMethod.getReturnType()));
+ }
+ }
+
+ // now, situate the call inside the possible dynamic tests,
+ // and actually add the whole mess to the shadow
+ if (! hasDynamicTest) {
+ range.append(advice);
+ } else {
+ InstructionList callback = makeCallToCallback(extractedMethod);
+ if (! isExpressionKind()) {
+ callback.append(fact.createReturn(extractedMethod.getReturnType()));
+ } else {
+ advice.append(fact.createBranchInstruction(Constants.GOTO, range.getEnd()));
+ }
+ range.append(munger.getTestInstructions(this, advice.getStart(), callback.getStart(), advice.getStart()));
+ range.append(advice);
+ range.append(callback);
+ }
+
+ // now the range contains everything we need. We now inline the advice method.
+ LazyMethodGen adviceMethod =
+ ((BcelObjectType) munger.getConcreteAspect())
+ .getLazyClassGen()
+ .getLazyMethodGen(munger.getSignature());
+
+ BcelClassWeaver.inlineMethod(adviceMethod, enclosingMethod, adviceMethodInvocation);
+
+ // now search through the advice, looking for a call to PROCEED.
+ // Then we replace the call to proceed with some argument setup, and a
+ // call to the extracted method.
+ String proceedName =
+ NameMangler.proceedMethodName(munger.getSignature().getName());
+
+ InstructionHandle curr = getRange().getStart();
+ InstructionHandle end = getRange().getEnd();
+ ConstantPoolGen cpg = extractedMethod.getEnclosingClass().getConstantPoolGen();
+ while (curr != end) {
+ InstructionHandle next = curr.getNext();
+ Instruction inst = curr.getInstruction();
+ if ((inst instanceof INVOKESTATIC)
+ && proceedName.equals(((INVOKESTATIC) inst).getMethodName(cpg))) {
+
+
+ enclosingMethod.getBody().append(curr, getRedoneProceedCall(fact, extractedMethod, munger));
+ Utility.deleteInstruction(curr, enclosingMethod);
+ }
+ curr = next;
+ }
+ // and that's it.
+ }
+
+ private InstructionList getRedoneProceedCall(
+ InstructionFactory fact,
+ LazyMethodGen callbackMethod,
+ BcelAdvice munger)
+ {
+ InstructionList ret = new InstructionList();
+ // we have on stack all the arguments for the ADVICE call.
+ // we have in frame somewhere all the arguments for the non-advice call.
+
+ List argVarList = new ArrayList();
+
+ // start w/ stuff
+ if (targetVar != null) argVarList.add(targetVar);
+ for (int i = 0, len = getArgCount(); i < len; i++) {
+ argVarList.add(argVars[i]);
+ }
+
+ BcelVar[] adviceVars = munger.getExposedStateAsBcelVars();
+ //??? this is too easy
+// for (int i=0; i < adviceVars.length; i++) {
+// if (adviceVars[i] != null)
+// adviceVars[i].setPositionInAroundState(i);
+// }
+
+
+ IntMap proceedMap = makeProceedArgumentMap(adviceVars);
+
+// System.out.println(proceedMap);
+// System.out.println(Arrays.asList(adviceVars));
+
+ ResolvedTypeX[] proceedParamTypes = world.resolve(munger.getSignature().getParameterTypes());
+
+ BcelVar[] proceedVars =
+ Utility.pushAndReturnArrayOfVars(proceedParamTypes, ret, fact, enclosingMethod);
+
+
+ Type[] stateTypes = callbackMethod.getArgumentTypes();
+
+ for (int i=0, len=stateTypes.length; i < len; i++) {
+ Type stateType = stateTypes[i];
+ ResolvedTypeX stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
+ if (proceedMap.hasKey(i)) {
+ //throw new RuntimeException("unimplemented");
+ proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX);
+ } else {
+ ((BcelVar) argVarList.get(i)).appendLoad(ret, fact);
+ }
+ }
+
+ ret.append(Utility.createInvoke(fact, callbackMethod));
+ ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(),
+ BcelWorld.makeBcelType(munger.getSignature().getReturnType())));
+ return ret;
+ }
+
+ public void weaveAroundClosure(
+ BcelAdvice munger,
+ boolean hasDynamicTest)
+ {
+ InstructionFactory fact = getFactory();
+
+ // MOVE OUT ALL THE INSTRUCTIONS IN MY SHADOW INTO ANOTHER METHOD!
+ LazyMethodGen callbackMethod =
+ extractMethod(
+ NameMangler.aroundCallbackMethodName(
+ getSignature(),
+ getEnclosingClass()));
+
+ BcelVar[] adviceVars = munger.getExposedStateAsBcelVars();
+
+ String closureClassName =
+ NameMangler.makeClosureClassName(
+ getEnclosingClass().getType(),
+ getEnclosingClass().getNewGeneratedNameTag());
+
+ Member constructorSig = new Member(Member.CONSTRUCTOR,
+ TypeX.forName(closureClassName), 0, "<init>",
+ "([Ljava/lang/Object;)V");
+
+ BcelVar closureHolder = null;
+
+ // This is not being used currently since getKind() == preinitializaiton
+ // cannot happen in around advice
+ if (getKind() == PreInitialization) {
+ closureHolder = genTempVar(AjcMemberMaker.AROUND_CLOSURE_TYPE);
+ }
+
+ InstructionList closureInstantiation =
+ makeClosureInstantiation(constructorSig, closureHolder);
+
+ LazyMethodGen constructor =
+ makeClosureClassAndReturnConstructor(
+ closureClassName,
+ callbackMethod,
+ makeProceedArgumentMap(adviceVars)
+ );
+
+ InstructionList returnConversionCode;
+ if (getKind() == PreInitialization) {
+ returnConversionCode = new InstructionList();
+
+ BcelVar stateTempVar = genTempVar(TypeX.OBJECTARRAY);
+ closureHolder.appendLoad(returnConversionCode, fact);
+
+ returnConversionCode.append(
+ Utility.createInvoke(
+ fact,
+ world,
+ AjcMemberMaker.aroundClosurePreInitializationGetter()));
+ stateTempVar.appendStore(returnConversionCode, fact);
+
+ Type[] stateTypes = getSuperConstructorParameterTypes();
+
+ returnConversionCode.append(fact.ALOAD_0); // put "this" back on the stack
+ for (int i = 0, len = stateTypes.length; i < len; i++) {
+ stateTempVar.appendConvertableArrayLoad(
+ returnConversionCode,
+ fact,
+ i,
+ world.resolve(BcelWorld.fromBcel(stateTypes[i])));
+ }
+ } else {
+ returnConversionCode =
+ Utility.createConversion(
+ getFactory(),
+ world.makeBcelType(munger.getSignature().getReturnType()),
+ callbackMethod.getReturnType());
+ if (! isFallsThrough()) {
+ returnConversionCode.append(fact.createReturn(callbackMethod.getReturnType()));
+ }
+ }
+
+ InstructionList advice = new InstructionList();
+ advice.append(munger.getAdviceArgSetup(this, null, closureInstantiation));
+// advice.append(closureInstantiation);
+ advice.append(munger.getNonTestAdviceInstructions(this));
+ advice.append(returnConversionCode);
+
+ if (! hasDynamicTest) {
+ range.append(advice);
+ } else {
+ InstructionList callback = makeCallToCallback(callbackMethod);
+ InstructionList postCallback = new InstructionList();
+ if (! isExpressionKind()) {
+ callback.append(fact.createReturn(callbackMethod.getReturnType()));
+ } else {
+ advice.append(fact.createBranchInstruction(Constants.GOTO, postCallback.append(fact.NOP)));
+ }
+ range.append(munger.getTestInstructions(this, advice.getStart(), callback.getStart(), advice.getStart()));
+ range.append(advice);
+ range.append(callback);
+ range.append(postCallback);
+ }
+ }
+
+ // XXX only used for testing
+ InstructionList makeCallToCallback(LazyMethodGen callbackMethod) {
+ InstructionFactory fact = getFactory();
+ InstructionList callback = new InstructionList();
+ if (targetVar != null) {
+ callback.append(BcelRenderer.renderExpr(fact, world, targetVar));
+ }
+ callback.append(BcelRenderer.renderExprs(fact, world, argVars));
+ callback.append(Utility.createInvoke(fact, callbackMethod));
+ return callback;
+ }
+
+ /** side-effect-free */
+ private InstructionList makeClosureInstantiation(Member constructor, BcelVar holder) {
+
+// LazyMethodGen constructor) {
+ InstructionFactory fact = getFactory();
+ BcelVar arrayVar = genTempVar(TypeX.OBJECTARRAY);
+ //final Type objectArrayType = new ArrayType(Type.OBJECT, 1);
+ final InstructionList il = new InstructionList();
+ int alen = getArgCount() + (targetVar == null ? 0 : 1) + (thisJoinPointVar == null ? 0 : 1);
+ il.append(Utility.createConstant(fact, alen));
+ il.append((Instruction)fact.createNewArray(Type.OBJECT, (short)1));
+ arrayVar.appendStore(il, fact);
+
+ int stateIndex = 0;
+ if (targetVar != null) {
+ arrayVar.appendConvertableArrayStore(il, fact, stateIndex, targetVar);
+ targetVar.setPositionInAroundState(stateIndex);
+ stateIndex++;
+ }
+ for (int i = 0, len = getArgCount(); i<len; i++) {
+ arrayVar.appendConvertableArrayStore(il, fact, stateIndex, argVars[i]);
+ argVars[i].setPositionInAroundState(stateIndex);
+ stateIndex++;
+ }
+ if (thisJoinPointVar != null) {
+ arrayVar.appendConvertableArrayStore(il, fact, stateIndex, thisJoinPointVar);
+ thisJoinPointVar.setPositionInAroundState(stateIndex);
+ stateIndex++;
+ }
+ il.append(fact.createNew(new ObjectType(constructor.getDeclaringType().getName())));
+ il.append(new DUP());
+ arrayVar.appendLoad(il, fact);
+ il.append(Utility.createInvoke(fact, world, constructor));
+ if (getKind() == PreInitialization) {
+ il.append(fact.DUP);
+ holder.appendStore(il, fact);
+ }
+ return il;
+ }
+
+
+ private IntMap makeProceedArgumentMap(BcelVar[] adviceArgs) {
+ //System.err.println("coming in with " + Arrays.asList(adviceArgs));
+
+ IntMap ret = new IntMap();
+ for(int i = 0, len = adviceArgs.length; i < len; i++) {
+ BcelVar v = (BcelVar) adviceArgs[i];
+ if (v == null) continue; // XXX we don't know why this is required
+ int pos = v.getPositionInAroundState();
+ if (pos >= 0) { // need this test to avoid args bound via cflow
+ ret.put(pos, i);
+ }
+ }
+ //System.err.println("returning " + ret);
+
+ return ret;
+ }
+
+ /**
+ *
+ *
+ * @param callbackMethod the method we will call back to when our run method gets called.
+ *
+ * @param proceedMap A map from state position to proceed argument position. May be
+ * non covering on state position.
+ */
+
+ private LazyMethodGen makeClosureClassAndReturnConstructor(
+ String closureClassName,
+ LazyMethodGen callbackMethod,
+ IntMap proceedMap)
+ {
+ String superClassName = "org.aspectj.runtime.internal.AroundClosure";
+ Type objectArrayType = new ArrayType(Type.OBJECT, 1);
+
+ LazyClassGen closureClass = new LazyClassGen(closureClassName,
+ superClassName,
+ getEnclosingClass().getFileName(),
+ Modifier.PUBLIC,
+ new String[] {});
+ InstructionFactory fact = new InstructionFactory(closureClass.getConstantPoolGen());
+
+ // constructor
+ LazyMethodGen constructor = new LazyMethodGen(Modifier.PUBLIC,
+ Type.VOID,
+ "<init>",
+ new Type[] {objectArrayType},
+ new String[] {},
+ closureClass);
+ InstructionList cbody = constructor.getBody();
+ cbody.append(fact.createLoad(Type.OBJECT, 0));
+ cbody.append(fact.createLoad(objectArrayType, 1));
+ cbody.append(fact.createInvoke(superClassName, "<init>", Type.VOID,
+ new Type[] {objectArrayType}, Constants.INVOKESPECIAL));
+ cbody.append(fact.createReturn(Type.VOID));
+
+ closureClass.addMethodGen(constructor);
+
+ // method
+ LazyMethodGen runMethod = new LazyMethodGen(Modifier.PUBLIC,
+ Type.OBJECT,
+ "run",
+ new Type[] {objectArrayType},
+ new String[] {},
+ closureClass);
+ InstructionList mbody = runMethod.getBody();
+ BcelVar proceedVar = new BcelVar(TypeX.OBJECTARRAY.resolve(world), 1);
+ // int proceedVarIndex = 1;
+ BcelVar stateVar = new BcelVar(TypeX.OBJECTARRAY.resolve(world), runMethod.allocateLocal(1));
+ // int stateVarIndex = runMethod.allocateLocal(1);
+ mbody.append(fact.createThis());
+ mbody.append(fact.createGetField(superClassName, "state", objectArrayType));
+ mbody.append(stateVar.createStore(fact));
+ // mbody.append(fact.createStore(objectArrayType, stateVarIndex));
+
+ Type[] stateTypes = callbackMethod.getArgumentTypes();
+
+ for (int i=0, len=stateTypes.length; i < len; i++) {
+ Type stateType = stateTypes[i];
+ ResolvedTypeX stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
+ if (proceedMap.hasKey(i)) {
+ mbody.append(
+ proceedVar.createConvertableArrayLoad(fact, proceedMap.get(i),
+ stateTypeX));
+ } else {
+ mbody.append(
+ stateVar.createConvertableArrayLoad(fact, i,
+ stateTypeX));
+ }
+ }
+
+
+ mbody.append(Utility.createInvoke(fact, callbackMethod));
+
+ if (getKind() == PreInitialization) {
+ mbody.append(Utility.createSet(
+ fact,
+ AjcMemberMaker.aroundClosurePreInitializationField()));
+ mbody.append(fact.ACONST_NULL);
+ } else {
+ mbody.append(
+ Utility.createConversion(
+ fact,
+ callbackMethod.getReturnType(),
+ Type.OBJECT));
+ }
+ mbody.append(fact.createReturn(Type.OBJECT));
+
+ closureClass.addMethodGen(runMethod);
+
+ // class
+ getEnclosingClass().addGeneratedInner(closureClass);
+
+ return constructor;
+ }
+
+ // ---- extraction methods
+
+
+ public LazyMethodGen extractMethod(String newMethodName) {
+ LazyMethodGen.assertGoodBody(range.getBody(), newMethodName);
+ if (!getKind().allowsExtraction()) throw new BCException();
+ LazyMethodGen freshMethod = createMethodGen(newMethodName);
+
+// System.err.println("******");
+// System.err.println("ABOUT TO EXTRACT METHOD for" + this);
+// enclosingMethod.print(System.err);
+// System.err.println("INTO");
+// freshMethod.print(System.err);
+// System.err.println("WITH REMAP");
+// System.err.println(makeRemap());
+
+ range.extractInstructionsInto(freshMethod, makeRemap(),
+ (getKind() != PreInitialization) &&
+ isFallsThrough());
+ if (getKind() == PreInitialization) {
+ addPreInitializationReturnCode(
+ freshMethod,
+ getSuperConstructorParameterTypes());
+ }
+ getEnclosingClass().addMethodGen(freshMethod);
+
+ return freshMethod;
+ }
+
+ private void addPreInitializationReturnCode(
+ LazyMethodGen extractedMethod,
+ Type[] superConstructorTypes)
+ {
+ InstructionList body = extractedMethod.getBody();
+ final InstructionFactory fact = getFactory();
+
+ BcelVar arrayVar = new BcelVar(
+ world.resolve(TypeX.OBJECTARRAY),
+ extractedMethod.allocateLocal(1));
+
+ int len = superConstructorTypes.length;
+
+ body.append(Utility.createConstant(fact, len));
+
+ body.append((Instruction)fact.createNewArray(Type.OBJECT, (short)1));
+ arrayVar.appendStore(body, fact);
+
+ for (int i = len - 1; i >= 0; i++) {
+ // convert thing on top of stack to object
+ body.append(
+ Utility.createConversion(fact, superConstructorTypes[i], Type.OBJECT));
+ // push object array
+ arrayVar.appendLoad(body, fact);
+ // swap
+ body.append(fact.SWAP);
+ // do object array store.
+ body.append(Utility.createConstant(fact, i));
+ body.append(fact.SWAP);
+ body.append(fact.createArrayStore(Type.OBJECT));
+ }
+ arrayVar.appendLoad(body, fact);
+ body.append(fact.ARETURN);
+ }
+
+ private Type[] getSuperConstructorParameterTypes() {
+ // assert getKind() == PreInitialization
+ InstructionHandle superCallHandle = getRange().getEnd().getNext();
+ InvokeInstruction superCallInstruction =
+ (InvokeInstruction) superCallHandle.getInstruction();
+ return superCallInstruction.getArgumentTypes(
+ getEnclosingClass().getConstantPoolGen());
+ }
+
+
+ /** make a map from old frame location to new frame location. Any unkeyed frame
+ * location picks out a copied local */
+ private IntMap makeRemap() {
+ IntMap ret = new IntMap(5);
+ int reti = 0;
+ if (targetVar != null) {
+ ret.put(targetVar.getSlot(), reti++);
+ }
+ for (int i = 0, len = argVars.length; i < len; i++) {
+ ret.put(argVars[i].getSlot(), reti);
+ reti += argVars[i].getType().getSize();
+ }
+ if (thisJoinPointVar != null) {
+ ret.put(thisJoinPointVar.getSlot(), reti++);
+ }
+ // we not only need to put the arguments, we also need to remap their
+ // aliases, which we so helpfully put into temps at the beginning of this join
+ // point.
+ if (! getKind().argsOnStack()) {
+ int index = 0;
+ if (hasThis()) { ret.put(0, 0); index++; }
+ for (int i = 0; i < getArgCount(); i++) {
+ TypeX type = getArgType(i);
+ ret.put(index, index);
+ index += type.getSize();
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * The new method is nonStatic iff we're from nonExpression advice
+ * with an enclosing non-static method.
+ * Otherwise, it's static
+ */
+ private LazyMethodGen createMethodGen(String newMethodName) {
+ Type[] parameterTypes = world.makeBcelTypes(getSignature().getParameterTypes());
+ int modifiers = Modifier.FINAL;
+
+ // XXX some bug
+// if (! isExpressionKind() && getSignature().isStrict(world)) {
+// modifiers |= Modifier.STRICT;
+// }
+ modifiers |= Modifier.STATIC;
+ if (hasTarget()) {
+ TypeX targetType = getTargetType();
+ parameterTypes = addType(world.makeBcelType(targetType), parameterTypes);
+ }
+
+ // We always want to pass down thisJoinPoint in case we have already woven
+ // some advice in here. If we only have a single piece of around advice on a
+ // join point, it is unnecessary to accept (and pass) tjp.
+ if (thisJoinPointVar != null) {
+ parameterTypes = addTypeToEnd(LazyClassGen.tjpType, parameterTypes);
+ }
+
+ TypeX returnType;
+ if (getKind() == ConstructorCall) {
+ returnType = getSignature().getDeclaringType();
+ } else if (getKind() == PreInitialization) {
+ returnType = TypeX.OBJECTARRAY;
+ } else {
+ returnType = getSignature().getReturnType();
+ }
+ return
+ new LazyMethodGen(
+ modifiers,
+ world.makeBcelType(returnType),
+ newMethodName,
+ parameterTypes,
+ new String[0],
+ // XXX again, we need to look up methods!
+// TypeX.getNames(getSignature().getExceptions(world)),
+ getEnclosingClass());
+ }
+
+ private Type[] addType(Type type, Type[] types) {
+ int len = types.length;
+ Type[] ret = new Type[len+1];
+ ret[0] = type;
+ System.arraycopy(types, 0, ret, 1, len);
+ return ret;
+ }
+
+ private Type[] addTypeToEnd(Type type, Type[] types) {
+ int len = types.length;
+ Type[] ret = new Type[len+1];
+ ret[len] = type;
+ System.arraycopy(types, 0, ret, 0, len);
+ return ret;
+ }
+
+ public BcelVar genTempVar(TypeX typeX) {
+ return new BcelVar(typeX.resolve(world), genTempVarIndex(typeX.getSize()));
+ }
+
+// public static final boolean CREATE_TEMP_NAMES = true;
+
+ public BcelVar genTempVar(TypeX typeX, String localName) {
+ BcelVar tv = genTempVar(typeX);
+
+// if (CREATE_TEMP_NAMES) {
+// for (InstructionHandle ih = range.getStart(); ih != range.getEnd(); ih = ih.getNext()) {
+// if (Range.isRangeHandle(ih)) continue;
+// ih.addTargeter(new LocalVariableTag(typeX, localName, tv.getSlot()));
+// }
+// }
+ return tv;
+ }
+
+ // eh doesn't think we need to garbage collect these (64K is a big number...)
+ private int genTempVarIndex(int size) {
+ return enclosingMethod.allocateLocal(size);
+ }
+
+ public InstructionFactory getFactory() {
+ return getEnclosingClass().getFactory();
+ }
+
+ public SourceLocation getSourceLocation() {
+ return new SourceLocation(new File(getEnclosingClass().getFileName()), getSourceLine());
+ }
+
+ public BcelShadow getEnclosingShadow() {
+ return enclosingShadow;
+ }
+
+ public LazyMethodGen getEnclosingMethod() {
+ return enclosingMethod;
+ }
+
+ public boolean isFallsThrough() {
+ return fallsThrough;
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelSourceContext.java b/weaver/src/org/aspectj/weaver/bcel/BcelSourceContext.java
new file mode 100644
index 000000000..aedfe074b
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelSourceContext.java
@@ -0,0 +1,55 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.File;
+import java.util.Arrays;
+
+import org.aspectj.bridge.*;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.AjAttribute.SourceContextAttribute;
+
+public class BcelSourceContext implements ISourceContext {
+ private BcelObjectType inObject;
+ private String sourceFileName;
+ private int[] lineBreaks;
+
+ public BcelSourceContext(BcelObjectType inObject) {
+ this.inObject = inObject;
+ }
+
+
+ public ISourceLocation makeSourceLocation(IHasPosition position) {
+ String fileName = sourceFileName;
+ if (fileName == null) inObject.getJavaClass().getFileName();
+ if (fileName == null) fileName = inObject.getName() + ".class";
+
+ if (lineBreaks != null) {
+ int line = Arrays.binarySearch(lineBreaks, position.getStart());
+ if (line < 0) line = -line;
+ return new SourceLocation(new File(fileName), line); //??? have more info
+ } else {
+ return new SourceLocation(new File(fileName), 0);
+ }
+ }
+
+
+
+ public void addAttributeInfo(SourceContextAttribute sourceContextAttribute) {
+ this.sourceFileName = sourceContextAttribute.getSourceFileName();
+ this.lineBreaks = sourceContextAttribute.getLineBreaks();
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java
new file mode 100644
index 000000000..a14f0e0b3
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java
@@ -0,0 +1,566 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.patterns.*;
+
+
+//XXX addLazyMethodGen is probably bad everywhere
+public class BcelTypeMunger extends ConcreteTypeMunger {
+
+ public BcelTypeMunger(ResolvedTypeMunger munger, ResolvedTypeX aspectType) {
+ super(munger, aspectType);
+ }
+
+ public String toString() {
+ return "(BcelTypeMunger " + getMunger() + ")";
+ }
+
+ public boolean munge(BcelClassWeaver weaver) {
+ if (munger.getKind() == ResolvedTypeMunger.Field) {
+ return mungeNewField(weaver, (NewFieldTypeMunger)munger);
+ } else if (munger.getKind() == ResolvedTypeMunger.Method) {
+ return mungeNewMethod(weaver, (NewMethodTypeMunger)munger);
+ } else if (munger.getKind() == ResolvedTypeMunger.PerObjectInterface) {
+ return mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger)munger);
+ } else if (munger.getKind() == ResolvedTypeMunger.PrivilegedAccess) {
+ return mungePrivilegedAccess(weaver, (PrivilegedAccessMunger)munger);
+ } else if (munger.getKind() == ResolvedTypeMunger.Constructor) {
+ return mungeNewConstructor(weaver, (NewConstructorTypeMunger)munger);
+ } else {
+ throw new RuntimeException("unimplemented");
+ }
+ }
+
+
+
+ private boolean mungePrivilegedAccess(
+ BcelClassWeaver weaver,
+ PrivilegedAccessMunger munger)
+ {
+ LazyClassGen gen = weaver.getLazyClassGen();
+ ResolvedMember member = munger.getMember();
+
+ ResolvedTypeX onType = weaver.getWorld().resolve(member.getDeclaringType());
+ //System.out.println("munging: " + gen + " with " + member);
+ if (onType.equals(gen.getType())) {
+ if (member.getKind() == Member.FIELD) {
+ //System.out.println("matched: " + gen);
+ addFieldGetter(gen, member,
+ AjcMemberMaker.privilegedAccessMethodForFieldGet(aspectType, member));
+ addFieldSetter(gen, member,
+ AjcMemberMaker.privilegedAccessMethodForFieldSet(aspectType, member));
+ return true;
+ } else if (member.getKind() == Member.METHOD) {
+ addMethodDispatch(gen, member,
+ AjcMemberMaker.privilegedAccessMethodForMethod(aspectType, member));
+ } else {
+ throw new RuntimeException("unimplemented");
+ }
+ }
+ return false;
+ }
+
+ private void addFieldGetter(
+ LazyClassGen gen,
+ ResolvedMember field,
+ ResolvedMember accessMethod)
+ {
+ LazyMethodGen mg = makeMethodGen(gen, accessMethod);
+ InstructionList il = new InstructionList();
+ InstructionFactory fact = gen.getFactory();
+ if (field.isStatic()) {
+ il.append(fact.createFieldAccess(
+ gen.getClassName(),
+ field.getName(),
+ BcelWorld.makeBcelType(field.getType()), Constants.GETSTATIC));
+ } else {
+ il.append(fact.ALOAD_0);
+ il.append(fact.createFieldAccess(
+ gen.getClassName(),
+ field.getName(),
+ BcelWorld.makeBcelType(field.getType()), Constants.GETFIELD));
+ }
+ il.append(fact.createReturn(BcelWorld.makeBcelType(field.getType())));
+ mg.getBody().insert(il);
+
+ gen.addMethodGen(mg);
+ }
+
+ private void addFieldSetter(
+ LazyClassGen gen,
+ ResolvedMember field,
+ ResolvedMember accessMethod)
+ {
+ LazyMethodGen mg = makeMethodGen(gen, accessMethod);
+ InstructionList il = new InstructionList();
+ InstructionFactory fact = gen.getFactory();
+ Type fieldType = BcelWorld.makeBcelType(field.getType());
+
+ if (field.isStatic()) {
+ il.append(fact.createLoad(fieldType, 0));
+ il.append(fact.createFieldAccess(
+ gen.getClassName(),
+ field.getName(),
+ fieldType, Constants.PUTSTATIC));
+ } else {
+ il.append(fact.ALOAD_0);
+ il.append(fact.createLoad(fieldType, 1));
+ il.append(fact.createFieldAccess(
+ gen.getClassName(),
+ field.getName(),
+ fieldType, Constants.PUTFIELD));
+ }
+ il.append(fact.createReturn(Type.VOID));
+ mg.getBody().insert(il);
+
+ gen.addMethodGen(mg);
+ }
+
+ private void addMethodDispatch(
+ LazyClassGen gen,
+ ResolvedMember method,
+ ResolvedMember accessMethod)
+ {
+ LazyMethodGen mg = makeMethodGen(gen, accessMethod);
+ InstructionList il = new InstructionList();
+ InstructionFactory fact = gen.getFactory();
+ //Type fieldType = BcelWorld.makeBcelType(field.getType());
+ Type[] paramTypes = BcelWorld.makeBcelTypes(method.getParameterTypes());
+
+ int pos = 0;
+
+ if (!method.isStatic()) {
+ il.append(fact.ALOAD_0);
+ pos++;
+ }
+ for (int i = 0, len = paramTypes.length; i < len; i++) {
+ Type paramType = paramTypes[i];
+ il.append(fact.createLoad(paramType, pos));
+ pos+=paramType.getSize();
+ }
+ il.append(Utility.createInvoke(fact, (BcelWorld)aspectType.getWorld(),
+ method));
+ il.append(fact.createReturn(BcelWorld.makeBcelType(method.getReturnType())));
+
+ mg.getBody().insert(il);
+
+ gen.addMethodGen(mg);
+ }
+
+
+
+ private LazyMethodGen makeMethodGen(LazyClassGen gen, ResolvedMember member) {
+ return new LazyMethodGen(
+ member.getModifiers(),
+ BcelWorld.makeBcelType(member.getReturnType()),
+ member.getName(),
+ BcelWorld.makeBcelTypes(member.getParameterTypes()),
+ TypeX.getNames(member.getExceptions()),
+ gen);
+ }
+
+
+ private FieldGen makeFieldGen(LazyClassGen gen, ResolvedMember member) {
+ return new FieldGen(
+ member.getModifiers(),
+ BcelWorld.makeBcelType(member.getReturnType()),
+ member.getName(),
+ gen.getConstantPoolGen());
+ }
+
+
+
+
+ private boolean mungePerObjectInterface(
+ BcelClassWeaver weaver,
+ PerObjectInterfaceTypeMunger munger)
+ {
+ LazyClassGen gen = weaver.getLazyClassGen();
+
+ if (couldMatch(gen.getType(), munger.getTestPointcut())) {
+ FieldGen fg = makeFieldGen(gen,
+ AjcMemberMaker.perObjectField(gen.getType(), aspectType));
+
+ gen.addField(fg.getField());
+
+
+ Type fieldType = BcelWorld.makeBcelType(aspectType);
+ LazyMethodGen mg = new LazyMethodGen(
+ Modifier.PUBLIC,
+ fieldType,
+ NameMangler.perObjectInterfaceGet(aspectType),
+ new Type[0], new String[0],
+ gen);
+ InstructionList il = new InstructionList();
+ InstructionFactory fact = gen.getFactory();
+ il.append(fact.ALOAD_0);
+ il.append(fact.createFieldAccess(
+ gen.getClassName(),
+ fg.getName(),
+ fieldType, Constants.GETFIELD));
+ il.append(fact.createReturn(fieldType));
+ mg.getBody().insert(il);
+
+ gen.addMethodGen(mg);
+
+ LazyMethodGen mg1 = new LazyMethodGen(
+ Modifier.PUBLIC,
+ Type.VOID,
+ NameMangler.perObjectInterfaceSet(aspectType),
+
+ new Type[]{fieldType,}, new String[0],
+ gen);
+ InstructionList il1 = new InstructionList();
+ il1.append(fact.ALOAD_0);
+ il1.append(fact.createLoad(fieldType, 1));
+ il1.append(fact.createFieldAccess(
+ gen.getClassName(),
+ fg.getName(),
+ fieldType, Constants.PUTFIELD));
+ il1.append(fact.createReturn(Type.VOID));
+ mg1.getBody().insert(il1);
+
+ gen.addMethodGen(mg1);
+
+ gen.addInterface(munger.getInterfaceType());
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean couldMatch(
+ BcelObjectType bcelObjectType,
+ Pointcut pointcut) {
+ return !bcelObjectType.isInterface();
+ }
+
+ private boolean mungeNewMethod(BcelClassWeaver weaver, NewMethodTypeMunger munger) {
+ ResolvedMember signature = munger.getSignature();
+ ResolvedMember dispatchMethod = munger.getDispatchMethod(aspectType);
+
+ LazyClassGen gen = weaver.getLazyClassGen();
+
+ ResolvedTypeX onType = weaver.getWorld().resolve(signature.getDeclaringType());
+ boolean onInterface = onType.isInterface();
+
+ if (onType.equals(gen.getType())) {
+ ResolvedMember introMethod =
+ AjcMemberMaker.interMethod(signature, aspectType, onInterface);
+
+ LazyMethodGen mg = makeMethodGen(gen, introMethod);
+
+ if (!onInterface && !Modifier.isAbstract(introMethod.getModifiers())) {
+ InstructionList body = mg.getBody();
+ InstructionFactory fact = gen.getFactory();
+ int pos = 0;
+
+ if (!signature.isStatic()) {
+ body.append(fact.createThis());
+ pos++;
+ }
+ Type[] paramTypes = BcelWorld.makeBcelTypes(introMethod.getParameterTypes());
+ for (int i = 0, len = paramTypes.length; i < len; i++) {
+ Type paramType = paramTypes[i];
+ body.append(fact.createLoad(paramType, pos));
+ pos+=paramType.getSize();
+ }
+ body.append(Utility.createInvoke(fact, weaver.getWorld(), dispatchMethod));
+ body.append(fact.createReturn(BcelWorld.makeBcelType(introMethod.getReturnType())));
+ } else {
+ //??? this is okay
+ //if (!(mg.getBody() == null)) throw new RuntimeException("bas");
+ }
+
+
+ // XXX make sure to check that we set exceptions properly on this guy.
+ weaver.addLazyMethodGen(mg);
+
+ Set neededSuperCalls = munger.getSuperMethodsCalled();
+
+ for (Iterator iter = neededSuperCalls.iterator(); iter.hasNext(); ) {
+ ResolvedMember superMethod = (ResolvedMember) iter.next();
+ if (weaver.addDispatchTarget(superMethod)) {
+ String dispatchName = genSuperDispatchName(onType, superMethod);
+ LazyMethodGen dispatcher = makeDispatcher(gen, dispatchName, superMethod, weaver.getWorld());
+
+ weaver.addLazyMethodGen(dispatcher);
+ }
+ }
+
+ return true;
+ } else if (onInterface && gen.getType().isTopmostImplementor(onType) &&
+ !Modifier.isAbstract(signature.getModifiers()))
+ {
+ ResolvedMember introMethod =
+ AjcMemberMaker.interMethod(signature, aspectType, false);
+
+ LazyMethodGen mg = makeMethodGen(gen, introMethod);
+
+ //
+
+ Type[] paramTypes = BcelWorld.makeBcelTypes(introMethod.getParameterTypes());
+ Type returnType = BcelWorld.makeBcelType(introMethod.getReturnType());
+
+ InstructionList body = mg.getBody();
+ InstructionFactory fact = gen.getFactory();
+ int pos = 0;
+
+ if (!introMethod.isStatic()) {
+ body.append(fact.createThis());
+ pos++;
+ }
+ for (int i = 0, len = paramTypes.length; i < len; i++) {
+ Type paramType = paramTypes[i];
+ body.append(fact.createLoad(paramType, pos));
+ pos+=paramType.getSize();
+ }
+ body.append(Utility.createInvoke(fact, weaver.getWorld(), dispatchMethod));
+ body.append(fact.createReturn(returnType));
+ mg.definingType = onType;
+
+ weaver.addOrReplaceLazyMethodGen(mg);
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ private boolean mungeNewConstructor(
+ BcelClassWeaver weaver,
+ NewConstructorTypeMunger newConstructorTypeMunger)
+ {
+ final LazyClassGen currentClass = weaver.getLazyClassGen();
+ final InstructionFactory fact = currentClass.getFactory();
+
+ ResolvedMember newConstructorMember = newConstructorTypeMunger.getSyntheticConstructor();
+ TypeX onType = newConstructorMember.getDeclaringType();
+
+
+ if (! onType.equals(currentClass.getType())) return false;
+
+ ResolvedMember explicitConstructor = newConstructorTypeMunger.getExplicitConstructor();
+ //int declaredParameterCount = newConstructorTypeMunger.getDeclaredParameterCount();
+ LazyMethodGen freshConstructor =
+ makeMethodGen(currentClass, newConstructorMember);
+ currentClass.addMethodGen(freshConstructor);
+ //weaver.addLazyMethodGen(freshConstructor);
+
+ InstructionList body = freshConstructor.getBody();
+
+ // add to body: push arts for call to pre, from actual args starting at 1 (skipping this), going to
+ // declared argcount + 1
+ TypeX[] declaredParams = newConstructorTypeMunger.getSignature().getParameterTypes();
+ Type[] paramTypes = freshConstructor.getArgumentTypes();
+ int frameIndex = 1;
+ for (int i = 0, len = declaredParams.length; i < len; i++) {
+ body.append(fact.createLoad(paramTypes[i], frameIndex));
+ frameIndex += paramTypes[i].getSize();
+ }
+ // do call to pre
+ Member preMethod = AjcMemberMaker.preIntroducedConstructor(aspectType, onType, declaredParams);
+ body.append(Utility.createInvoke(fact, null, preMethod));
+
+ // create a local, and store return pre stuff into it.
+ int arraySlot = freshConstructor.allocateLocal(1);
+ body.append(fact.createStore(Type.OBJECT, arraySlot));
+
+ // put this on the stack
+ body.append(fact.ALOAD_0);
+
+ // unpack pre args onto stack
+ TypeX[] superParamTypes = explicitConstructor.getParameterTypes();
+
+ for (int i = 0, len = superParamTypes.length; i < len; i++) {
+ body.append(fact.createLoad(Type.OBJECT, arraySlot));
+ body.append(Utility.createConstant(fact, i));
+ body.append(fact.createArrayLoad(Type.OBJECT));
+ body.append(Utility.createConversion(fact, Type.OBJECT, BcelWorld.makeBcelType(superParamTypes[i])));
+ }
+
+ // call super/this
+
+ body.append(Utility.createInvoke(fact, null, explicitConstructor));
+
+ // put this back on the stack
+
+ body.append(fact.ALOAD_0);
+
+ // unpack params onto stack
+ Member postMethod = AjcMemberMaker.postIntroducedConstructor(aspectType, onType, declaredParams);
+ TypeX[] postParamTypes = postMethod.getParameterTypes();
+
+ for (int i = 1, len = postParamTypes.length; i < len; i++) {
+ body.append(fact.createLoad(Type.OBJECT, arraySlot));
+ body.append(Utility.createConstant(fact, superParamTypes.length + i-1));
+ body.append(fact.createArrayLoad(Type.OBJECT));
+ body.append(Utility.createConversion(fact, Type.OBJECT, BcelWorld.makeBcelType(postParamTypes[i])));
+ }
+
+ // call post
+ body.append(Utility.createInvoke(fact, null, postMethod));
+
+ // don't forget to return!!
+
+ body.append(fact.RETURN);
+
+ return true;
+ }
+
+
+ private static LazyMethodGen makeDispatcher(
+ LazyClassGen onGen,
+ String dispatchName,
+ ResolvedMember superMethod,
+ BcelWorld world)
+ {
+ Type[] paramTypes = BcelWorld.makeBcelTypes(superMethod.getParameterTypes());
+ Type returnType = BcelWorld.makeBcelType(superMethod.getReturnType());
+
+ LazyMethodGen mg =
+ new LazyMethodGen(
+ Modifier.PUBLIC,
+ returnType,
+ dispatchName,
+ paramTypes,
+ TypeX.getNames(superMethod.getExceptions()),
+ onGen);
+ InstructionList body = mg.getBody();
+
+ // assert (!superMethod.isStatic())
+ InstructionFactory fact = onGen.getFactory();
+ int pos = 0;
+
+ body.append(fact.createThis());
+ pos++;
+ for (int i = 0, len = paramTypes.length; i < len; i++) {
+ Type paramType = paramTypes[i];
+ body.append(fact.createLoad(paramType, pos));
+ pos+=paramType.getSize();
+ }
+ body.append(Utility.createSuperInvoke(fact, world, superMethod));
+ body.append(fact.createReturn(returnType));
+
+ return mg;
+ }
+
+
+ private static String genSuperDispatchName(
+ ResolvedTypeX onType,
+ ResolvedMember superMethod)
+ {
+ return "ajc$" + ResolvedTypeMunger.SUPER_DISPATCH_NAME + "$" + onType.getNameAsIdentifier() + "$" + superMethod.getName();
+ }
+
+
+
+ private boolean mungeNewField(BcelClassWeaver weaver, NewFieldTypeMunger munger) {
+ ResolvedMember initMethod = munger.getInitMethod(aspectType);
+
+ LazyClassGen gen = weaver.getLazyClassGen();
+ ResolvedMember field = munger.getSignature();
+
+
+ ResolvedTypeX onType = weaver.getWorld().resolve(field.getDeclaringType());
+ boolean onInterface = onType.isInterface();
+
+ if (onType.equals(gen.getType())) {
+ if (onInterface) {
+ LazyMethodGen mg = makeMethodGen(gen,
+ AjcMemberMaker.interFieldInterfaceGetter(field, onType, aspectType));
+ gen.addMethodGen(mg);
+
+ LazyMethodGen mg1 = makeMethodGen(gen,
+ AjcMemberMaker.interFieldInterfaceSetter(field, onType, aspectType));
+ gen.addMethodGen(mg1);
+ } else {
+ weaver.addInitializer(this);
+ FieldGen fg = makeFieldGen(gen,
+ AjcMemberMaker.interFieldClassField(field, aspectType));
+ gen.addField(fg.getField());
+ }
+ return true;
+ } else if (onInterface && gen.getType().isTopmostImplementor(onType)) {
+ // wew know that we can't be static since we don't allow statics on interfaces
+ if (field.isStatic()) throw new RuntimeException("unimplemented");
+ weaver.addInitializer(this);
+ //System.err.println("impl body on " + gen.getType() + " for " + munger);
+ Type fieldType = BcelWorld.makeBcelType(field.getType());
+
+ FieldGen fg = makeFieldGen(gen,
+ AjcMemberMaker.interFieldInterfaceField(field, onType, aspectType));
+ gen.addField(fg.getField());
+
+ //this uses a shadow munger to add init method to constructors
+ //weaver.getShadowMungers().add(makeInitCallShadowMunger(initMethod));
+
+ LazyMethodGen mg = makeMethodGen(gen,
+ AjcMemberMaker.interFieldInterfaceGetter(field, gen.getType(), aspectType));
+ InstructionList il = new InstructionList();
+ InstructionFactory fact = gen.getFactory();
+ if (field.isStatic()) {
+ il.append(fact.createFieldAccess(
+ gen.getClassName(),
+ fg.getName(),
+ fieldType, Constants.GETSTATIC));
+ } else {
+ il.append(fact.ALOAD_0);
+ il.append(fact.createFieldAccess(
+ gen.getClassName(),
+ fg.getName(),
+ fieldType, Constants.GETFIELD));
+ }
+ il.append(fact.createReturn(fieldType));
+ mg.getBody().insert(il);
+
+ gen.addMethodGen(mg);
+
+ LazyMethodGen mg1 = makeMethodGen(gen,
+ AjcMemberMaker.interFieldInterfaceSetter(field, gen.getType(), aspectType));
+ InstructionList il1 = new InstructionList();
+ if (field.isStatic()) {
+ il1.append(fact.createLoad(fieldType, 0));
+ il1.append(fact.createFieldAccess(
+ gen.getClassName(),
+ fg.getName(),
+ fieldType, Constants.PUTSTATIC));
+ } else {
+ il1.append(fact.ALOAD_0);
+ il1.append(fact.createLoad(fieldType, 1));
+ il1.append(fact.createFieldAccess(
+ gen.getClassName(),
+ fg.getName(),
+ fieldType, Constants.PUTFIELD));
+ }
+ il1.append(fact.createReturn(Type.VOID));
+ mg1.getBody().insert(il1);
+
+ gen.addMethodGen(mg1);
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelVar.java b/weaver/src/org/aspectj/weaver/bcel/BcelVar.java
new file mode 100644
index 000000000..8423e9c79
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelVar.java
@@ -0,0 +1,126 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ResolvedTypeX;
+import org.aspectj.weaver.ast.Var;
+
+public class BcelVar extends Var {
+
+ private int positionInAroundState = -1;
+
+ private int slot;
+
+ public BcelVar(ResolvedTypeX type, int slot) {
+ super(type);
+ this.slot = slot;
+ }
+
+ public String toString() {
+ return "BcelVar(" + getType() + " " + slot +
+ ((positionInAroundState != -1) ? (" " + positionInAroundState) : "") +
+
+ ")";
+ }
+
+ public int getSlot() { return slot; }
+
+ public Instruction createLoad(InstructionFactory fact) {
+ return fact.createLoad(BcelWorld.makeBcelType(getType()), slot);
+ }
+ public Instruction createStore(InstructionFactory fact) {
+ return fact.createStore(BcelWorld.makeBcelType(getType()), slot);
+ }
+
+ public void appendStore(InstructionList il, InstructionFactory fact) {
+ il.append(createStore(fact));
+ }
+ public void appendLoad(InstructionList il, InstructionFactory fact) {
+ il.append(createLoad(fact));
+ }
+ public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedTypeX toType) {
+ il.append(createLoad(fact));
+ Utility.appendConversion(il, fact, getType(), toType);
+ }
+ public void insertLoad(InstructionList il, InstructionFactory fact) {
+ il.insert(createLoad(fact));
+ }
+ public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) {
+ InstructionList il = new InstructionList();
+ il.append(fact.createLoad(BcelWorld.makeBcelType(getType()), oldSlot));
+ il.append(createStore(fact));
+ return il;
+ }
+
+ // this is an array var
+ void appendConvertableArrayLoad(
+ InstructionList il,
+ InstructionFactory fact,
+ int index,
+ ResolvedTypeX convertTo)
+ {
+ ResolvedTypeX convertFromType = getType().getResolvedComponentType();
+ appendLoad(il, fact);
+ il.append(Utility.createConstant(fact, index));
+ il.append(fact.createArrayLoad(BcelWorld.makeBcelType(convertFromType)));
+ Utility.appendConversion(il, fact, convertFromType, convertTo);
+ }
+
+ void appendConvertableArrayStore(
+ InstructionList il,
+ InstructionFactory fact,
+ int index,
+ BcelVar storee)
+ {
+ ResolvedTypeX convertToType = getType().getResolvedComponentType();
+ appendLoad(il, fact);
+ il.append(Utility.createConstant(fact, index));
+ storee.appendLoad(il, fact);
+ Utility.appendConversion(il, fact, storee.getType(), convertToType);
+ il.append(fact.createArrayStore(BcelWorld.makeBcelType(convertToType)));
+ }
+
+ InstructionList createConvertableArrayStore(
+ InstructionFactory fact,
+ int index,
+ BcelVar storee)
+ {
+ InstructionList il = new InstructionList();
+ appendConvertableArrayStore(il, fact, index, storee);
+ return il;
+ }
+ InstructionList createConvertableArrayLoad(
+ InstructionFactory fact,
+ int index,
+ ResolvedTypeX convertTo)
+ {
+ InstructionList il = new InstructionList();
+ appendConvertableArrayLoad(il, fact, index, convertTo);
+ return il;
+ }
+ public int getPositionInAroundState() {
+ return positionInAroundState;
+ }
+
+ public void setPositionInAroundState(int positionInAroundState) {
+ this.positionInAroundState = positionInAroundState;
+ }
+
+ // random useful fields
+
+ public static final BcelVar[] NONE = new BcelVar[] {};
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
new file mode 100644
index 000000000..63eb043d5
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
@@ -0,0 +1,374 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+
+import org.apache.bcel.classfile.*;
+import org.apache.bcel.classfile.JavaClass;
+import org.aspectj.util.FileUtil;
+import org.aspectj.weaver.*;
+
+public class BcelWeaver implements IWeaver {
+ private BcelWorld world;
+ private CrosscuttingMembersSet xcutSet;
+
+ public BcelWeaver(BcelWorld world) {
+ super();
+ this.world = world;
+ this.xcutSet = world.getCrosscuttingMembersSet();
+ }
+
+ public BcelWeaver() {
+ this(new BcelWorld());
+ }
+
+ // ---- fields
+ private Map sourceJavaClasses = new HashMap(); /* String -> UnwovenClassFile */
+ private List addedClasses = new ArrayList(); /* List<UnovenClassFile> */
+ private List deletedTypenames = new ArrayList(); /* List<String> */
+ private boolean needToReweaveWorld = false;
+
+ private List shadowMungerList = null; // setup by prepareForWeave
+ private List typeMungerList = null; // setup by prepareForWeave
+
+ private ZipOutputStream zipOutputStream;
+
+ // ----
+
+ // only called for testing
+ public void setShadowMungers(List l) {
+ shadowMungerList = l;
+ }
+
+
+ public void addLibraryAspect(String aspectName) {
+ ResolvedTypeX type = world.resolve(aspectName);
+ System.out.println("type: " + type + " for " + aspectName);
+ if (type.isAspect()) {
+ xcutSet.addOrReplaceAspect(type);
+ } else {
+ throw new RuntimeException("unimplemented");
+ }
+ }
+
+
+
+ public void addLibraryJarFile(File inFile) throws IOException {
+ ZipInputStream inStream = new ZipInputStream(new FileInputStream(inFile)); //??? buffered
+
+ List addedAspects = new ArrayList();
+
+ while (true) {
+ ZipEntry entry = inStream.getNextEntry();
+ if (entry == null) break;
+
+ if (entry.isDirectory() || !entry.getName().endsWith(".class")) {
+ continue;
+ }
+
+ ClassParser parser = new ClassParser(new ByteArrayInputStream(FileUtil.readAsByteArray(inStream)), entry.getName());
+ JavaClass jc = parser.parse();
+ inStream.closeEntry();
+
+ ResolvedTypeX type = world.addSourceObjectType(jc);
+ if (type.isAspect()) {
+ addedAspects.add(type);
+ }
+
+ }
+
+ inStream.close();
+
+ for (Iterator i = addedAspects.iterator(); i.hasNext();) {
+ ResolvedTypeX aspectX = (ResolvedTypeX) i.next();
+ xcutSet.addOrReplaceAspect(aspectX);
+ }
+ }
+
+
+ /** Adds all class files in the jar
+ */
+ public void addJarFile(File inFile, File outDir) throws IOException {
+ needToReweaveWorld = true;
+ //System.err.println("adding jar: " + inFile);
+ ZipInputStream inStream = new ZipInputStream(new FileInputStream(inFile)); //??? buffered
+
+ while (true) {
+ ZipEntry entry = inStream.getNextEntry();
+ if (entry == null) break;
+
+ if (entry.isDirectory() || !entry.getName().endsWith(".class")) {
+ continue; //??? need to pass other things along untouched
+// outStream.putNextEntry(entry);
+// outStream.write(Utility.getByteArray(inStream));
+// outStream.closeEntry();
+// return;
+ }
+ //System.err.println("adding class: " + entry.getName());
+
+ byte[] bytes = FileUtil.readAsByteArray(inStream);
+ String filename = entry.getName();
+ UnwovenClassFile classFile = new UnwovenClassFile(new File(outDir, filename).getAbsolutePath(), bytes);
+ inStream.closeEntry();
+ this.addClassFile(classFile);
+ }
+
+ inStream.close();
+ }
+
+
+ /** Should be addOrReplace
+ */
+ public void addClassFile(UnwovenClassFile classFile) {
+ addedClasses.add(classFile);
+ sourceJavaClasses.put(classFile.getClassName(), classFile);
+ world.addSourceObjectType(classFile.getJavaClass());
+ }
+
+
+ public void deleteClassFile(String typename) {
+ deletedTypenames.add(typename);
+ sourceJavaClasses.remove(typename);
+ world.deleteSourceObjectType(TypeX.forName(typename));
+ }
+
+ // ---- weave preparation
+
+ public void prepareForWeave() {
+ needToReweaveWorld = false;
+
+
+ // update mungers
+ for (Iterator i = addedClasses.iterator(); i.hasNext(); ) {
+ UnwovenClassFile jc = (UnwovenClassFile)i.next();
+ String name = jc.getClassName();
+ ResolvedTypeX type = world.resolve(name);
+ if (type.isAspect()) {
+ needToReweaveWorld |= xcutSet.addOrReplaceAspect(type);
+ }
+ }
+
+ for (Iterator i = deletedTypenames.iterator(); i.hasNext(); ) {
+ String name = (String)i.next();
+ xcutSet.deleteAspect(TypeX.forName(name));
+ needToReweaveWorld = true;
+ }
+
+ shadowMungerList = xcutSet.getShadowMungers();
+ typeMungerList = xcutSet.getTypeMungers();
+
+ //XXX this gets us a stable (but completely meaningless) order
+ Collections.sort(
+ shadowMungerList,
+ new Comparator() {
+ public int compare(Object o1, Object o2) {
+ return o1.toString().compareTo(o2.toString());
+ }
+ });
+ }
+
+ public void dumpUnwoven(File file) throws IOException {
+ BufferedOutputStream os = FileUtil.makeOutputStream(file);
+ this.zipOutputStream = new ZipOutputStream(os);
+ dumpUnwoven();
+ zipOutputStream.close(); //this flushes and closes the acutal file
+ }
+
+
+ public void dumpUnwoven() throws IOException {
+ Collection filesToDump = new HashSet(sourceJavaClasses.values());
+ for (Iterator i = filesToDump.iterator(); i.hasNext(); ) {
+ UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+ dumpUnchanged(classFile);
+ }
+ }
+
+
+ // ---- weaving
+
+ public Collection weave(File file) throws IOException {
+ OutputStream os = FileUtil.makeOutputStream(file);
+ this.zipOutputStream = new ZipOutputStream(os);
+ Collection c = weave();
+ zipOutputStream.close(); //this flushes and closes the acutal file
+ return c;
+ }
+
+ public Collection weave() throws IOException {
+ prepareForWeave();
+ Collection filesToWeave;
+ if (needToReweaveWorld) {
+ filesToWeave = sourceJavaClasses.values();
+ } else {
+ filesToWeave = addedClasses;
+ }
+
+ Collection wovenClassNames = new ArrayList();
+
+ //XXX this isn't quite the right place for this...
+ for (Iterator i = filesToWeave.iterator(); i.hasNext(); ) {
+ UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+ String className = classFile.getClassName();
+ ResolvedTypeX onType = world.resolve(className);
+ weave(onType);
+ }
+
+ // first weave into aspects
+ for (Iterator i = filesToWeave.iterator(); i.hasNext(); ) {
+ UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+ String className = classFile.getClassName();
+ BcelObjectType classType = (BcelObjectType) world.resolve(className);
+ if (classType.isAspect()) {
+ weave(classFile, classType);
+ wovenClassNames.add(className);
+ }
+ }
+
+ // then weave into non-aspects
+ for (Iterator i = filesToWeave.iterator(); i.hasNext(); ) {
+ UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+ String className = classFile.getClassName();
+ BcelObjectType classType = (BcelObjectType) world.resolve(className);
+ if (! classType.isAspect()) {
+ weave(classFile, classType);
+ wovenClassNames.add(className);
+ }
+ }
+
+ if (zipOutputStream != null && !needToReweaveWorld) {
+ Collection filesToDump = new HashSet(sourceJavaClasses.values());
+ filesToDump.removeAll(filesToWeave);
+ for (Iterator i = filesToDump.iterator(); i.hasNext(); ) {
+ UnwovenClassFile classFile = (UnwovenClassFile)i.next();
+ dumpUnchanged(classFile);
+ }
+ }
+
+ addedClasses = new ArrayList();
+ deletedTypenames = new ArrayList();
+
+ return wovenClassNames;
+ }
+
+ private void weave(ResolvedTypeX onType) {
+ onType.clearInterTypeMungers();
+ for (Iterator i = typeMungerList.iterator(); i.hasNext(); ) {
+ ConcreteTypeMunger m = (ConcreteTypeMunger)i.next();
+ if (m.matches(onType)) {
+ onType.addInterTypeMunger(m);
+ }
+ }
+ }
+
+
+ // non-private for testing
+ LazyClassGen weave(UnwovenClassFile classFile, BcelObjectType classType) throws IOException {
+ JavaClass javaClass = classType.getJavaClass();
+ List shadowMungers = fastMatch(shadowMungerList, javaClass);
+ List typeMungers = fastMatch(classType.getInterTypeMungers(), javaClass);
+
+ LazyClassGen clazz = null;
+
+ if (shadowMungers.size() > 0 || typeMungers.size() > 0) {
+ clazz = classType.getLazyClassGen();
+ try {
+ boolean isChanged = BcelClassWeaver.weave(world, clazz, shadowMungers, typeMungers);
+ if (isChanged) {
+ dump(classFile, clazz);
+ return clazz;
+ }
+ } catch (RuntimeException re) {
+ System.err.println("trouble in: ");
+ clazz.print(System.err);
+ throw re;
+ } catch (Error re) {
+ System.err.println("trouble in: ");
+ clazz.print(System.err);
+ throw re;
+ }
+ }
+
+ dumpUnchanged(classFile);
+ return clazz;
+ }
+
+ // ---- writing
+
+ private void dumpUnchanged(UnwovenClassFile classFile) throws IOException {
+ if (zipOutputStream != null) {
+ writeZipEntry(getEntryName(classFile.getJavaClass().getClassName()), classFile.getBytes());
+ } else {
+ classFile.writeUnchangedBytes();
+ }
+ }
+
+ private String getEntryName(String className) {
+ //XXX what does bcel's getClassName do for inner names
+ return className.replace('.', '/') + ".class";
+ }
+
+ private void dump(UnwovenClassFile classFile, LazyClassGen clazz) throws IOException {
+ if (zipOutputStream != null) {
+ String mainClassName = classFile.getJavaClass().getClassName();
+
+ writeZipEntry(getEntryName(mainClassName),
+ clazz.getJavaClass().getBytes());
+ if (!clazz.getChildClasses().isEmpty()) {
+ for (Iterator i = clazz.getChildClasses().iterator(); i.hasNext();) {
+ UnwovenClassFile.ChildClass c = (UnwovenClassFile.ChildClass) i.next();
+ writeZipEntry(getEntryName(mainClassName + "$" + c.name), c.bytes);
+ }
+ }
+ } else {
+ classFile.writeWovenBytes(
+ clazz.getJavaClass().getBytes(),
+ clazz.getChildClasses()
+ );
+ }
+ }
+
+ private void writeZipEntry(String name, byte[] bytes) throws IOException {
+ ZipEntry newEntry = new ZipEntry(name); //??? get compression scheme right
+
+ zipOutputStream.putNextEntry(newEntry);
+ zipOutputStream.write(bytes);
+ zipOutputStream.closeEntry();
+ }
+
+ // ---- fast matching
+
+// boolean fastMatch(JavaClass jc) {
+// ConstantPool pool = jc.getConstantPool();
+// for (int i=0, len=pool.getLength(); i < len; i++) {
+// Constant c = pool.getConstant(i);
+// if (c instanceof ConstantNameAndType) {
+// ConstantNameAndType nt = (ConstantNameAndType)c;
+// if (nt.getName(pool).equals("toShortString")) {
+// //System.out.println("found in " + jc);
+// return true;
+// }
+// }
+// }
+// return false;
+// }
+
+ //XXX need to implement a real fast-match here
+ private List fastMatch(List list, JavaClass javaClass) {
+ if (list == null) return Collections.EMPTY_LIST;
+ return list;
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java b/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java
new file mode 100644
index 000000000..1ff0c4e34
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java
@@ -0,0 +1,320 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.*;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.*;
+import java.util.zip.*;
+import java.util.zip.ZipInputStream;
+
+import org.apache.bcel.classfile.*;
+import org.apache.bcel.generic.*;
+import org.apache.bcel.util.ClassPath;
+import org.aspectj.util.FileUtil;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.patterns.*;
+import org.aspectj.asm.StructureModel;
+import org.aspectj.bridge.*;
+import org.aspectj.bridge.IMessageHandler;
+
+public class BcelWorld extends World {
+ private ClassPathManager classPath;
+
+ //private ClassPathManager aspectPath = null;
+ private List aspectPathEntries;
+
+ // ---- constructors
+
+ public BcelWorld() {
+ this("");
+ }
+
+ public BcelWorld(String cp) {
+ this(makeDefaultClasspath(cp), IMessageHandler.THROW);
+ }
+
+ private static List makeDefaultClasspath(String cp) {
+ List classPath = new ArrayList();
+ classPath.addAll(getPathEntries(cp));
+ classPath.addAll(getPathEntries(ClassPath.getClassPath()));
+ //System.err.println("classpath: " + classPath);
+ return classPath;
+
+ }
+
+ private static List getPathEntries(String s) {
+ List ret = new ArrayList();
+ StringTokenizer tok = new StringTokenizer(s, File.pathSeparator);
+
+ while(tok.hasMoreTokens()) ret.add(tok.nextToken());
+
+ return ret;
+ }
+
+ public BcelWorld(List classPath, IMessageHandler handler) {
+ //this.aspectPath = new ClassPathManager(aspectPath, handler);
+ this.classPath = new ClassPathManager(classPath, handler);
+ setMessageHandler(handler);
+ }
+
+ /**
+ * Parse a string into advice.
+ *
+ * <blockquote><pre>
+ * Kind ( Id , ... ) : Pointcut -> MethodSignature
+ * </pre></blockquote>
+ */
+ public Advice shadowMunger(String str, int extraFlag) {
+ str = str.trim();
+ int start = 0;
+ int i = str.indexOf('(');
+ AdviceKind kind =
+ AdviceKind.stringToKind(str.substring(start, i));
+ start = ++i;
+ i = str.indexOf(')', i);
+ String[] ids = parseIds(str.substring(start, i).trim());
+ //start = ++i;
+
+
+
+ i = str.indexOf(':', i);
+ start = ++i;
+ i = str.indexOf("->", i);
+ Pointcut pointcut = Pointcut.fromString(str.substring(start, i).trim());
+ Member m = Member.methodFromString(str.substring(i+2, str.length()).trim());
+
+ // now, we resolve
+ TypeX[] types = m.getParameterTypes();
+ FormalBinding[] bindings = new FormalBinding[ids.length];
+ for (int j = 0, len = ids.length; j < len; j++) {
+ bindings[j] = new FormalBinding(types[j], ids[j], j, 0, 0, "fromString");
+ }
+
+ Pointcut p =
+ pointcut.resolve(new SimpleScope(this, bindings));
+
+ return concreteAdvice(kind, p, m, extraFlag, 0, 0, null);
+ }
+
+ private String[] parseIds(String str) {
+ if (str.length() == 0) return ZERO_STRINGS;
+ List l = new ArrayList();
+ int start = 0;
+ while (true) {
+ int i = str.indexOf(',', start);
+ if (i == -1) {
+ l.add(str.substring(start).trim());
+ break;
+ }
+ l.add(str.substring(start, i).trim());
+ start = i+1;
+ }
+ return (String[]) l.toArray(new String[l.size()]);
+ }
+
+ // ---- various interactions with bcel
+
+ public static Type makeBcelType(TypeX type) {
+ return Type.getType(type.getSignature());
+ }
+
+ static Type[] makeBcelTypes(TypeX[] types) {
+ Type[] ret = new Type[types.length];
+ for (int i = 0, len = types.length; i < len; i++) {
+ ret[i] = makeBcelType(types[i]);
+ }
+ return ret;
+ }
+
+ public static TypeX fromBcel(Type t) {
+ return TypeX.forSignature(t.getSignature());
+ }
+
+ static TypeX[] fromBcel(Type[] ts) {
+ TypeX[] ret = new TypeX[ts.length];
+ for (int i = 0, len = ts.length; i < len; i++) {
+ ret[i] = fromBcel(ts[i]);
+ }
+ return ret;
+ }
+
+ public ResolvedTypeX resolve(Type t) {
+ return resolve(fromBcel(t));
+ }
+
+ // ---- fluf
+ public ResolvedTypeX resolveObjectType(TypeX ty) {
+ String name = ty.getName();
+ JavaClass jc = null;
+ //UnwovenClassFile classFile = (UnwovenClassFile)sourceJavaClasses.get(name);
+ //if (classFile != null) jc = classFile.getJavaClass();
+// if (jc == null) {
+// jc = lookupJavaClass(aspectPath, name);
+// }
+ if (jc == null) {
+ jc = lookupJavaClass(classPath, name);
+ }
+ if (jc == null) {
+ return ResolvedTypeX.MISSING;
+ } else {
+ return new BcelObjectType(ty.getSignature(), this, jc);
+ }
+ }
+
+ private JavaClass lookupJavaClass(ClassPathManager classPath, String name) {
+ if (classPath == null) return null;
+ try {
+ ClassPathManager.ClassFile file = classPath.find(TypeX.forName(name));
+ if (file == null) return null;
+
+ ClassParser parser = new ClassParser(file.getInputStream(), file.getPath());
+
+ JavaClass jc = parser.parse();
+
+ return jc;
+ } catch (IOException ioe) {
+ return null;
+ }
+ }
+
+
+ BcelObjectType addSourceObjectType(JavaClass jc) {
+ String signature = TypeX.forName(jc.getClassName()).getSignature();
+ BcelObjectType ret = (BcelObjectType)typeMap.get(signature);
+ if (ret == null) {
+ ret = new BcelObjectType(signature, this, jc);
+ typeMap.put(signature, ret);
+ } else {
+ ret.replaceJavaClass(jc);
+ }
+ return ret;
+ }
+
+ void deleteSourceObjectType(TypeX ty) {
+ typeMap.remove(ty.getSignature());
+ }
+
+ public static Member makeFieldSignature(LazyClassGen cg, FieldInstruction fi) {
+ ConstantPoolGen cpg = cg.getConstantPoolGen();
+ return
+ Member.field(
+ fi.getClassName(cpg),
+ (fi instanceof GETSTATIC || fi instanceof PUTSTATIC)
+ ? Modifier.STATIC
+ : 0,
+ fi.getName(cpg),
+ fi.getSignature(cpg));
+ }
+
+ public static Member makeFieldSetSignature(LazyClassGen cg, FieldInstruction fi) {
+ ConstantPoolGen cpg = cg.getConstantPoolGen();
+ return
+ Member.field(
+ fi.getClassName(cpg),
+ (fi instanceof GETSTATIC || fi instanceof PUTSTATIC)
+ ? Modifier.STATIC
+ : 0,
+ fi.getName(cpg),
+ "(" + fi.getSignature(cpg) + ")" +fi.getSignature(cpg));
+ }
+
+ public Member makeMethodSignature(LazyMethodGen mg) {
+ ResolvedMember ret = mg.getMemberView();
+ if (ret == null) {
+ int mods = mg.getAccessFlags();
+ if (mg.getEnclosingClass().isInterface()) {
+ mods |= Modifier.INTERFACE;
+ }
+ return new ResolvedMember(mg.getName().equals("<init>") ? Member.CONSTRUCTOR : Member.METHOD,
+ TypeX.forName(mg.getClassName()),
+ mods,
+ fromBcel(mg.getReturnType()),
+ mg.getName(),
+ fromBcel(mg.getArgumentTypes())
+ );
+ } else {
+ return ret;
+ }
+
+ }
+
+ public static Member makeMethodSignature(LazyClassGen cg, InvokeInstruction ii) {
+ ConstantPoolGen cpg = cg.getConstantPoolGen();
+ String declaring = ii.getClassName(cpg);
+ String name = ii.getName(cpg);
+ String signature = ii.getSignature(cpg);
+
+ int modifier =
+ (ii instanceof INVOKEINTERFACE)
+ ? Modifier.INTERFACE
+ : (ii instanceof INVOKESTATIC)
+ ? Modifier.STATIC
+ : (ii instanceof INVOKESPECIAL && ! name.equals("<init>"))
+ ? Modifier.PRIVATE
+ : 0;
+ return Member.method(TypeX.forName(declaring), modifier, name, signature);
+ }
+
+ public static Member makeMungerMethodSignature(JavaClass javaClass, Method method) {
+ int mods = 0;
+ if (method.isStatic()) mods = Modifier.STATIC;
+ else if (javaClass.isInterface()) mods = Modifier.INTERFACE;
+ else if (method.isPrivate()) mods = Modifier.PRIVATE;
+ return Member.method(
+ TypeX.forName(javaClass.getClassName()), mods, method.getName(), method.getSignature());
+ }
+
+ public JavaClass lookupJavaClass(String className) {
+ ResolvedTypeX t = resolve(TypeX.forName(className));
+ if (t instanceof BcelObjectType) {
+ return ((BcelObjectType)t).getJavaClass();
+ } else {
+ return null;
+ }
+ }
+
+ private static final String[] ZERO_STRINGS = new String[0];
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("BcelWorld(");
+ //buf.append(shadowMungerMap);
+ buf.append(")");
+ return buf.toString();
+ }
+
+ public Advice concreteAdvice(
+ AdviceKind kind,
+ Pointcut p,
+ Member signature,
+ int extraParameterFlags,
+ int start, int end, ISourceContext sourceContext)
+ {
+ //System.err.println("concrete advice: " + signature + " context " + sourceContext);
+ return new BcelAdvice(kind, p, signature, extraParameterFlags, start, end, sourceContext, null);
+ }
+
+ public ConcreteTypeMunger concreteTypeMunger(
+ ResolvedTypeMunger munger, ResolvedTypeX aspectType)
+ {
+ return new BcelTypeMunger(munger, aspectType);
+ }
+
+ public ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField) {
+ return new BcelCflowStackFieldAdder(cflowField);
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java b/weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java
new file mode 100644
index 000000000..6f8d6deba
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.*;
+import java.io.File;
+import java.util.*;
+import java.util.zip.*;
+import java.util.zip.ZipFile;
+
+import org.aspectj.bridge.*;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.weaver.TypeX;
+
+
+public class ClassPathManager {
+
+ private List entries;
+
+ public ClassPathManager(List classpath, IMessageHandler handler) {
+ entries = new ArrayList();
+ for (Iterator i = classpath.iterator(); i.hasNext();) {
+ String name = (String) i.next();
+ File f = new File(name);
+ String lc = name.toLowerCase();
+ if (lc.endsWith(".jar") || lc.endsWith(".zip")) {
+ if (!f.isFile()) {
+ MessageUtil.info(handler, "zipfile classpath entry does not exist: " + name);
+ continue;
+ }
+ try {
+ entries.add(new ZipFileEntry(f));
+ } catch (IOException ioe) {
+ MessageUtil.warn(handler, "zipfile classpath entry is invalid: " + name + "<" + ioe.getMessage() + ">");
+ continue;
+ }
+ } else {
+ if (!f.isDirectory()) {
+ MessageUtil.info(handler, "directory classpath entry does not exist: " + name);
+ continue;
+ }
+ entries.add(new DirEntry(f));
+ }
+ }
+ }
+
+ public ClassFile find(TypeX type) {
+ String name = type.getName();
+ for (Iterator i = entries.iterator(); i.hasNext(); ) {
+ Entry entry = (Entry)i.next();
+ ClassFile ret = entry.find(name);
+ if (ret != null) return ret;
+ }
+ return null;
+ }
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ boolean start = true;
+ for (Iterator i = entries.iterator(); i.hasNext(); ) {
+ if (start) { start = false; }
+ else {buf.append(File.pathSeparator); }
+ buf.append(i.next());
+ }
+ return buf.toString();
+ }
+
+ /**
+ * This method is extremely expensive and should only be called rarely
+ */
+ public List getAllClassFiles() {
+ List ret = new ArrayList();
+ for (Iterator i = entries.iterator(); i.hasNext(); ) {
+ Entry entry = (Entry)i.next();
+ ret.addAll(entry.getAllClassFiles());
+ }
+ return ret;
+ }
+
+
+
+ public abstract static class ClassFile {
+ public abstract InputStream getInputStream() throws IOException;
+ public abstract String getPath();
+ }
+
+
+ public abstract static class Entry {
+ public abstract ClassFile find(String name);
+ public abstract List getAllClassFiles();
+ }
+
+
+ private static class FileClassFile extends ClassFile {
+ private File file;
+ public FileClassFile(File file) {
+ this.file = file;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return new FileInputStream(file);
+ }
+
+ public String getPath() { return file.getPath(); }
+ }
+
+ public class DirEntry extends Entry {
+ private String dirPath;
+
+ public DirEntry(File dir) { this.dirPath = dir.getPath(); }
+ public DirEntry(String dirPath) { this.dirPath = dirPath; }
+
+ public ClassFile find(String name) {
+ File f = new File(dirPath + File.separator + name.replace('.', File.separatorChar) + ".class");
+ if (f.isFile()) return new FileClassFile(f);
+ else return null;
+ }
+
+ public List getAllClassFiles() {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public String toString() { return dirPath; }
+ }
+
+
+ private static class ZipEntryClassFile extends ClassFile {
+ private ZipEntry entry;
+ private ZipFile zipFile;
+ public ZipEntryClassFile(ZipFile zipFile, ZipEntry entry) {
+ this.zipFile = zipFile;
+ this.entry = entry;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return zipFile.getInputStream(entry);
+ }
+
+ public String getPath() { return entry.getName(); }
+
+ }
+
+
+ public class ZipFileEntry extends Entry {
+ private ZipFile zipFile;
+
+ public ZipFileEntry(File file) throws IOException {
+ this(new ZipFile(file));
+ }
+
+ public ZipFileEntry(ZipFile zipFile) {
+ this.zipFile = zipFile;
+ }
+
+ public ClassFile find(String name) {
+ String key = name.replace('.', '/') + ".class";
+ ZipEntry entry = zipFile.getEntry(key);
+ if (entry != null) return new ZipEntryClassFile(zipFile, entry);
+ else return null;
+ }
+
+ public List getAllClassFiles() {
+ List ret = new ArrayList();
+ for (Enumeration e = zipFile.entries(); e.hasMoreElements(); ) {
+ ZipEntry entry = (ZipEntry)e.nextElement();
+ String name = entry.getName();
+ if (hasClassExtension(name)) ret.add(new ZipEntryClassFile(zipFile, entry));
+ }
+ return ret;
+ }
+
+
+ public String toString() { return zipFile.getName(); }
+ }
+
+
+ private static boolean hasClassExtension(String name) {
+ return name.toLowerCase().endsWith((".class"));
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/ExceptionRange.java b/weaver/src/org/aspectj/weaver/bcel/ExceptionRange.java
new file mode 100644
index 000000000..2e6520361
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/ExceptionRange.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.TypeX;
+
+/** exceptionRanges are set initially to be low priority. The various setPriority methods
+ * should be used accordingly. The priority is used when we pack the exception table into
+ * a method... the exception table should be sorted from high to low priority. Exceptions we generate
+ * for advice is either high priority (higher than anything coming from the original method...
+ * most kinds of non-execution advice) or low priority (lower than anything coming from the
+ * original method, for execution advice).
+ *
+ * <p> ??? This does not account for handler, or any other
+ * "statement-level" advice. When such statement level advice happens, we may want to go to a float level,
+ * so we can set the priority of advice to be lower than anything it encloses, and higher than
+ * anything enclosing it.
+ */
+
+/* we're actually using the fact that we're an instruction targeter, for the
+ * handler */
+public final class ExceptionRange extends Range {
+
+ private InstructionHandle handler;
+ private final TypeX exceptionType;
+ private final int priority;
+
+ // ---- initialization
+
+ /**
+ * After this constructor is called, this range is not well situated unless
+ * {@link #associateWithTargets} is called
+ */
+ public ExceptionRange(InstructionList body, TypeX exceptionType, int priority) {
+ super(body);
+ this.exceptionType = exceptionType;
+ this.priority = priority;
+ }
+ public ExceptionRange(InstructionList body, TypeX exceptionType, boolean highPriority) {
+ this(body, exceptionType, highPriority ? Integer.MAX_VALUE : -1);
+ }
+ public void associateWithTargets(
+ InstructionHandle start,
+ InstructionHandle end,
+ InstructionHandle handler)
+ {
+ // assert body.contains(start) && body.contains(end) && body.contains(handler)
+ this.start = start;
+ this.end = end;
+ this.handler = handler;
+ start.addTargeter(this);
+ end.addTargeter(this);
+ handler.addTargeter(this);
+ }
+
+ // ----
+
+ public InstructionHandle getHandler() {
+ return handler;
+ }
+ public TypeX getCatchType() {
+ return exceptionType;
+ }
+ public int getPriority() {
+ return priority;
+ }
+
+ // ---- from object
+
+ public String toString() {
+ String str;
+ if (exceptionType == null) {
+ str = "finally";
+ } else {
+ str = "catch " + exceptionType;
+ }
+// if (priority >= 0 && priority < Integer.MAX_VALUE) {
+// str += " (priority " + priority + ")";
+// }
+ return str;
+ }
+ public boolean equals(Object other) {
+ if (!(other instanceof ExceptionRange)) return false;
+ ExceptionRange o = (ExceptionRange) other;
+ return o.getStart() == getStart()
+ && o.getEnd() == getEnd()
+ && o.handler == handler
+ && ((o.exceptionType == null)
+ ? (exceptionType == null) :
+ o.exceptionType.equals(exceptionType))
+ && o.priority == priority;
+ }
+ private volatile int hashCode = 0;
+ public int hashCode() {
+ if (hashCode == 0) {
+ int ret = 17;
+ ret = 37*ret + getStart().hashCode();
+ ret = 37*ret + getEnd().hashCode();
+ ret = 37*ret + handler.hashCode();
+ ret = 37*ret + ((exceptionType == null) ? 0 : exceptionType.hashCode());
+ ret = 37*ret + priority;
+ hashCode = ret;
+ }
+ return hashCode;
+ }
+
+ public void updateTarget(
+ InstructionHandle oldIh,
+ InstructionHandle newIh,
+ InstructionList newBody)
+ {
+ super.updateTarget(oldIh, newIh, newBody);
+ // we're guaranteed that start, end, and handler are distinct instruction handles.
+ if (oldIh == handler) {
+ handler = newIh;
+ }
+ }
+ public static boolean isExceptionStart(InstructionHandle ih) {
+ if (! isRangeHandle(ih)) return false;
+ Range r = getRange(ih);
+ if (! (r instanceof ExceptionRange)) return false;
+ ExceptionRange er = (ExceptionRange) r;
+ return er.getStart() == ih;
+ }
+ public static boolean isExceptionEnd(InstructionHandle ih) {
+ if (! isRangeHandle(ih)) return false;
+ Range r = getRange(ih);
+ if (! (r instanceof ExceptionRange)) return false;
+ ExceptionRange er = (ExceptionRange) r;
+ return er.getEnd() == ih;
+ }
+
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java
new file mode 100644
index 000000000..0a1861b47
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java
@@ -0,0 +1,471 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.*;
+import org.apache.bcel.generic.*;
+import org.apache.bcel.util.ClassPath;
+import org.aspectj.weaver.*;
+import org.aspectj.util.CollectionUtil;
+
+public final class LazyClassGen {
+
+ /** Emit disassembled class and newline to out */
+ public static void disassemble(String path, String name, PrintStream out)
+ throws IOException {
+ if (null == out) {
+ return;
+ }
+ //out.println("classPath: " + classPath);
+
+ BcelWorld world = new BcelWorld(path);
+
+ LazyClassGen clazz = new LazyClassGen((BcelObjectType) world.resolve(name));
+ clazz.print(out);
+ out.println();
+ }
+
+ private BcelObjectType myType; // XXX is not set for types we create
+ private ClassGen myGen;
+ private ConstantPoolGen constantPoolGen;
+
+ private List /*LazyMethodGen*/
+ methodGens = new ArrayList();
+ private List /*LazyClassGen*/
+ classGens = new ArrayList();
+
+ private int childCounter = 0;
+
+ public int getNewGeneratedNameTag() {
+ return childCounter++;
+ }
+
+ private InstructionFactory fact;
+ // ----
+
+ public LazyClassGen(
+ String class_name,
+ String super_class_name,
+ String file_name,
+ int access_flags,
+ String[] interfaces)
+ {
+ myGen = new ClassGen(class_name, super_class_name, file_name, access_flags, interfaces);
+ constantPoolGen = myGen.getConstantPool();
+ fact = new InstructionFactory(constantPoolGen);
+ }
+
+ //Non child type, so it comes from a real type in the world.
+ public LazyClassGen(BcelObjectType myType) {
+ myGen = new ClassGen(myType.getJavaClass());
+ constantPoolGen = myGen.getConstantPool();
+ fact = new InstructionFactory(constantPoolGen);
+ this.myType = myType;
+
+ Method[] methods = myGen.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ addMethodGen(new LazyMethodGen(methods[i], this));
+ }
+ }
+
+// public void addAttribute(Attribute i) {
+// myGen.addAttribute(i);
+// }
+
+ // ----
+
+ public String getInternalClassName() {
+ return getConstantPoolGen().getConstantPool().getConstantString(
+ myGen.getClassNameIndex(),
+ Constants.CONSTANT_Class);
+
+ }
+
+ public File getPackagePath(File root) {
+ String str = getInternalClassName();
+ int index = str.lastIndexOf('/');
+ if (index == -1)
+ return root;
+ return new File(root, str.substring(0, index));
+ }
+
+ public String getClassId() {
+ String str = getInternalClassName();
+ int index = str.lastIndexOf('/');
+ if (index == -1)
+ return str;
+ return str.substring(index + 1);
+ }
+
+
+ public void addMethodGen(LazyMethodGen gen) {
+ //assert gen.getClassName() == super.getClassName();
+ methodGens.add(gen);
+ }
+
+ public List getMethodGens() {
+ return Collections.unmodifiableList(methodGens);
+
+ }
+
+ private void writeBack() {
+ addAjcInitializers();
+
+
+ int len = methodGens.size();
+ myGen.setMethods(new Method[0]);
+ for (int i = 0; i < len; i++) {
+ LazyMethodGen gen = (LazyMethodGen) methodGens.get(i);
+ // we skip empty clinits
+ if (isEmptyClinit(gen)) continue;
+ myGen.addMethod(gen.getMethod());
+ }
+ }
+
+ public JavaClass getJavaClass() {
+ writeBack();
+ return myGen.getJavaClass();
+ }
+
+ public void addGeneratedInner(LazyClassGen newClass) {
+ classGens.add(newClass);
+ }
+
+ public void addInterface(TypeX typeX) {
+ myGen.addInterface(typeX.getName());
+ }
+
+ // non-recursive, may be a bug, ha ha.
+ private List getClassGens() {
+ List ret = new ArrayList();
+ ret.add(this);
+ ret.addAll(classGens);
+
+ return ret;
+ }
+
+
+ public List getChildClasses() {
+ if (classGens.isEmpty()) return Collections.EMPTY_LIST;
+ List ret = new ArrayList();
+ for (Iterator i = classGens.iterator(); i.hasNext();) {
+ LazyClassGen clazz = (LazyClassGen) i.next();
+ byte[] bytes = clazz.getJavaClass().getBytes();
+ String name = clazz.getName();
+ int index = name.lastIndexOf('$');
+ // XXX this could be bad, check use of dollar signs.
+ name = name.substring(index+1);
+ ret.add(new UnwovenClassFile.ChildClass(name, bytes));
+ }
+ return ret;
+ }
+
+ public String toString() {
+ return toShortString();
+ }
+
+ public String toShortString() {
+ String s =
+ org.apache.bcel.classfile.Utility.accessToString(myGen.getAccessFlags(), true);
+ if (s != "")
+ s += " ";
+ s += org.apache.bcel.classfile.Utility.classOrInterface(myGen.getAccessFlags());
+ s += " ";
+ s += myGen.getClassName();
+ return s;
+ }
+
+ public String toLongString() {
+ ByteArrayOutputStream s = new ByteArrayOutputStream();
+ print(new PrintStream(s));
+ return new String(s.toByteArray());
+ }
+
+ public void print() { print(System.out); }
+
+ public void print(PrintStream out) {
+ List classGens = getClassGens();
+ for (Iterator iter = classGens.iterator(); iter.hasNext();) {
+ LazyClassGen element = (LazyClassGen) iter.next();
+ element.printOne(out);
+ if (iter.hasNext()) out.println();
+ }
+ }
+
+ private void printOne(PrintStream out) {
+ out.print(toShortString());
+ out.print(" extends ");
+ out.print(
+ org.apache.bcel.classfile.Utility.compactClassName(
+ myGen.getSuperclassName(),
+ false));
+
+ int size = myGen.getInterfaces().length;
+
+ if (size > 0) {
+ out.print(" implements ");
+ for (int i = 0; i < size; i++) {
+ out.print(myGen.getInterfaceNames()[i]);
+ if (i < size - 1)
+ out.print(", ");
+ }
+ }
+ out.print(":");
+ out.println();
+ // XXX make sure to pass types correctly around, so this doesn't happen.
+ if (myType != null) {
+ myType.printWackyStuff(out);
+ }
+ Field[] fields = myGen.getFields();
+ for (int i = 0, len = fields.length; i < len; i++) {
+ out.print(" ");
+ out.println(fields[i]);
+ }
+ List methodGens = getMethodGens();
+ for (Iterator iter = methodGens.iterator(); iter.hasNext();) {
+ LazyMethodGen gen = (LazyMethodGen) iter.next();
+ // we skip empty clinits
+ if (isEmptyClinit(gen)) continue;
+ gen.print(out);
+ if (iter.hasNext()) out.println();
+ }
+// out.println(" ATTRIBS: " + Arrays.asList(myGen.getAttributes()));
+
+ out.println("end " + toShortString());
+ }
+
+ private boolean isEmptyClinit(LazyMethodGen gen) {
+ if (!gen.getName().equals("<clinit>")) return false;
+ //System.err.println("checking clinig: " + gen);
+ InstructionHandle start = gen.getBody().getStart();
+ while (start != null) {
+ if (Range.isRangeHandle(start) || (start.getInstruction() instanceof RETURN)) {
+ start = start.getNext();
+ } else {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public ConstantPoolGen getConstantPoolGen() {
+ return constantPoolGen;
+ }
+
+ public String getName() {
+ return myGen.getClassName();
+ }
+
+ public WeaverStateKind getWeaverState() {
+ WeaverStateKind kind = myType.getWeaverState();
+ if (kind == null) return WeaverStateKind.Untouched;
+ return kind;
+ }
+
+ public void setWeaverState(WeaverStateKind s) {
+ Attribute[] attributes = myGen.getAttributes();
+ if (attributes != null) {
+ for (int i = attributes.length - 1; i >=0; i--) {
+ Attribute a = attributes[i];
+ if (a instanceof Unknown) {
+ Unknown u = (Unknown) a;
+ if (u.getName().equals(AjAttribute.WeaverState.AttributeName)) {
+ myGen.removeAttribute(u);
+ }
+ }
+ }
+ }
+ myGen.addAttribute(BcelAttributes.bcelAttribute(
+ new AjAttribute.WeaverState(s),
+ getConstantPoolGen()));
+ }
+
+ public InstructionFactory getFactory() {
+ return fact;
+ }
+
+ public LazyMethodGen getStaticInitializer() {
+ for (Iterator i = methodGens.iterator(); i.hasNext();) {
+ LazyMethodGen gen = (LazyMethodGen) i.next();
+ if (gen.getName().equals("<clinit>")) return gen;
+ }
+ LazyMethodGen clinit = new LazyMethodGen(
+ Modifier.STATIC,
+ Type.VOID,
+ "<clinit>",
+ new Type[0],
+ CollectionUtil.NO_STRINGS,
+ this);
+ clinit.getBody().insert(getFactory().RETURN);
+ methodGens.add(clinit);
+ return clinit;
+ }
+
+
+ // reflective thisJoinPoint support
+ Map/*BcelShadow, Field*/ tjpFields = new HashMap();
+ public static final ObjectType tjpType =
+ new ObjectType("org.aspectj.lang.JoinPoint");
+ public static final ObjectType staticTjpType =
+ new ObjectType("org.aspectj.lang.JoinPoint$StaticPart");
+ private static final ObjectType sigType =
+ new ObjectType("org.aspectj.lang.Signature");
+ private static final ObjectType slType =
+ new ObjectType("org.aspectj.lang.reflect.SourceLocation");
+ private static final ObjectType factoryType =
+ new ObjectType("org.aspectj.runtime.reflect.Factory");
+ private static final ObjectType classType =
+ new ObjectType("java.lang.Class");
+
+ public Field getTjpField(BcelShadow shadow) {
+ Field ret = (Field)tjpFields.get(shadow);
+ if (ret != null) return ret;
+
+ ret = new FieldGen(Modifier.STATIC | Modifier.PUBLIC | Modifier.FINAL,
+ staticTjpType,
+ "ajc$tjp_" + tjpFields.size(),
+ getConstantPoolGen()).getField();
+ addField(ret);
+ tjpFields.put(shadow, ret);
+ return ret;
+ }
+
+ private void addAjcInitializers() {
+ if (tjpFields.size() == 0) return;
+
+ InstructionList il = initializeAllTjps();
+ getStaticInitializer().getBody().insert(il);
+ }
+
+
+ private InstructionList initializeAllTjps() {
+ InstructionList list = new InstructionList();
+ InstructionFactory fact = getFactory();
+
+ // make a new factory
+ list.append(fact.createNew(factoryType));
+ list.append(fact.createDup(1));
+
+ list.append(new PUSH(getConstantPoolGen(), getFileName()));
+
+ // load the current Class object
+ //XXX check that this works correctly for inners/anonymous
+ list.append(new PUSH(getConstantPoolGen(), getClassName()));
+ //XXX do we need to worry about the fact the theorectically this could throw
+ //a ClassNotFoundException
+ list.append(fact.createInvoke("java.lang.Class", "forName", classType,
+ new Type[] {Type.STRING}, Constants.INVOKESTATIC));
+
+ list.append(fact.createInvoke(factoryType.getClassName(), "<init>",
+ Type.VOID, new Type[] {Type.STRING, classType},
+ Constants.INVOKESPECIAL));
+
+ list.append(fact.createStore(factoryType, 0));
+
+ List entries = new ArrayList(tjpFields.entrySet());
+ Collections.sort(entries, new Comparator() {
+ public int compare(Object a, Object b) {
+ Map.Entry ae = (Map.Entry) a;
+ Map.Entry be = (Map.Entry) b;
+ return ((Field) ae.getValue())
+ .getName()
+ .compareTo(((Field)be.getValue()).getName());
+ }
+ });
+
+ for (Iterator i = entries.iterator(); i.hasNext(); ) {
+ Map.Entry entry = (Map.Entry)i.next();
+ initializeTjp(fact, list, (Field)entry.getValue(), (BcelShadow)entry.getKey());
+ }
+
+ return list;
+ }
+
+
+ private void initializeTjp(InstructionFactory fact, InstructionList list,
+ Field field, BcelShadow shadow)
+ {
+ Member sig = shadow.getSignature();
+ //ResolvedMember mem = shadow.getSignature().resolve(shadow.getWorld());
+
+ // load the factory
+ list.append(fact.createLoad(factoryType, 0));
+
+ // load the kind
+ list.append(new PUSH(getConstantPoolGen(), shadow.getKind().getName()));
+
+ // create the signature
+ list.append(fact.createLoad(factoryType, 0));
+ list.append(new PUSH(getConstantPoolGen(), sig.getSignatureString(shadow.getWorld())));
+ list.append(fact.createInvoke(factoryType.getClassName(),
+ sig.getSignatureMakerName(),
+ new ObjectType(sig.getSignatureType()),
+ new Type[] { Type.STRING },
+ Constants.INVOKEVIRTUAL));
+
+ //XXX should load source location from shadow
+ list.append(Utility.createConstant(fact, shadow.getSourceLine()));
+
+
+ list.append(fact.createInvoke(factoryType.getClassName(),
+ "makeSJP", staticTjpType,
+ new Type[] { Type.STRING, sigType, Type.INT},
+ Constants.INVOKEVIRTUAL));
+
+ // put it in the field
+ list.append(fact.createFieldAccess(getClassName(), field.getName(),
+ staticTjpType, Constants.PUTSTATIC));
+ }
+
+
+ public BcelObjectType getType() {
+ return myType;
+ }
+
+ public String getFileName() {
+ return myGen.getFileName();
+ }
+
+ public void addField(Field field) {
+ myGen.addField(field);
+ }
+
+ public String getClassName() {
+ return myGen.getClassName();
+ }
+
+ public boolean isInterface() {
+ return myGen.isInterface();
+ }
+
+ public LazyMethodGen getLazyMethodGen(Member m) {
+ return getLazyMethodGen(m.getName(), m.getSignature());
+ }
+
+ public LazyMethodGen getLazyMethodGen(String name, String signature) {
+ for (Iterator i = methodGens.iterator(); i.hasNext();) {
+ LazyMethodGen gen = (LazyMethodGen) i.next();
+ if (gen.getName().equals(name) && gen.getSignature().equals(signature))
+ return gen;
+ }
+ throw new BCException("Class " + this.getName() + " does not have a method "
+ + name + " with signature " + signature);
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
new file mode 100644
index 000000000..63d105e19
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
@@ -0,0 +1,1060 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.*;
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.*;
+
+
+/**
+ * A LazyMethodGen should be treated as a MethodGen. It's our way of abstracting over the
+ * low-level Method objects. It converts through {@link MethodGen} to create
+ * and to serialize, but that's it.
+ *
+ * <p> At any rate, there are two ways to create LazyMethodGens.
+ * One is from a method, which
+ * does work through MethodGen to do the correct thing.
+ * The other is the creation of a completely empty
+ * LazyMethodGen, and it is used when we're constructing code from scratch.
+ *
+ * <p> We stay away from targeters for rangey things like Shadows and Exceptions.
+ */
+
+public final class LazyMethodGen {
+ private final int accessFlags;
+ private final Type returnType;
+ private final String name;
+ private final Type[] argumentTypes;
+ //private final String[] argumentNames;
+ private final String[] declaredExceptions;
+ private final InstructionList body; // leaving null for abstracts
+ private final Attribute[] attributes;
+ private final LazyClassGen enclosingClass;
+ private final BcelMethod memberView;
+
+ private int maxLocals;
+
+ /**
+ * only used by {@link BcelClassWeaver}
+ */
+ List /*ShadowMungers*/ matchedShadows;
+
+ // Used for interface introduction
+ // this is the type of the interface the method is technically on
+ public ResolvedTypeX definingType = null;
+
+ public LazyMethodGen(
+ int accessFlags,
+ Type returnType,
+ String name,
+ Type[] paramTypes,
+ String[] declaredExceptions,
+ LazyClassGen enclosingClass)
+ {
+ this.memberView = null; // ??? should be okay, since constructed ones aren't woven into
+ this.accessFlags = accessFlags;
+ this.returnType = returnType;
+ this.name = name;
+ this.argumentTypes = paramTypes;
+ //this.argumentNames = Utility.makeArgNames(paramTypes.length);
+ this.declaredExceptions = declaredExceptions;
+ if (!Modifier.isAbstract(accessFlags)) {
+ body = new InstructionList();
+ setMaxLocals(calculateMaxLocals());
+ } else {
+ body = null;
+ }
+ this.attributes = new Attribute[0];
+ this.enclosingClass = enclosingClass;
+ assertGoodBody();
+ }
+
+ private int calculateMaxLocals() {
+ int ret = 0;
+ if (!Modifier.isStatic(accessFlags)) ret++;
+ for (int i = 0, len = argumentTypes.length; i < len; i++) {
+ ret += argumentTypes[i].getSize();
+ }
+ return ret;
+ }
+
+ // build from an existing method
+ public LazyMethodGen(Method m, LazyClassGen enclosingClass) {
+ this.enclosingClass = enclosingClass;
+ if (!m.isAbstract() && m.getCode() == null) {
+ throw new RuntimeException("bad non-abstract method with no code: " + m + " on " + enclosingClass);
+ }
+ MethodGen gen = new MethodGen(m, enclosingClass.getName(), enclosingClass.getConstantPoolGen());
+ this.memberView = new BcelMethod(enclosingClass.getType(), m);
+ this.accessFlags = gen.getAccessFlags();
+ this.returnType = gen.getReturnType();
+ this.name = gen.getName();
+ this.argumentTypes = gen.getArgumentTypes();
+ //this.argumentNames = gen.getArgumentNames();
+ this.declaredExceptions = gen.getExceptions();
+ this.attributes = gen.getAttributes();
+ this.maxLocals = gen.getMaxLocals();
+ if (gen.isAbstract() || gen.isNative()) {
+ body = null;
+ } else {
+ body = gen.getInstructionList();
+ unpackHandlers(gen);
+ unpackLineNumbers(gen);
+ unpackLocals(gen);
+ }
+ assertGoodBody();
+ }
+
+ // XXX we're relying on the javac promise I've just made up that we won't have an early exception
+ // in the list mask a later exception: That is, for two exceptions E and F,
+ // if E preceeds F, then either E \cup F = {}, or E \nonstrictsubset F. So when we add F,
+ // we add it on the _OUTSIDE_ of any handlers that share starts or ends with it.
+
+ // with that in mind, we merrily go adding ranges for exceptions.
+
+ private void unpackHandlers(MethodGen gen) {
+ CodeExceptionGen[] exns = gen.getExceptionHandlers();
+ if (exns != null) {
+ int len = exns.length;
+ int priority = len - 1;
+ for (int i = 0; i < len; i++, priority--) {
+ CodeExceptionGen exn = exns[i];
+
+ InstructionHandle start =
+ Range.genStart(
+ body,
+ getOutermostExceptionStart(exn.getStartPC()));
+ InstructionHandle end = Range.genEnd(body, getOutermostExceptionEnd(exn.getEndPC()));
+ // this doesn't necessarily handle overlapping correctly!!!
+ ExceptionRange er =
+ new ExceptionRange(
+ body,
+ exn.getCatchType() == null
+ ? null
+ : BcelWorld.fromBcel(exn.getCatchType()),
+ priority);
+ er.associateWithTargets(start, end, exn.getHandlerPC());
+ exn.setStartPC(null); // also removes from target
+ exn.setEndPC(null); // also removes from target
+ exn.setHandlerPC(null); // also removes from target
+ }
+ gen.removeExceptionHandlers();
+ }
+ }
+
+ private InstructionHandle getOutermostExceptionStart(InstructionHandle ih) {
+ while (true) {
+ if (ExceptionRange.isExceptionStart(ih.getPrev())) {
+ ih = ih.getPrev();
+ } else {
+ return ih;
+ }
+ }
+ }
+ private InstructionHandle getOutermostExceptionEnd(InstructionHandle ih) {
+ while (true) {
+ if (ExceptionRange.isExceptionEnd(ih.getNext())) {
+ ih = ih.getNext();
+ } else {
+ return ih;
+ }
+ }
+ }
+
+
+ private void unpackLineNumbers(MethodGen gen) {
+ LineNumberTag lr = null;
+ for (InstructionHandle ih = body.getStart(); ih != null; ih = ih.getNext()) {
+ InstructionTargeter[] targeters = ih.getTargeters();
+ if (targeters != null) {
+ for (int i = targeters.length - 1; i >= 0; i--) {
+ InstructionTargeter targeter = targeters[i];
+ if (targeter instanceof LineNumberGen) {
+ LineNumberGen lng = (LineNumberGen) targeter;
+ lng.updateTarget(ih, null);
+ lr = new LineNumberTag(lng.getSourceLine());
+ }
+ }
+ }
+ if (lr != null) {
+ ih.addTargeter(lr);
+ }
+ }
+ gen.removeLineNumbers();
+ }
+
+ private void unpackLocals(MethodGen gen) {
+ Set locals = new HashSet();
+ for (InstructionHandle ih = body.getStart(); ih != null; ih = ih.getNext()) {
+ InstructionTargeter[] targeters = ih.getTargeters();
+ List ends = new ArrayList(0);
+ if (targeters != null) {
+ for (int i = targeters.length - 1; i >= 0; i--) {
+ InstructionTargeter targeter = targeters[i];
+ if (targeter instanceof LocalVariableGen) {
+ LocalVariableGen lng = (LocalVariableGen) targeter;
+ LocalVariableTag lr = new LocalVariableTag(BcelWorld.fromBcel(lng.getType()), lng.getName(), lng.getIndex());
+ if (lng.getStart() == ih) {
+ lng.setStart(null);
+ locals.add(lr);
+ } else {
+ lng.setEnd(null);
+ ends.add(lr);
+ }
+ }
+ }
+ }
+ for (Iterator i = locals.iterator(); i.hasNext(); ) {
+ ih.addTargeter((LocalVariableTag) i.next());
+ }
+ locals.removeAll(ends);
+ }
+ gen.removeLocalVariables();
+ }
+
+ // ===============
+
+ public int allocateLocal(Type type) {
+ return allocateLocal(type.getSize());
+ }
+
+ public int allocateLocal(int slots) {
+ int max = getMaxLocals();
+ setMaxLocals(max + slots);
+ return max;
+ }
+
+ public Method getMethod() {
+ MethodGen gen = pack();
+ return gen.getMethod();
+ }
+
+ // =============================
+
+ public String toString() {
+ return toLongString();
+ }
+
+ public String toShortString() {
+ org.apache.bcel.classfile.Utility util = null; // EVIL!
+ String access = util.accessToString(getAccessFlags());
+
+ StringBuffer buf = new StringBuffer();
+
+ if (!access.equals("")) {
+ buf.append(access);
+ buf.append(" ");
+ }
+ buf.append(util.signatureToString(getReturnType().getSignature(), true));
+ buf.append(" ");
+ buf.append(getName());
+ buf.append("(");
+ {
+ int len = argumentTypes.length;
+ if (len > 0) {
+ buf.append(util.signatureToString(argumentTypes[0].getSignature(), true));
+ for (int i = 1; i < argumentTypes.length; i++) {
+ buf.append(", ");
+ buf.append(util.signatureToString(argumentTypes[i].getSignature(), true));
+ }
+ }
+ }
+ buf.append(")");
+
+ {
+ int len = declaredExceptions != null ? declaredExceptions.length : 0;
+ if (len > 0) {
+ buf.append(" throws ");
+ buf.append(declaredExceptions[0]);
+ for (int i = 1; i < declaredExceptions.length; i++) {
+ buf.append(", ");
+ buf.append(declaredExceptions[i]);
+ }
+ }
+ }
+ return buf.toString();
+ }
+
+ public String toLongString() {
+ ByteArrayOutputStream s = new ByteArrayOutputStream();
+ print(new PrintStream(s));
+ return new String(s.toByteArray());
+ }
+
+ public void print() {
+ print(System.out);
+ }
+
+ public void print(PrintStream out) {
+ out.print(" " + toShortString());
+ printAspectAttributes(out);
+
+ InstructionList body = getBody();
+ if (body == null) {
+ out.println(";");
+ return;
+ }
+ out.println(":");
+ new BodyPrinter(out).run();
+ out.println(" end " + toShortString());
+ }
+
+
+ private void printAspectAttributes(PrintStream out) {
+ ISourceContext context = null;
+ if (enclosingClass != null && enclosingClass.getType() != null) {
+ context = enclosingClass.getType().getSourceContext();
+ }
+ List as = BcelAttributes.readAjAttributes(attributes, context);
+ if (! as.isEmpty()) {
+ out.println(" " + as.get(0)); // XXX assuming exactly one attribute, munger...
+ }
+ }
+
+
+ private class BodyPrinter {
+ Map prefixMap = new HashMap();
+ Map suffixMap = new HashMap();
+ Map labelMap = new HashMap();
+
+ InstructionList body;
+ PrintStream out;
+ ConstantPool pool;
+ List ranges;
+
+ BodyPrinter(PrintStream out) {
+ this.pool = enclosingClass.getConstantPoolGen().getConstantPool();
+ this.body = getBody();
+ this.out = out;
+ }
+
+ void run() {
+ assignLabels();
+ print();
+ }
+
+ // label assignment
+ void assignLabels() {
+ LinkedList exnTable = new LinkedList();
+ String pendingLabel = null;
+// boolean hasPendingTargeters = false;
+ int lcounter = 0;
+ for (InstructionHandle ih = body.getStart(); ih != null; ih = ih.getNext()) {
+ InstructionTargeter[] targeters = ih.getTargeters();
+ if (targeters != null) {
+ for (int i = targeters.length - 1; i >= 0; i--) {
+ InstructionTargeter t = targeters[i];
+ if (t instanceof ExceptionRange) {
+ // assert isRangeHandle(h);
+ ExceptionRange r = (ExceptionRange) t;
+ if (r.getStart() == ih) {
+ insertHandler(r, exnTable);
+ }
+ } else if (t instanceof BranchInstruction) {
+ if (pendingLabel == null) {
+ pendingLabel = "L" + lcounter++;
+ }
+ } else {
+ // assert isRangeHandle(h)
+ }
+ }
+ }
+ if (pendingLabel != null) {
+ labelMap.put(ih, pendingLabel);
+ if (! Range.isRangeHandle(ih)) {
+ pendingLabel = null;
+ }
+ }
+ }
+ int ecounter = 0;
+ for (Iterator i = exnTable.iterator(); i.hasNext();) {
+ ExceptionRange er = (ExceptionRange) i.next();
+ String exceptionLabel = "E" + ecounter++;
+ labelMap.put(Range.getRealStart(er.getHandler()), exceptionLabel);
+ labelMap.put(er.getHandler(), exceptionLabel);
+ }
+ }
+
+ // printing
+
+ void print() {
+ int depth = 0;
+ int currLine = -1;
+ bodyPrint:
+ for (InstructionHandle ih = body.getStart(); ih != null; ih = ih.getNext()) {
+ if (Range.isRangeHandle(ih)) {
+ Range r = Range.getRange(ih);
+ // don't print empty ranges, that is, ranges who contain no actual instructions
+ for (InstructionHandle xx = r.getStart(); Range.isRangeHandle(xx); xx = xx.getNext()) {
+ if (xx == r.getEnd()) continue bodyPrint;
+ }
+ // doesn't handle nested: if (r.getStart().getNext() == r.getEnd()) continue;
+ if (r.getStart() == ih) {
+ printRangeString(r, depth++);
+ } else {
+ if (r.getEnd() != ih) throw new RuntimeException("bad");
+ printRangeString(r, --depth);
+ }
+ } else {
+ printInstruction(ih, depth);
+ int line = getLineNumber(ih, currLine);
+ if (line != currLine) {
+ currLine = line;
+ out.println(" (line " + line + ")");
+ } else {
+ out.println();
+ }
+ }
+ }
+ }
+
+ void printRangeString(Range r, int depth) {
+ printDepth(depth);
+ out.println(getRangeString(r, labelMap));
+ }
+
+
+ String getRangeString(Range r, Map labelMap) {
+ if (r instanceof ExceptionRange) {
+ ExceptionRange er = (ExceptionRange) r;
+ return er.toString() + " -> " + labelMap.get(er.getHandler());
+ } else {
+ return r.toString();
+ }
+ }
+
+ void printDepth(int depth) {
+ pad(BODY_INDENT);
+ while (depth > 0) {
+ out.print("| ");
+ depth--;
+ }
+ }
+
+
+ void printLabel(String s, int depth) {
+ int space = Math.max(CODE_INDENT - depth * 2, 0);
+ if (s == null) {
+ pad(space);
+ } else {
+ space = Math.max(space - (s.length() + 2), 0);
+ pad(space);
+ out.print(s);
+ out.print(": ");
+ }
+ }
+
+ void printInstruction(InstructionHandle h, int depth) {
+ printDepth(depth);
+ printLabel((String) labelMap.get(h), depth);
+
+ Instruction inst = h.getInstruction();
+ if (inst instanceof CPInstruction) {
+ CPInstruction cpinst = (CPInstruction) inst;
+ out.print(Constants.OPCODE_NAMES[cpinst.getOpcode()].toUpperCase());
+ out.print(" ");
+ out.print(pool.constantToString(pool.getConstant(cpinst.getIndex())));
+ } else if (inst instanceof Select) {
+ Select sinst = (Select) inst;
+ out.println(Constants.OPCODE_NAMES[sinst.getOpcode()].toUpperCase());
+ int[] matches = sinst.getMatchs();
+ InstructionHandle[] targets = sinst.getTargets();
+ InstructionHandle defaultTarget = sinst.getTarget();
+ for (int i = 0, len = matches.length; i < len; i++) {
+ printDepth(depth);
+ printLabel(null, depth);
+ out.print(" ");
+ out.print(matches[i]);
+ out.print(": \t");
+ out.println(labelMap.get(targets[i]));
+ }
+ printDepth(depth);
+ printLabel(null, depth);
+ out.print(" ");
+ out.print("default: \t");
+ out.print(labelMap.get(defaultTarget));
+ } else if (inst instanceof BranchInstruction) {
+ BranchInstruction brinst = (BranchInstruction) inst;
+ out.print(Constants.OPCODE_NAMES[brinst.getOpcode()].toUpperCase());
+ out.print(" ");
+ out.print(labelMap.get(brinst.getTarget()));
+ } else if (inst instanceof LocalVariableInstruction) {
+ LocalVariableInstruction lvinst = (LocalVariableInstruction) inst;
+ out.print(inst.toString(false).toUpperCase());
+ int index = lvinst.getIndex();
+ LocalVariableTag tag = getLocalVariableTag(h, index);
+ if (tag != null) {
+ out.print(" // ");
+ out.print(tag.getType());
+ out.print(" ");
+ out.print(tag.getName());
+ }
+ } else {
+ out.print(inst.toString(false).toUpperCase());
+ }
+ }
+
+
+
+
+ static final int BODY_INDENT = 4;
+ static final int CODE_INDENT = 16;
+
+ void pad(int size) {
+ for (int i = 0; i < size; i++) {
+ out.print(" ");
+ }
+ }
+ }
+
+
+ static LocalVariableTag getLocalVariableTag(
+ InstructionHandle ih,
+ int index)
+ {
+ InstructionTargeter[] targeters = ih.getTargeters();
+ if (targeters == null) return null;
+ for (int i = targeters.length - 1; i >= 0; i--) {
+ InstructionTargeter t = targeters[i];
+ if (t instanceof LocalVariableTag) {
+ LocalVariableTag lvt = (LocalVariableTag) t;
+ if (lvt.getSlot() == index) return lvt;
+ }
+ }
+ return null;
+ }
+
+ static int getLineNumber(
+ InstructionHandle ih,
+ int prevLine)
+ {
+ InstructionTargeter[] targeters = ih.getTargeters();
+ if (targeters == null) return prevLine;
+ for (int i = targeters.length - 1; i >= 0; i--) {
+ InstructionTargeter t = targeters[i];
+ if (t instanceof LineNumberTag) {
+ return ((LineNumberTag)t).getLineNumber();
+ }
+ }
+ return prevLine;
+ }
+
+ public boolean isStatic() {
+ return Modifier.isStatic(getAccessFlags());
+ }
+
+ public void addExceptionHandler(
+ InstructionHandle start,
+ InstructionHandle end,
+ InstructionHandle handlerStart,
+ ObjectType catchType,
+ boolean highPriority) {
+
+ InstructionHandle start1 = Range.genStart(body, start);
+ InstructionHandle end1 = Range.genEnd(body, end);
+
+ ExceptionRange er =
+ new ExceptionRange(body, BcelWorld.fromBcel(catchType), highPriority);
+ er.associateWithTargets(start1, end1, handlerStart);
+ }
+
+ public int getAccessFlags() {
+ return accessFlags;
+ }
+
+ public Type[] getArgumentTypes() {
+ return argumentTypes;
+ }
+
+// public String[] getArgumentNames() {
+// return argumentNames;
+// }
+
+ public LazyClassGen getEnclosingClass() {
+ return enclosingClass;
+ }
+
+ public int getMaxLocals() {
+ return maxLocals;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Type getReturnType() {
+ return returnType;
+ }
+
+ public void setMaxLocals(int maxLocals) {
+ this.maxLocals = maxLocals;
+ }
+
+ public InstructionList getBody() {
+ return body;
+ }
+
+ public boolean hasBody() { return body != null; }
+
+
+ public Attribute[] getAttributes() {
+ return attributes;
+ }
+
+ public String[] getDeclaredExceptions() {
+ return declaredExceptions;
+ }
+
+ public String getClassName() {
+ return enclosingClass.getName();
+ }
+
+
+ // ---- packing!
+
+ public MethodGen pack() {
+ MethodGen gen =
+ new MethodGen(
+ getAccessFlags(),
+ getReturnType(),
+ getArgumentTypes(),
+ null, //getArgumentNames(),
+ getName(),
+ getEnclosingClass().getName(),
+ new InstructionList(),
+ getEnclosingClass().getConstantPoolGen());
+ for (int i = 0, len = declaredExceptions.length; i < len; i++) {
+ gen.addException(declaredExceptions[i]);
+ }
+ for (int i = 0, len = attributes.length; i < len; i++) {
+ gen.addAttribute(attributes[i]);
+ }
+ if (hasBody()) {
+ packBody(gen);
+ gen.setMaxLocals();
+ gen.setMaxStack();
+ }
+ return gen;
+ }
+
+ /** fill the newly created method gen with our body,
+ * inspired by InstructionList.copy()
+ */
+ public void packBody(MethodGen gen) {
+ HashMap map = new HashMap();
+ InstructionList fresh = gen.getInstructionList();
+
+ /* Make copies of all instructions, append them to the new list
+ * and associate old instruction references with the new ones, i.e.,
+ * a 1:1 mapping.
+ */
+ for (InstructionHandle ih = getBody().getStart(); ih != null; ih = ih.getNext()) {
+ if (Range.isRangeHandle(ih)) {
+ continue;
+ }
+ Instruction i = ih.getInstruction();
+ Instruction c = i.copy(); // Use clone for shallow copy
+
+ if (c instanceof BranchInstruction)
+ map.put(ih, fresh.append((BranchInstruction) c));
+ else
+ map.put(ih, fresh.append(c));
+ }
+ // at this point, no rangeHandles are in fresh. Let's use that...
+
+ /* Update branch targets and insert various attributes.
+ * Insert our exceptionHandlers
+ * into a sorted list, so they can be added in order later.
+ */
+ InstructionHandle ih = getBody().getStart();
+ InstructionHandle jh = fresh.getStart();
+
+ LinkedList exnList = new LinkedList();
+
+ Map localVariableStarts = new HashMap();
+ Map localVariableEnds = new HashMap();
+
+ int currLine = -1;
+
+ while (ih != null) {
+ if (map.get(ih) == null) {
+ // we're a range instruction
+ Range r = Range.getRange(ih);
+ if (r instanceof ExceptionRange) {
+ ExceptionRange er = (ExceptionRange) r;
+ if (er.getStart() == ih) {
+ // order is important, insert handlers in order of start
+ insertHandler(er, exnList);
+ }
+ } else {
+ // we must be a shadow range or something equally useless,
+ // so forget about doing anything
+ }
+ // just increment ih.
+ ih = ih.getNext();
+ } else {
+ // assert map.get(ih) == jh
+ Instruction i = ih.getInstruction();
+ Instruction j = jh.getInstruction();
+
+ if (i instanceof BranchInstruction) {
+ BranchInstruction bi = (BranchInstruction) i;
+ BranchInstruction bj = (BranchInstruction) j;
+ InstructionHandle itarget = bi.getTarget(); // old target
+
+// try {
+ // New target is in hash map
+ bj.setTarget(remap(itarget, map));
+// } catch (NullPointerException e) {
+// print();
+// System.out.println("Was trying to remap " + bi);
+// System.out.println("who's target was supposedly " + itarget);
+// throw e;
+// }
+
+ if (bi instanceof Select) {
+ // Either LOOKUPSWITCH or TABLESWITCH
+ InstructionHandle[] itargets = ((Select) bi).getTargets();
+ InstructionHandle[] jtargets = ((Select) bj).getTargets();
+
+ for (int k = itargets.length - 1; k >= 0; k--) {
+ // Update all targets
+ jtargets[k] = remap(itargets[k], map);
+ jtargets[k].addTargeter(bj);
+ }
+ }
+ }
+
+ // now deal with line numbers
+ // and store up info for local variables
+ InstructionTargeter[] targeters = ih.getTargeters();
+ if (targeters != null) {
+ for (int k = targeters.length - 1; k >= 0; k--) {
+ InstructionTargeter targeter = targeters[k];
+ if (targeter instanceof LineNumberTag) {
+ int line = ((LineNumberTag)targeter).getLineNumber();
+ if (line != currLine) {
+ gen.addLineNumber(jh, line);
+ currLine = line;
+ }
+ } else if (targeter instanceof LocalVariableTag) {
+ LocalVariableTag lvt = (LocalVariableTag) targeter;
+ if (i instanceof LocalVariableInstruction) {
+ int index = ((LocalVariableInstruction)i).getIndex();
+ if (lvt.getSlot() == index) {
+ if (localVariableStarts.get(lvt) == null) {
+ localVariableStarts.put(lvt, jh);
+ }
+ localVariableEnds.put(lvt, jh);
+ }
+ }
+ }
+ }
+ }
+ // now continue
+ ih = ih.getNext();
+ jh = jh.getNext();
+ }
+ }
+
+ // now add exception handlers
+ for (Iterator iter = exnList.iterator(); iter.hasNext();) {
+ ExceptionRange r = (ExceptionRange) iter.next();
+ if (r.isEmpty()) continue;
+ gen.addExceptionHandler(
+ remap(r.getRealStart(), map),
+ remap(r.getRealEnd(), map),
+ remap(r.getHandler(), map),
+ (r.getCatchType() == null)
+ ? null
+ : (ObjectType) BcelWorld.makeBcelType(r.getCatchType()));
+ }
+ // now add local variables
+ gen.removeLocalVariables();
+ for (Iterator iter = localVariableStarts.keySet().iterator(); iter.hasNext(); ) {
+ LocalVariableTag tag = (LocalVariableTag) iter.next();
+ gen.addLocalVariable(
+ tag.getName(),
+ BcelWorld.makeBcelType(tag.getType()),
+ tag.getSlot(),
+ (InstructionHandle) localVariableStarts.get(tag),
+ (InstructionHandle) localVariableEnds.get(tag));
+ }
+ }
+
+ private static InstructionHandle remap(InstructionHandle ih, Map map) {
+ while (true) {
+ Object ret = map.get(ih);
+ if (ret == null) {
+ ih = ih.getNext();
+ } else {
+ return (InstructionHandle) ret;
+ }
+ }
+ }
+
+ // exception ordering
+ // An exception A preceeds an exception B in the exception table iff:
+
+ // * A and B were in the original method, and A preceeded B in the original exception table
+ // * If A has a higher priority than B, than it preceeds B.
+ // * If A and B have the same priority, then the one whose START happens EARLIEST has LEAST priority.
+ // in short, the outermost exception has least priority.
+ // we implement this with a LinkedList. We could possibly implement this with a java.util.SortedSet,
+ // but I don't trust the only implementation, TreeSet, to do the right thing.
+
+ private static void insertHandler(ExceptionRange fresh, LinkedList l) {
+ for (ListIterator iter = l.listIterator(); iter.hasNext();) {
+ ExceptionRange r = (ExceptionRange) iter.next();
+ if (fresh.getPriority() >= r.getPriority()) {
+ iter.previous();
+ iter.add(fresh);
+ return;
+ }
+ }
+ l.add(fresh);
+ }
+
+
+
+ public boolean isPrivate() {
+ return Modifier.isPrivate(getAccessFlags());
+ }
+
+
+ // ----
+
+ /** A good body is a body with the following properties:
+ *
+ * <ul>
+ * <li> For each branch instruction S in body, target T of S is in body.
+ * <li> For each branch instruction S in body, target T of S has S as a targeter.
+ * <li> For each instruction T in body, for each branch instruction S that is a
+ * targeter of T, S is in body.
+ * <li> For each non-range-handle instruction T in body, for each instruction S
+ * that is a targeter of T, S is
+ * either a branch instruction, an exception range or a tag
+ * <li> For each range-handle instruction T in body, there is exactly one targeter S
+ * that is a range.
+ * <li> For each range-handle instruction T in body, the range R targeting T is in body.
+ * <li> For each instruction T in body, for each exception range R targeting T, R is
+ * in body.
+ * <li> For each exception range R in body, let T := R.handler. T is in body, and R is one
+ * of T's targeters
+ * <li> All ranges are properly nested: For all ranges Q and R, if Q.start preceeds
+ * R.start, then R.end preceeds Q.end.
+ * </ul>
+ *
+ * Where the shorthand "R is in body" means "R.start is in body, R.end is in body, and
+ * any InstructionHandle stored in a field of R (such as an exception handle) is in body".
+ */
+
+ public void assertGoodBody() {
+ // XXX this is REALLY slow since we get the string first...
+ assertGoodBody(getBody(), toString());
+ }
+
+ // XXX we might not want to release with any calls to this incredibly inefficient method.
+ public static void assertGoodBody(InstructionList il, String from) {
+ if (true) return;
+ if (il == null) return;
+ Set body = new HashSet();
+ Stack ranges = new Stack();
+ for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) {
+ body.add(ih);
+ if (ih.getInstruction() instanceof BranchInstruction) {
+ body.add(ih.getInstruction());
+ }
+ }
+
+ for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) {
+ assertGoodHandle(ih, body, ranges, from);
+ InstructionTargeter[] ts = ih.getTargeters();
+ if (ts != null) {
+ for (int i = ts.length - 1; i >= 0; i--) {
+ assertGoodTargeter(ts[i], ih, body, from);
+ }
+ }
+ }
+ }
+
+ private static void assertGoodHandle(InstructionHandle ih, Set body, Stack ranges, String from) {
+ Instruction inst = ih.getInstruction();
+ if ((inst instanceof BranchInstruction) ^ (ih instanceof BranchHandle)) {
+ throw new BCException("bad instruction/handle pair in " + from);
+ }
+ if (Range.isRangeHandle(ih)) {
+ assertGoodRangeHandle(ih, body, ranges, from);
+ } else if (inst instanceof BranchInstruction) {
+ assertGoodBranchInstruction((BranchHandle) ih, (BranchInstruction) inst, body, ranges, from);
+ }
+ }
+
+ private static void assertGoodBranchInstruction(
+ BranchHandle ih,
+ BranchInstruction inst,
+ Set body,
+ Stack ranges,
+ String from)
+ {
+ if (ih.getTarget() != inst.getTarget()) {
+ throw new BCException("bad branch instruction/handle pair in " + from);
+ }
+ InstructionHandle target = ih.getTarget();
+ assertInBody(target, body, from);
+ assertTargetedBy(target, inst, from);
+ if (inst instanceof Select) {
+ Select sel = (Select) inst;
+ InstructionHandle[] itargets = sel.getTargets();
+ for (int k = itargets.length - 1; k >= 0; k--) {
+ assertInBody(itargets[k], body, from);
+ assertTargetedBy(itargets[k], inst, from);
+ }
+ }
+ }
+
+ /** ih is an InstructionHandle or a BranchInstruction */
+ private static void assertInBody(Object ih, Set body, String from) {
+ if (! body.contains(ih)) throw new BCException("thing not in body in " + from);
+ }
+
+ private static void assertGoodRangeHandle(InstructionHandle ih, Set body, Stack ranges, String from) {
+ Range r = getRangeAndAssertExactlyOne(ih, from);
+ assertGoodRange(r, body, from);
+ if (r.getStart() == ih) {
+ ranges.push(r);
+ } else if (r.getEnd() == ih) {
+ if (ranges.peek() != r) throw new BCException("bad range inclusion in " + from);
+ ranges.pop();
+ }
+ }
+
+ private static void assertGoodRange(Range r, Set body, String from) {
+ assertInBody(r.getStart(), body, from);
+ assertRangeHandle(r.getStart(), from);
+ assertTargetedBy(r.getStart(), r, from);
+
+ assertInBody(r.getEnd(), body, from);
+ assertRangeHandle(r.getEnd(), from);
+ assertTargetedBy(r.getEnd(), r, from);
+
+ if (r instanceof ExceptionRange) {
+ ExceptionRange er = (ExceptionRange) r;
+ assertInBody(er.getHandler(), body, from);
+ assertTargetedBy(er.getHandler(), r, from);
+ }
+ }
+
+ private static void assertRangeHandle(InstructionHandle ih, String from) {
+ if (! Range.isRangeHandle(ih)) throw new BCException("bad range handle " + ih + " in " + from);
+ }
+
+
+ private static void assertTargetedBy(
+ InstructionHandle target,
+ InstructionTargeter targeter,
+ String from)
+ {
+ InstructionTargeter[] ts = target.getTargeters();
+ if (ts == null) throw new BCException("bad targeting relationship in " + from);
+ for (int i = ts.length - 1; i >= 0; i--) {
+ if (ts[i] == targeter) return;
+ }
+ throw new RuntimeException("bad targeting relationship in " + from);
+ }
+
+ private static void assertTargets(InstructionTargeter targeter, InstructionHandle target, String from) {
+ if (targeter instanceof Range) {
+ Range r = (Range) targeter;
+ if (r.getStart() == target || r.getEnd() == target) return;
+ if (r instanceof ExceptionRange) {
+ if (((ExceptionRange)r).getHandler() == target) return;
+ }
+ } else if (targeter instanceof BranchInstruction) {
+ BranchInstruction bi = (BranchInstruction) targeter;
+ if (bi.getTarget() == target) return;
+ if (targeter instanceof Select) {
+ Select sel = (Select) targeter;
+ InstructionHandle[] itargets = sel.getTargets();
+ for (int k = itargets.length - 1; k >= 0; k--) {
+ if (itargets[k] == target) return;
+ }
+ }
+ } else if (targeter instanceof Tag) {
+ return;
+ }
+ throw new BCException(targeter + " doesn't target " + target + " in " + from );
+ }
+
+ private static Range getRangeAndAssertExactlyOne(InstructionHandle ih, String from) {
+ Range ret = null;
+ InstructionTargeter[] ts = ih.getTargeters();
+ if (ts == null) throw new BCException("range handle with no range in " + from);
+ for (int i = ts.length - 1; i >= 0; i--) {
+ if (ts[i] instanceof Range) {
+ if (ret != null) throw new BCException("range handle with multiple ranges in " + from);
+ ret = (Range) ts[i];
+ }
+ }
+ if (ret == null) throw new BCException("range handle with no range in " + from);
+ return ret;
+ }
+
+ private static void assertGoodTargeter(
+ InstructionTargeter t,
+ InstructionHandle ih,
+ Set body,
+ String from)
+ {
+ assertTargets(t, ih, from);
+ if (t instanceof Range) {
+ assertGoodRange((Range) t, body, from);
+ } else if (t instanceof BranchInstruction) {
+ assertInBody(t, body, from);
+ }
+ }
+
+
+ // ----
+
+ boolean isAdviceMethod() {
+ return memberView.getAssociatedShadowMunger() != null;
+ }
+
+ boolean isAjSynthetic() {
+ if (memberView == null) return true;
+ return memberView.isAjSynthetic();
+ }
+
+ public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature() {
+ //if (memberView == null) return null;
+ return memberView.getEffectiveSignature();
+ }
+
+ public String getSignature() {
+ return Member.typesToSignature(BcelWorld.fromBcel(getReturnType()),
+ BcelWorld.fromBcel(getArgumentTypes()));
+ }
+
+ public BcelMethod getMemberView() {
+ return memberView;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/LineNumberTag.java b/weaver/src/org/aspectj/weaver/bcel/LineNumberTag.java
new file mode 100644
index 000000000..ef5822f3a
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/LineNumberTag.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+/** we don't actually target instructions, but instructions target us. */
+public class LineNumberTag extends Tag {
+
+ private final int lineNumber;
+
+ public LineNumberTag(int lineNumber) {
+ this.lineNumber = lineNumber;
+ }
+
+ public int getLineNumber() { return lineNumber; }
+
+ // ---- from Object
+
+ public String toString() {
+ return "line " + lineNumber;
+ }
+ public boolean equals(Object other) {
+ if (! (other instanceof LineNumberTag)) return false;
+ return lineNumber == ((LineNumberTag)other).lineNumber;
+ }
+ public int hashCode() {
+ return lineNumber;
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/LocalVariableTag.java b/weaver/src/org/aspectj/weaver/bcel/LocalVariableTag.java
new file mode 100644
index 000000000..609dac005
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/LocalVariableTag.java
@@ -0,0 +1,60 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import org.aspectj.weaver.TypeX;
+
+public final class LocalVariableTag extends Tag {
+ private final TypeX type;
+ private final String name;
+ private final int slot;
+
+ public LocalVariableTag(TypeX type, String name, int slot) {
+ this.type = type;
+ this.name = name;
+ this.slot = slot;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public int getSlot() {
+ return slot;
+ }
+ public TypeX getType() {
+ return type;
+ }
+
+ // ---- from Object
+
+ public String toString() {
+ return "local " + slot + ": " + type + " " + name;
+ }
+ public boolean equals(Object other) {
+ if (!(other instanceof LocalVariableTag)) return false;
+ LocalVariableTag o = (LocalVariableTag)other;
+ return o.type.equals(type) && o.name.equals(name) && o.slot == slot;
+ }
+ private volatile int hashCode = 0;
+ public int hashCode() {
+ if (hashCode == 0) {
+ int ret = 17;
+ ret = 37*ret + type.hashCode();
+ ret = 37*ret + name.hashCode();
+ ret = 37*ret + slot;
+ hashCode = ret;
+ }
+ return hashCode;
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/Range.java b/weaver/src/org/aspectj/weaver/bcel/Range.java
new file mode 100644
index 000000000..0d6eb21b6
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/Range.java
@@ -0,0 +1,225 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.lang.reflect.Modifier;
+import java.util.Map;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.IntMap;
+
+abstract class Range implements InstructionTargeter {
+
+ protected InstructionList body;
+ protected InstructionHandle start;
+ protected InstructionHandle end;
+
+ // ---- initialization
+
+ protected Range(InstructionList il) {
+ this.body = il;
+ }
+
+
+ // ----
+
+ final InstructionList getBody() {
+ return body;
+ }
+ final InstructionHandle getStart() {
+ return start;
+ }
+ final InstructionHandle getEnd() {
+ return end;
+ }
+
+ // ----
+
+ boolean isEmpty() {
+ InstructionHandle ih = start;
+ while (ih != end) {
+ if (! Range.isRangeHandle(ih)) return false;
+ ih = ih.getNext();
+ }
+ return true;
+ }
+
+ static InstructionHandle getRealStart(InstructionHandle ih) {
+ while (Range.isRangeHandle(ih)) {
+ ih = ih.getNext();
+ }
+ return ih;
+ }
+
+ InstructionHandle getRealStart() {
+ return getRealStart(start);
+ }
+
+ static InstructionHandle getRealEnd(InstructionHandle ih) {
+ while (Range.isRangeHandle(ih)) {
+ ih = ih.getPrev();
+ }
+ return ih;
+ }
+ InstructionHandle getRealEnd() {
+ return getRealEnd(end);
+ }
+
+ static InstructionHandle getRealPrev(InstructionHandle ih) {
+ InstructionHandle ret = ih.getPrev();
+ while (isRangeHandle(ret)) {
+ ret = ret.getPrev();
+ }
+ return ret;
+ }
+
+ // ----
+
+ InstructionHandle insert(Instruction i, Where where) {
+ InstructionList il = new InstructionList();
+ InstructionHandle ret = il.insert(i);
+ insert(il, where);
+ return ret;
+ }
+ void insert(InstructionList freshIl, Where where) {
+ InstructionHandle h;
+ if (where == InsideBefore || where == OutsideBefore) {
+ h = getStart();
+ } else {
+ h = getEnd();
+ }
+ if (where == InsideBefore || where == OutsideAfter) {
+ body.append(h, freshIl);
+ } else {
+ InstructionHandle newStart = body.insert(h, freshIl);
+ if (where == OutsideBefore) {
+ // XXX this is slow. There's a better design than this. We should
+ // never have to retarget branches apart from the creation of ranges.
+ // basically, we should never weave OutsideBefore.
+ BcelShadow.retargetAllBranches(h, newStart);
+ }
+ }
+
+ }
+ InstructionHandle append(Instruction i) {
+ return insert(i, InsideAfter);
+ }
+ void append(InstructionList i) {
+ insert(i, InsideAfter);
+ }
+
+ static InstructionHandle remap(InstructionHandle h, Map m) {
+ return (InstructionHandle) m.get(h);
+ }
+
+ private static void setLineNumberFromNext(InstructionHandle ih) {
+ int lineNumber = Utility.getSourceLine(ih.getNext());
+ if (lineNumber != -1) {
+ Utility.setSourceLine(ih, lineNumber);
+ }
+ }
+
+ static InstructionHandle genStart(InstructionList body) {
+ InstructionHandle ih = body.insert(Range.RANGEINSTRUCTION);
+ setLineNumberFromNext(ih);
+ return ih;
+ }
+
+ static InstructionHandle genEnd(InstructionList body) {
+ return body.append(Range.RANGEINSTRUCTION);
+ }
+ static InstructionHandle genStart(InstructionList body, InstructionHandle ih) {
+ if (ih == null) return genStart(body);
+ InstructionHandle freshIh = body.insert(ih, Range.RANGEINSTRUCTION);
+ setLineNumberFromNext(freshIh);
+ return freshIh;
+ }
+
+ static InstructionHandle genEnd(InstructionList body, InstructionHandle ih) {
+ if (ih == null) return genEnd(body);
+ return body.append(ih, Range.RANGEINSTRUCTION);
+ }
+
+ // -----
+
+ public boolean containsTarget(InstructionHandle ih) {
+ return false;
+ }
+
+ public final void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
+ throw new RuntimeException("Ranges must be updated with an enclosing instructionList");
+ }
+
+ protected void updateTarget(
+ InstructionHandle old_ih,
+ InstructionHandle new_ih,
+ InstructionList new_il)
+ {
+ old_ih.removeTargeter(this);
+ if (new_ih != null)
+ new_ih.addTargeter(this);
+ body = new_il;
+
+ if (old_ih == start) {
+ start = new_ih;
+ }
+ if (old_ih == end) {
+ end = new_ih;
+ }
+ }
+
+ public static final boolean isRangeHandle(InstructionHandle ih) {
+ if (ih == null) return false;
+ return ih.getInstruction() == Range.RANGEINSTRUCTION;
+ }
+
+ protected static final Range getRange(InstructionHandle ih) {
+ // assert isRangeHandle(ih)
+ Range ret = null;
+ InstructionTargeter[] targeters = ih.getTargeters();
+ for (int i = targeters.length - 1; i >= 0; i--) {
+ if (targeters[i] instanceof Range) {
+ Range r = (Range) targeters[i];
+ if (r.getStart() != ih && r.getEnd() != ih) continue;
+ if (ret != null) throw new BCException("multiple ranges on same range handle: " + ret + ", " + targeters[i]);
+ ret = (Range) targeters[i];
+ }
+ }
+ if (ret == null) throw new BCException("shouldn't happen");
+ return ret;
+ }
+
+ // ----
+
+ static final Where InsideBefore = new Where("insideBefore");
+ static final Where InsideAfter = new Where("insideAfter");
+ static final Where OutsideBefore = new Where("outsideBefore");
+ static final Where OutsideAfter = new Where("outsideAfter");
+
+ // ---- constants
+
+ // note that this is STUPIDLY copied by Instruction.copy(), so don't do that.
+
+ public static final Instruction RANGEINSTRUCTION = new IMPDEP1();
+
+ // ----
+
+ static class Where {
+ private String name;
+ public Where(String name) { this.name = name; }
+ public String toString() { return name; }
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/ShadowRange.java b/weaver/src/org/aspectj/weaver/bcel/ShadowRange.java
new file mode 100644
index 000000000..edd22db95
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/ShadowRange.java
@@ -0,0 +1,199 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.*;
+
+final class ShadowRange extends Range {
+
+ private BcelShadow shadow;
+
+ // ---- initialization
+
+ /**
+ * After this constructor is called, this range is not well situated unless both
+ * {@link #associateWithTargets} and {@link #associateWithShadow} are called.
+ */
+ public ShadowRange(InstructionList body) {
+ super(body);
+ }
+ protected void associateWithTargets(InstructionHandle start, InstructionHandle end) {
+ // assert body.contains(start) && body.contains(end);
+ this.start = start;
+ this.end = end;
+ start.addTargeter(this);
+ end.addTargeter(this);
+ }
+ public void associateWithShadow(BcelShadow shadow) {
+ this.shadow = shadow;
+ shadow.setRange(this);
+ }
+
+ // ----
+
+ public Shadow.Kind getKind() {
+ return shadow.getKind();
+ }
+
+ public String toString() {
+ return shadow.toString();
+ }
+
+ void extractInstructionsInto(LazyMethodGen freshMethod, IntMap remap, boolean addReturn) {
+ LazyMethodGen.assertGoodBody(getBody(), toString());
+ freshMethod.assertGoodBody();
+ InstructionList freshBody = freshMethod.getBody();
+
+ for (InstructionHandle oldIh = start.getNext(); oldIh != end; oldIh = oldIh.getNext()) {
+ // first we copy the instruction itself.
+ Instruction oldI = oldIh.getInstruction();
+ Instruction freshI = (oldI == RANGEINSTRUCTION) ? oldI : oldI.copy();
+
+ // Now we add it to the new instruction list.
+ InstructionHandle freshIh;
+ if (freshI instanceof BranchInstruction) {
+ //If it's a targeting instruction,
+ // update the target(s) to point to the new copy instead of the old copy.
+ BranchInstruction oldBranch = (BranchInstruction) oldI;
+ BranchInstruction freshBranch = (BranchInstruction) freshI;
+ InstructionHandle oldTarget = oldBranch.getTarget();
+ oldTarget.removeTargeter(oldBranch);
+ oldTarget.addTargeter(freshBranch);
+ if (freshBranch instanceof Select) {
+ Select oldSelect = (Select) oldI;
+ Select freshSelect = (Select) freshI;
+ InstructionHandle[] oldTargets = freshSelect.getTargets();
+ for (int k = oldTargets.length - 1; k >= 0; k--) {
+ oldTargets[k].removeTargeter(oldSelect);
+ oldTargets[k].addTargeter(freshSelect);
+ }
+ }
+ freshIh = freshBody.append(freshBranch);
+ } else {
+ freshIh = freshBody.append(freshI);
+ }
+
+ // if source comes before target:
+ // source <--> target
+ // --> [process: target.removeTargeter(source); target.addTargeter(sourcecopy)]
+ // source ---------\
+ // v
+ // sourcecopy <--> target
+ // --> [ process: sourcecopy.updateTarget(target, targetcopy) ]
+ // source ----> target
+ // sourcecopy <--> targetcopy
+
+ // if target comes before source
+
+ // target <--> source
+ // --> [process: source.updateTarget(target, targetcopy) ]
+ // target
+ // targetcopy <--> source
+ // --> [process: targetcopy.removeTargeter(source); targetcopy.addTargeter(sourcecopy)]
+ // target source
+ // v
+ // targetcopy <--> sourcecopy
+
+ // now deal with the old instruction's targeters. Update them all to point to us
+ // instead of the old instruction. We use updateTarget to do this. One goal is
+ // to make sure we remove all targeters from the old guy, so we can successfully
+ // delete it.
+ InstructionTargeter[] sources = oldIh.getTargeters();
+ if (sources != null) {
+ for (int j = sources.length - 1; j >= 0; j--) {
+ InstructionTargeter source = sources[j];
+ if (source instanceof LocalVariableTag) {
+ // XXX destroying local variable info
+ source.updateTarget(oldIh, null);
+ } else if (source instanceof Range) {
+ // exceptions and shadows are just moved
+ ((Range)source).updateTarget(oldIh, freshIh, freshBody);
+ } else {
+ // line numbers can be shared,
+ // branches will be copied along with us.
+ source.updateTarget(oldIh, freshIh);
+ }
+ }
+ }
+ // we're now done with the old instruction entirely, and will ignore them through
+ // the rest of this loop. The only time we'll see them again is a second pass to
+ // delete them.
+
+ // now deal with local variable instructions. If this points to a remapped
+ // frame location, update the instruction's index. If this doesn't,
+ // do compaction/expansion: allocate a new local variable, and modify the remap
+ // to handle it. XXX We're doing the safe thing and allocating ALL these local variables
+ // as double-wides, in case the location is found to hold a double-wide later.
+ if (freshI instanceof LocalVariableInstruction || freshI instanceof RET) {
+ IndexedInstruction indexedI = (IndexedInstruction) freshI;
+ int oldIndex = indexedI.getIndex();
+ int freshIndex;
+ if (! remap.hasKey(oldIndex)) {
+ freshIndex = freshMethod.allocateLocal(2);
+ remap.put(oldIndex, freshIndex);
+ } else {
+ freshIndex = remap.get(oldIndex);
+ }
+ indexedI.setIndex(freshIndex);
+ }
+// System.err.println("JUST COPIED: " + oldIh.getInstruction().toString(freshMethod.getEnclosingClass().getConstantPoolGen().getConstantPool())
+// + " INTO " + freshIh.getInstruction().toString(freshMethod.getEnclosingClass().getConstantPoolGen().getConstantPool()));
+ }
+
+ // we've now copied out all the instructions.
+ // now delete the instructions... we've already taken care of the damn
+ // targets, but since TargetLostException is checked, we have to do this stuff.
+ try {
+ for (InstructionHandle oldIh = start.getNext(); oldIh != end; ) {
+ InstructionHandle next = oldIh.getNext();
+ body.delete(oldIh);
+ oldIh = next;
+ }
+ } catch (TargetLostException e) {
+ throw new BCException("shouldn't have gotten a target lost");
+ }
+
+ // now add the return, if one is warranted.
+ InstructionHandle ret = null;
+ if (addReturn) {
+ // we really should pull this out somewhere...
+ ret = freshBody.append(
+ new InstructionFactory(freshMethod.getEnclosingClass().getConstantPoolGen())
+ .createReturn(freshMethod.getReturnType()));
+ }
+ // and remap all the old targeters of the end handle of the range to the return.
+ InstructionTargeter[] ts = end.getTargeters();
+ if (ts != null) { // shouldn't be the case, but let's test for paranoia
+ for (int j = ts.length - 1; j >= 0; j--) {
+ InstructionTargeter t = ts[j];
+ if (t == this) continue;
+ if (! addReturn) {
+ throw new BCException("range has target, but we aren't adding a return");
+ } else {
+ t.updateTarget(end, ret);
+ }
+ }
+ }
+
+ LazyMethodGen.assertGoodBody(getBody(), toString());
+ freshMethod.assertGoodBody();
+ }
+
+ public BcelShadow getShadow() {
+ return shadow;
+ }
+
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/Tag.java b/weaver/src/org/aspectj/weaver/bcel/Tag.java
new file mode 100644
index 000000000..cfa5eb41f
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/Tag.java
@@ -0,0 +1,42 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import org.apache.bcel.generic.*;
+
+/** A tag is an instruction-targeter that doesn't bother remembering its target(s) */
+abstract class Tag implements InstructionTargeter, Cloneable {
+
+ public Tag() {
+ }
+
+ // ---- from InstructionTargeter
+ public boolean containsTarget(InstructionHandle ih) {
+ return false;
+ }
+
+ public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
+ old_ih.removeTargeter(this);
+ if (new_ih != null)
+ new_ih.addTargeter(this);
+ }
+
+ public Tag copy() {
+ try {
+ return (Tag)clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException("Sanity check, can't clone me");
+ }
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/UnwovenClassFile.java b/weaver/src/org/aspectj/weaver/bcel/UnwovenClassFile.java
new file mode 100644
index 000000000..9ea49d53f
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/UnwovenClassFile.java
@@ -0,0 +1,181 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.bcel.classfile.JavaClass;
+import org.aspectj.util.FileUtil;
+
+public class UnwovenClassFile {
+ protected String filename;
+ protected byte[] bytes;
+// protected JavaClass javaClass = null;
+ protected byte[] writtenBytes = null;
+ protected List /* ChildClass */ writtenChildClasses = new ArrayList(0);
+ protected String className = null;
+
+ public UnwovenClassFile(String filename, byte[] bytes) {
+ this.filename = filename;
+ this.bytes = bytes;
+ }
+
+ public String getFilename() {
+ return filename;
+ }
+
+ public String makeInnerFileName(String innerName) {
+ String prefix = filename.substring(0, filename.length()-6); // strip the .class
+ return prefix + "$" + innerName + ".class";
+ }
+
+ public byte[] getBytes() {
+// if (bytes == null) bytes = javaClass.getBytes();
+ return bytes;
+ }
+
+ public JavaClass getJavaClass() {
+ //XXX need to know when to make a new class and when not to
+ //XXX this is an important optimization
+ if (getBytes() == null) {
+ System.out.println("no bytes for: " + getFilename());
+ Thread.currentThread().dumpStack();
+ }
+ return Utility.makeJavaClass(filename, getBytes());
+// if (javaClass == null) javaClass = Utility.makeJavaClass(filename, getBytes());
+// return javaClass;
+ }
+
+ public boolean exists() {
+ return getBytes() != null;
+ }
+
+
+ public void writeUnchangedBytes() throws IOException {
+ writeWovenBytes(getBytes(), Collections.EMPTY_LIST);
+ }
+
+ public void writeWovenBytes(byte[] bytes, List childClasses) throws IOException {
+ writeChildClasses(childClasses);
+
+ //System.err.println("about to write: " + this + ", " + writtenBytes + ", ");
+// + writtenBytes != null + " && " + unchanged(bytes, writtenBytes) );
+
+ if (writtenBytes != null && !unchanged(bytes, writtenBytes)) return;
+
+ BufferedOutputStream os = FileUtil.makeOutputStream(new File(filename));
+ os.write(bytes);
+ os.close();
+
+ writtenBytes = bytes;
+ }
+
+ private void writeChildClasses(List childClasses) throws IOException {
+ //??? we only really need to delete writtenChildClasses whose
+ //??? names aren't in childClasses; however, it's unclear
+ //??? how much that will affect performance
+ deleteAllChildClasses();
+
+ childClasses.removeAll(writtenChildClasses); //XXX is this right
+
+ for (Iterator iter = childClasses.iterator(); iter.hasNext();) {
+ ChildClass childClass = (ChildClass) iter.next();
+ writeChildClassFile(childClass.name, childClass.bytes);
+
+ }
+
+ writtenChildClasses = childClasses;
+
+ }
+
+ private void writeChildClassFile(String innerName, byte[] bytes) throws IOException {
+ BufferedOutputStream os =
+ FileUtil.makeOutputStream(new File(makeInnerFileName(innerName)));
+ os.write(bytes);
+ os.close();
+ }
+
+
+ protected void deleteAllChildClasses() {
+ for (Iterator iter = writtenChildClasses.iterator(); iter.hasNext();) {
+ ChildClass childClass = (ChildClass) iter.next();
+ deleteChildClassFile(childClass.name);
+ }
+ }
+
+ protected void deleteChildClassFile(String innerName) {
+ File childClassFile = new File(makeInnerFileName(innerName));
+ childClassFile.delete();
+ }
+
+
+
+ private static boolean unchanged(byte[] b1, byte[] b2) {
+ int len = b1.length;
+ if (b2.length != len) return false;
+ for (int i=0; i < len; i++) {
+ if (b1[i] != b2[i]) return false;
+ }
+ return true;
+ }
+
+
+ public String getClassName() {
+ if (className == null) className = getJavaClass().getClassName();
+ return className;
+ }
+ public byte[] getWrittenBytes() {
+ return writtenBytes;
+ }
+
+ public String toString() {
+ return "UnwovenClassFile(" + filename + ", " + getClassName() + ")";
+ }
+
+ public void deleteRealFile() throws IOException {
+ new File(filename).delete();
+ }
+
+
+
+
+ // record
+ public static class ChildClass {
+ public final String name;
+ public final byte[] bytes;
+
+ ChildClass(String name, byte[] bytes) {
+ this.name = name;
+ this.bytes = bytes;
+ }
+
+ public boolean equals(Object other) {
+ if (! (other instanceof ChildClass)) return false;
+ ChildClass o = (ChildClass) other;
+ return o.name.equals(name) && unchanged(o.bytes, bytes);
+ }
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ public String toString() {
+ return "(ChildClass " + name + ")";
+ }
+ }
+}
+
+
+
+
diff --git a/weaver/src/org/aspectj/weaver/bcel/UnwovenZipClassFile.java b/weaver/src/org/aspectj/weaver/bcel/UnwovenZipClassFile.java
new file mode 100644
index 000000000..2c4c760a9
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/UnwovenZipClassFile.java
@@ -0,0 +1,45 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.zip.*;
+
+//XXX we believe this is now unneeded
+public class UnwovenZipClassFile extends UnwovenClassFile {
+ private ZipOutputStream zipOutputStream;
+
+ public UnwovenZipClassFile(ZipOutputStream zipOutputStream, String filename, byte[] bytes) {
+ super(filename, bytes);
+ this.zipOutputStream = zipOutputStream;
+ }
+
+
+ public void writeWovenBytes(byte[] bytes, List childClasses) throws IOException {
+ //??? we rewrite this every time
+ if (!childClasses.isEmpty()) {
+ throw new RuntimeException("unimplemented");
+ }
+
+ ZipEntry newEntry = new ZipEntry(filename); //??? get compression scheme right
+
+ zipOutputStream.putNextEntry(newEntry);
+ zipOutputStream.write(bytes);
+ zipOutputStream.closeEntry();
+
+ writtenBytes = bytes;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/Utility.java b/weaver/src/org/aspectj/weaver/bcel/Utility.java
new file mode 100644
index 000000000..9da48c01f
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/Utility.java
@@ -0,0 +1,442 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.*;
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.*;
+
+public class Utility {
+
+ private Utility() {
+ super();
+ }
+
+
+ public static Instruction createSuperInvoke(
+ InstructionFactory fact,
+ BcelWorld world,
+ Member signature) {
+ short kind;
+ if (signature.isInterface()) {
+ throw new RuntimeException("bad");
+ } else if (signature.isPrivate() || signature.getName().equals("<init>")) {
+ throw new RuntimeException("unimplemented, possibly bad");
+ } else if (signature.isStatic()) {
+ throw new RuntimeException("bad");
+ } else {
+ kind = Constants.INVOKESPECIAL;
+ }
+
+ return fact.createInvoke(
+ signature.getDeclaringType().getName(),
+ signature.getName(),
+ world.makeBcelType(signature.getReturnType()),
+ world.makeBcelTypes(signature.getParameterTypes()),
+ kind);
+ }
+
+ // XXX don't need the world now
+ public static Instruction createInvoke(
+ InstructionFactory fact,
+ BcelWorld world,
+ Member signature) {
+ short kind;
+ if (signature.isInterface()) {
+ kind = Constants.INVOKEINTERFACE;
+ } else if (signature.isPrivate() || signature.getName().equals("<init>")) {
+ kind = Constants.INVOKESPECIAL;
+ } else if (signature.isStatic()) {
+ kind = Constants.INVOKESTATIC;
+ } else {
+ kind = Constants.INVOKEVIRTUAL;
+ }
+
+ return fact.createInvoke(
+ signature.getDeclaringType().getName(),
+ signature.getName(),
+ BcelWorld.makeBcelType(signature.getReturnType()),
+ BcelWorld.makeBcelTypes(signature.getParameterTypes()),
+ kind);
+ }
+
+ public static Instruction createGet(InstructionFactory fact, Member signature) {
+ short kind;
+ if (signature.isStatic()) {
+ kind = Constants.GETSTATIC;
+ } else {
+ kind = Constants.GETFIELD;
+ }
+
+ return fact.createFieldAccess(
+ signature.getDeclaringType().getName(),
+ signature.getName(),
+ BcelWorld.makeBcelType(signature.getReturnType()),
+ kind);
+ }
+
+ public static Instruction createSet(InstructionFactory fact, Member signature) {
+ short kind;
+ if (signature.isStatic()) {
+ kind = Constants.PUTSTATIC;
+ } else {
+ kind = Constants.PUTFIELD;
+ }
+
+ return fact.createFieldAccess(
+ signature.getDeclaringType().getName(),
+ signature.getName(),
+ BcelWorld.makeBcelType(signature.getReturnType()),
+ kind);
+ }
+
+ public static Instruction createInvoke(
+ InstructionFactory fact,
+ JavaClass declaringClass,
+ Method newMethod) {
+ short kind;
+ if (newMethod.isInterface()) {
+ kind = Constants.INVOKEINTERFACE;
+ } else if (newMethod.isPrivate() || newMethod.getName().equals("<init>")) {
+ kind = Constants.INVOKESPECIAL;
+ } else if (newMethod.isStatic()) {
+ kind = Constants.INVOKESTATIC;
+ } else {
+ kind = Constants.INVOKEVIRTUAL;
+ }
+
+ return fact.createInvoke(
+ declaringClass.getClassName(),
+ newMethod.getName(),
+ Type.getReturnType(newMethod.getSignature()),
+ Type.getArgumentTypes(newMethod.getSignature()),
+ kind);
+ }
+
+ public static Instruction createInstanceof(InstructionFactory fact, ObjectType t) {
+ return new INSTANCEOF(fact.getConstantPool().addClass(t));
+ }
+
+
+ public static Instruction createInvoke(
+ InstructionFactory fact,
+ LazyMethodGen m) {
+ short kind;
+ if (m.getEnclosingClass().isInterface()) {
+ kind = Constants.INVOKEINTERFACE;
+ } else if (m.isPrivate() || m.getName().equals("<init>")) {
+ kind = Constants.INVOKESPECIAL;
+ } else if (m.isStatic()) {
+ kind = Constants.INVOKESTATIC;
+ } else {
+ kind = Constants.INVOKEVIRTUAL;
+ }
+
+ return fact.createInvoke(
+ m.getClassName(),
+ m.getName(),
+ m.getReturnType(),
+ m.getArgumentTypes(),
+ kind);
+ }
+
+
+ // ??? these should perhaps be cached. Remember to profile this to see if it's a problem.
+ public static String[] makeArgNames(int n) {
+ String[] ret = new String[n];
+ for (int i=0; i<n; i++) {
+ ret[i] = "arg" + i;
+ }
+ return ret;
+ }
+
+ public static void appendConversion(
+ InstructionList il,
+ InstructionFactory fact,
+ ResolvedTypeX fromType,
+ ResolvedTypeX toType)
+ {
+ if (! toType.isConvertableFrom(fromType)) {
+ throw new BCException("can't convert from " + fromType + " to " + toType);
+ }
+ if (toType.needsNoConversionFrom(fromType)) return;
+
+ if (toType.equals(ResolvedTypeX.VOID)) {
+ // assert fromType.equals(TypeX.OBJECT)
+ il.append(fact.createPop(fromType.getSize()));
+ } else if (fromType.equals(ResolvedTypeX.VOID)) {
+ // assert toType.equals(TypeX.OBJECT)
+ il.append(fact.createNull(Type.OBJECT));
+ return;
+ } else if (fromType.equals(TypeX.OBJECT)) {
+ Type to = BcelWorld.makeBcelType(toType);
+ if (toType.isPrimitive()) {
+ String name = toType.toString() + "Value";
+ il.append(
+ fact.createInvoke(
+ "org.aspectj.runtime.internal.Conversions",
+ name,
+ to,
+ new Type[] { Type.OBJECT },
+ Constants.INVOKESTATIC));
+ } else {
+ il.append(fact.createCheckCast((ReferenceType)to));
+ }
+ } else if (toType.equals(TypeX.OBJECT)) {
+ // assert fromType.isPrimitive()
+ Type from = BcelWorld.makeBcelType(fromType);
+ String name = fromType.toString() + "Object";
+ il.append(
+ fact.createInvoke(
+ "org.aspectj.runtime.internal.Conversions",
+ name,
+ Type.OBJECT,
+ new Type[] { from },
+ Constants.INVOKESTATIC));
+ } else if (fromType.isPrimitive()) {
+ // assert toType.isPrimitive()
+ Type from = BcelWorld.makeBcelType(fromType);
+ Type to = BcelWorld.makeBcelType(toType);
+ try {
+ il.append(fact.createCast(from, to));
+ } catch (RuntimeException e) {
+ il.append(fact.createCast(from, Type.INT));
+ il.append(fact.createCast(Type.INT, to));
+ }
+ } else {
+ Type to = BcelWorld.makeBcelType(toType);
+ // assert ! fromType.isPrimitive() && ! toType.isPrimitive()
+ il.append(fact.createCheckCast((ReferenceType) to));
+ }
+ }
+
+
+ public static InstructionList createConversion(
+ InstructionFactory fact,
+ Type fromType,
+ Type toType) {
+ //System.out.println("cast to: " + toType);
+
+ InstructionList il = new InstructionList();
+ if (fromType.equals(toType))
+ return il;
+ if (toType.equals(Type.VOID)) {
+ il.append(fact.createPop(fromType.getSize()));
+ return il;
+ }
+
+ if (fromType.equals(Type.VOID)) {
+ if (toType instanceof BasicType)
+ throw new BCException("attempting to cast from void to basic type");
+ il.append(fact.createNull(Type.OBJECT));
+ return il;
+ }
+
+ if (fromType.equals(Type.OBJECT)) {
+ if (toType instanceof BasicType) {
+ String name = toType.toString() + "Value";
+ il.append(
+ fact.createInvoke(
+ "org.aspectj.runtime.internal.Conversions",
+ name,
+ toType,
+ new Type[] { Type.OBJECT },
+ Constants.INVOKESTATIC));
+ return il;
+ }
+ }
+
+ if (toType.equals(Type.OBJECT)) {
+ if (fromType instanceof BasicType) {
+ String name = fromType.toString() + "Object";
+ il.append(
+ fact.createInvoke(
+ "org.aspectj.runtime.internal.Conversions",
+ name,
+ Type.OBJECT,
+ new Type[] { fromType },
+ Constants.INVOKESTATIC));
+ return il;
+ } else if (fromType instanceof ReferenceType) {
+ return il;
+ } else {
+ throw new RuntimeException();
+ }
+ }
+
+ if (fromType instanceof ReferenceType
+ && ((ReferenceType)fromType).isAssignmentCompatibleWith(toType)) {
+ return il;
+ }
+
+ il.append(fact.createCast(fromType, toType));
+ return il;
+ }
+
+ public static Instruction createConstant(
+ InstructionFactory fact,
+ int i) {
+ Instruction inst;
+ switch(i) {
+ case -1: inst = fact.ICONST_M1; break;
+ case 0: inst = fact.ICONST_0; break;
+ case 1: inst = fact.ICONST_1; break;
+ case 2: inst = fact.ICONST_2; break;
+ case 3: inst = fact.ICONST_3; break;
+ case 4: inst = fact.ICONST_4; break;
+ case 5: inst = fact.ICONST_5; break;
+ }
+ if (i <= Byte.MAX_VALUE && i >= Byte.MIN_VALUE) {
+ inst = new BIPUSH((byte)i);
+ } else if (i <= Short.MAX_VALUE && i >= Short.MIN_VALUE) {
+ inst = new SIPUSH((short)i);
+ } else {
+ inst = new LDC(fact.getClassGen().getConstantPool().addInteger(i));
+ }
+ return inst;
+ }
+
+ public static JavaClass makeJavaClass(String filename, byte[] bytes) {
+ try {
+ ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes), filename);
+ return parser.parse();
+ } catch (IOException e) {
+ throw new BCException("malformed class file");
+ }
+ }
+
+ public static String arrayToString(int[] a) {
+ int len = a.length;
+ if (len == 0) return "[]";
+ StringBuffer buf = new StringBuffer("[");
+ buf.append(a[0]);
+ for (int i = 1; i < len; i++) {
+ buf.append(", ");
+ buf.append(a[i]);
+ }
+ buf.append("]");
+ return buf.toString();
+ }
+
+ /**
+ * replace an instruction handle with another instruction, in this case, a branch instruction.
+ *
+ * @param ih the instruction handle to replace.
+ * @param branchInstruction the branch instruction to replace ih with
+ * @param enclosingMethod where to find ih's instruction list.
+ */
+ public static void replaceInstruction(
+ InstructionHandle ih,
+ BranchInstruction branchInstruction,
+ LazyMethodGen enclosingMethod)
+ {
+
+ InstructionList il = enclosingMethod.getBody();
+ InstructionHandle fresh = il.append(ih, branchInstruction);
+ deleteInstruction(ih, fresh, enclosingMethod);
+ }
+
+ /** delete an instruction handle and retarget all targeters of the deleted instruction
+ * to the next instruction. Obviously, this should not be used to delete
+ * a control transfer instruction unless you know what you're doing.
+ *
+ * @param ih the instruction handle to delete.
+ * @param enclosingMethod where to find ih's instruction list.
+ */
+ public static void deleteInstruction(
+ InstructionHandle ih,
+ LazyMethodGen enclosingMethod)
+ {
+ deleteInstruction(ih, ih.getNext(), enclosingMethod);
+ }
+
+
+ /** delete an instruction handle and retarget all targeters of the deleted instruction
+ * to the provided target.
+ *
+ * @param ih the instruction handle to delete
+ * @param retargetTo the instruction handle to retarget targeters of ih to.
+ * @param enclosingMethod where to find ih's instruction list.
+ */
+ public static void deleteInstruction(
+ InstructionHandle ih,
+ InstructionHandle retargetTo,
+ LazyMethodGen enclosingMethod)
+ {
+ InstructionList il = enclosingMethod.getBody();
+ InstructionTargeter[] targeters = ih.getTargeters();
+ if (targeters != null) {
+ for (int i = targeters.length - 1; i >= 0; i--) {
+ InstructionTargeter targeter = targeters[i];
+ targeter.updateTarget(ih, retargetTo);
+ }
+ ih.removeAllTargeters();
+ }
+ try {
+ il.delete(ih);
+ } catch (TargetLostException e) {
+ throw new BCException("this really can't happen");
+ }
+ }
+
+ /** returns -1 if no source line attribute */
+ public static int getSourceLine(InstructionHandle ih) {
+ InstructionTargeter[] ts = ih.getTargeters();
+ if (ts != null) {
+ for (int j = ts.length - 1; j >= 0; j--) {
+ InstructionTargeter t = ts[j];
+ if (t instanceof LineNumberTag) {
+ return ((LineNumberTag)t).getLineNumber();
+ }
+ }
+ }
+ return -1;
+ }
+
+ // assumes that there is no already extant source line tag. Otherwise we'll have to be better.
+ public static void setSourceLine(InstructionHandle ih, int lineNumber) {
+ ih.addTargeter(new LineNumberTag(lineNumber));
+ }
+
+ public static int makePublic(int i) {
+ return i & ~(Modifier.PROTECTED | Modifier.PRIVATE) | Modifier.PUBLIC;
+ }
+ public static int makePrivate(int i) {
+ return i & ~(Modifier.PROTECTED | Modifier.PUBLIC) | Modifier.PRIVATE;
+ }
+ public static BcelVar[] pushAndReturnArrayOfVars(
+ ResolvedTypeX[] proceedParamTypes,
+ InstructionList il,
+ InstructionFactory fact,
+ LazyMethodGen enclosingMethod)
+ {
+ int len = proceedParamTypes.length;
+ BcelVar[] ret = new BcelVar[len];
+
+ for (int i = len - 1; i >= 0; i--) {
+ ResolvedTypeX typeX = proceedParamTypes[i];
+ Type type = BcelWorld.makeBcelType(typeX);
+ int local = enclosingMethod.allocateLocal(type);
+
+ il.append(fact.createStore(type, local));
+ ret[i] = new BcelVar(typeX, local);
+ }
+ return ret;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/ZipFileWeaver.java b/weaver/src/org/aspectj/weaver/bcel/ZipFileWeaver.java
new file mode 100644
index 000000000..c243ec6bf
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/ZipFileWeaver.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.*;
+import java.util.zip.*;
+
+import org.aspectj.util.FileUtil;
+
+
+//XXX delete very soon
+public class ZipFileWeaver {
+ File inFile;
+ public ZipFileWeaver(File inFile) {
+ super();
+ this.inFile = inFile;
+ }
+
+ public void weave(BcelWeaver weaver, File outFile) throws IOException {
+ int count = 0;
+ long startTime = System.currentTimeMillis();
+ weaver.addJarFile(inFile, new File("."));
+ weaver.weave(outFile);
+ long stopTime = System.currentTimeMillis();
+
+
+ System.out.println("handled " + count + " entries, in " +
+ (stopTime-startTime)/1000. + " seconds");
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java b/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java
new file mode 100644
index 000000000..96a2b4ce2
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java
@@ -0,0 +1,84 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.util.Map;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.util.*;
+
+public class AndPointcut extends Pointcut {
+ Pointcut left, right; // exposed for testing
+
+ public AndPointcut(Pointcut left, Pointcut right) {
+ super();
+ this.left = left;
+ this.right = right;
+ setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
+ }
+
+ public FuzzyBoolean match(Shadow shadow) {
+ return left.match(shadow).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(DataInputStream s, ISourceContext context) throws IOException {
+ AndPointcut ret = new AndPointcut(Pointcut.read(s, context), Pointcut.read(s, context));
+ ret.readLocation(context, s);
+ return ret;
+ }
+
+
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ return Test.makeAnd(left.findResidue(shadow, state), right.findResidue(shadow, state));
+ }
+
+ public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
+ return new AndPointcut(left.concretize1(inAspect, bindings),
+ right.concretize1(inAspect, bindings));
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java
new file mode 100644
index 000000000..86a63f971
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java
@@ -0,0 +1,79 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ResolvedTypeX;
+
+/**
+ * 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); //??? we override all methods that care about includeSubtypes
+ this.left = left;
+ this.right = right;
+ setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
+ }
+
+ public FuzzyBoolean matchesInstanceof(ResolvedTypeX type) {
+ return left.matchesInstanceof(type).and(right.matchesInstanceof(type));
+ }
+
+ protected boolean matchesExactly(ResolvedTypeX type) {
+ //??? if these had side-effects, this sort-circuit could be a mistake
+ return left.matchesExactly(type) && right.matchesExactly(type);
+ }
+
+ public boolean matchesStatically(ResolvedTypeX type) {
+ return left.matchesStatically(type) && right.matchesStatically(type);
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ s.writeByte(TypePattern.AND);
+ left.write(s);
+ right.write(s);
+ writeLocation(s);
+ }
+
+ public static TypePattern read(DataInputStream s, ISourceContext context) throws IOException {
+ TypePattern ret = new AndTypePattern(TypePattern.read(s, context), TypePattern.read(s, context));
+ ret.readLocation(context, s);
+ return ret;
+ }
+
+ public TypePattern resolveBindings(
+ IScope scope,
+ Bindings bindings,
+ boolean allowBinding) {
+ left = left.resolveBindings(scope, bindings, false);
+ right = right.resolveBindings(scope, bindings, false);
+ return this;
+ }
+
+ public String toString() {
+ return "(" + left.toString() + " && " + right.toString() + ")";
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java
new file mode 100644
index 000000000..4c3d22449
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java
@@ -0,0 +1,140 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+
+/**
+ * args(arguments)
+ *
+ * @author Erik Hilsdale
+ * @author Jim Hugunin
+ */
+public class ArgsPointcut extends NameBindingPointcut {
+ TypePatternList arguments;
+
+ public ArgsPointcut(TypePatternList arguments) {
+ this.arguments = arguments;
+ }
+
+ public FuzzyBoolean match(Shadow shadow) {
+ int n = shadow.getArgCount();
+ TypeX[] argTypes = new TypeX[n];
+ for (int i=0; i < n; i++) {
+ argTypes[i] = shadow.getArgType(i);
+ }
+ FuzzyBoolean ret =
+ arguments.matches(shadow.getIWorld().resolve(argTypes), TypePattern.DYNAMIC);
+ return ret;
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ s.writeByte(Pointcut.ARGS);
+ arguments.write(s);
+ writeLocation(s);
+ }
+
+ public static Pointcut read(DataInputStream 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);
+ }
+
+ public void postRead(ResolvedTypeX enclosingType) {
+ arguments.postRead(enclosingType);
+ }
+
+
+ public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
+ return new ArgsPointcut(arguments.resolveReferences(bindings));
+ }
+
+ private Test findResidueNoEllipsis(Shadow shadow, ExposedState state, TypePattern[] patterns) {
+ int len = shadow.getArgCount();
+ //System.err.println("boudn to : " + len + ", " + patterns.length);
+ if (patterns.length != len) {
+ throw new RuntimeException("this should never happen");
+ //return Literal.FALSE; //??? this should never happen
+ }
+
+ Test ret = Literal.TRUE;
+
+ for (int i=0; i < len; i++) {
+ TypeX argType = shadow.getArgType(i);
+ TypePattern type = patterns[i];
+ if (!(type instanceof BindingTypePattern)) {
+ if (type.matchesInstanceof(shadow.getIWorld().resolve(argType)).alwaysTrue()) {
+ continue;
+ }
+ }
+ ret = Test.makeAnd(ret,
+ exposeStateForVar(shadow.getArgVar(i), type, state,shadow.getIWorld()));
+ }
+
+ return ret;
+ }
+
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ 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[shadow.getArgCount()];
+ 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 BetaException("unimplemented");
+ }
+ }
+
+ public String toString() {
+ return "args" + arguments.toString() + "";
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/BasicToken.java b/weaver/src/org/aspectj/weaver/patterns/BasicToken.java
new file mode 100644
index 000000000..9a36b35e7
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/BasicToken.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+
+public 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/weaver/src/org/aspectj/weaver/patterns/BasicTokenSource.java b/weaver/src/org/aspectj/weaver/patterns/BasicTokenSource.java
new file mode 100644
index 000000000..ef4db5bf8
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/BasicTokenSource.java
@@ -0,0 +1,153 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.util.*;
+
+import org.aspectj.weaver.*;
+
+
+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) {
+ 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 ':':
+ tokens.add(BasicToken.makeOperator(makeString(ch), i-1, i-1));
+ continue;
+ case '&':
+ 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));
+ 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()]), null);
+ }
+
+ private static String makeString(char ch) {
+ // slightly inefficient ;-)
+ return new String(new char[] {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;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/BindingTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/BindingTypePattern.java
new file mode 100644
index 000000000..836b6ac4c
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/BindingTypePattern.java
@@ -0,0 +1,74 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.weaver.*;
+
+public class BindingTypePattern extends ExactTypePattern {
+ private int formalIndex;
+
+ public BindingTypePattern(TypeX type, int index) {
+ super(type, false);
+ this.formalIndex = index;
+ }
+
+ public BindingTypePattern(FormalBinding binding) {
+ this(binding.getType(), binding.getIndex());
+ }
+
+ public int getFormalIndex() {
+ return formalIndex;
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof BindingTypePattern)) return false;
+ BindingTypePattern o = (BindingTypePattern)other;
+ return o.type.equals(this.type) && o.formalIndex == this.formalIndex;
+ }
+ public int hashCode() {
+ int result = 17;
+ result = 37*result + type.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);
+ writeLocation(out);
+ }
+
+ public static TypePattern read(DataInputStream s, ISourceContext context) throws IOException {
+ TypePattern ret = new BindingTypePattern(TypeX.read(s), s.readShort());
+ ret.readLocation(context, s);
+ return ret;
+ }
+
+ public TypePattern remapAdviceFormals(IntMap bindings) {
+ if (!bindings.hasKey(formalIndex)) {
+ return new ExactTypePattern(type, false);
+ } else {
+ int newFormalIndex = bindings.get(formalIndex);
+ return new BindingTypePattern(type, newFormalIndex);
+ }
+ }
+
+ public String toString() {
+ //Thread.currentThread().dumpStack();
+ return "BindingTypePattern(" + type.toString() + ", " + formalIndex + ")";
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/Bindings.java b/weaver/src/org/aspectj/weaver/patterns/Bindings.java
new file mode 100644
index 000000000..b0a1e4eda
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/Bindings.java
@@ -0,0 +1,127 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.BCException;
+import org.aspectj.bridge.IMessage;
+
+public class Bindings {
+ public static final Bindings NONE = new Bindings(0);
+
+ private BindingTypePattern[] bindings;
+
+ public Bindings(BindingTypePattern[] bindings) {
+ this.bindings = bindings;
+ }
+
+ public Bindings(int count) {
+ this(new BindingTypePattern[count]);
+ }
+
+ public void register(BindingTypePattern binding, IScope scope) {
+ int index = binding.getFormalIndex();
+ BindingTypePattern 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) {
+ BindingTypePattern[] b1 = this.bindings;
+ BindingTypePattern[] 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 Bindings copy() {
+// int len = bindings.length;
+// boolean[] a = new boolean[len];
+// System.arraycopy(bindings, 0, a, 0, len);
+ return new Bindings((BindingTypePattern[])bindings.clone());
+ }
+
+ public void checkAllBound(IScope scope) {
+ for (int i=0, len=bindings.length; i < len; i++) {
+ if (bindings[i] == null) {
+ scope.message(IMessage.ERROR, scope.getFormal(i), "formal unbound in pointcut");
+ }
+ }
+
+ }
+
+ public int size() { return bindings.length; }
+
+ public void checkEmpty(IScope scope, String message) {
+ for (int i=0, len=bindings.length; i < len; i++) {
+ if (bindings[i] != null) {
+ scope.message(IMessage.ERROR, bindings[i], message);
+ }
+ }
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java b/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java
new file mode 100644
index 000000000..72348d45b
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.*;
+import java.util.List;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.weaver.bcel.BcelTypeMunger;
+import org.aspectj.util.*;
+
+
+public class CflowPointcut extends Pointcut {
+ private Pointcut entry;
+ private boolean isBelow;
+ 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, TypeX.NONE, Pointcut.makeMatchesNothing(Pointcut.RESOLVED));
+
+
+ public CflowPointcut(Pointcut entry, boolean isBelow, int[] freeVars) {
+ this.entry = entry;
+ this.isBelow = isBelow;
+ this.freeVars = freeVars;
+ }
+
+ public FuzzyBoolean match(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(s, freeVars);
+ writeLocation(s);
+ }
+ public static Pointcut read(DataInputStream 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 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(this.entry) && o.isBelow == this.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 + ")";
+ }
+
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ throw new RuntimeException("unimplemented");
+ }
+
+
+ public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
+ //make this remap from formal positions to arrayIndices
+ IntMap entryBindings = new IntMap();
+ 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;
+
+ CrosscuttingMembers xcut = inAspect.crosscuttingMembers;
+ Collection previousCflowEntries = xcut.getCflowEntries();
+
+ entryBindings.pushEnclosingDefinition(CFLOW_MARKER);
+ try {
+ concreteEntry = entry.concretize(inAspect, entryBindings);
+ } finally {
+ entryBindings.popEnclosingDefinitition();
+ }
+
+ List innerCflowEntries = new ArrayList(xcut.getCflowEntries());
+ innerCflowEntries.removeAll(previousCflowEntries);
+
+
+ ResolvedMember cflowField = new ResolvedMember(
+ Member.FIELD, inAspect, Modifier.STATIC | Modifier.PUBLIC | Modifier.FINAL,
+ NameMangler.cflowStack(xcut),
+ TypeX.forName(NameMangler.CFLOW_STACK_TYPE).getSignature());
+
+ // 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
+ inAspect.crosscuttingMembers.addConcreteShadowMunger(
+ Advice.makeCflowEntry(world, concreteEntry, isBelow, cflowField, freeVars.length, innerCflowEntries));
+
+ inAspect.crosscuttingMembers.addTypeMunger(
+ world.makeCflowStackFieldAdder(cflowField));
+
+
+ List slots = new ArrayList();
+ for (int i=0, len=freeVars.length; i < len; i++) {
+ int freeVar = freeVars[i];
+ int formalIndex = bindings.get(freeVar);
+ ResolvedTypeX formalType =
+ bindings.getAdviceSignature().getParameterTypes()[formalIndex].resolve(world);
+
+ ConcreteCflowPointcut.Slot slot =
+ new ConcreteCflowPointcut.Slot(formalIndex, formalType, i);
+ slots.add(slot);
+ }
+
+ return new ConcreteCflowPointcut(cflowField, slots);
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java
new file mode 100644
index 000000000..3d3301b41
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java
@@ -0,0 +1,116 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.*;
+import java.util.List;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.weaver.bcel.BcelTypeMunger;
+import org.aspectj.util.*;
+
+
+public class ConcreteCflowPointcut extends Pointcut {
+ private Member cflowStackField;
+ List/*Slot*/ slots; // exposed for testing
+
+
+ public ConcreteCflowPointcut(Member cflowStackField, List slots) {
+ this.cflowStackField = cflowStackField;
+ this.slots = slots;
+ }
+
+ public FuzzyBoolean match(Shadow shadow) {
+ //??? this is not maximally efficient
+ return FuzzyBoolean.MAYBE;
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ throw new RuntimeException("unimplemented");
+ }
+
+
+ public void resolveBindings(IScope scope, Bindings bindings) {
+ throw new RuntimeException("unimplemented");
+ }
+
+
+ public boolean equals(Object other) {
+ if (!(other instanceof ConcreteCflowPointcut)) return false;
+ ConcreteCflowPointcut o = (ConcreteCflowPointcut)other;
+ return o.cflowStackField.equals(this.cflowStackField);
+ }
+ public int hashCode() {
+ int result = 17;
+ result = 37*result + cflowStackField.hashCode();
+ return result;
+ }
+ public String toString() {
+ return "concretecflow(" + cflowStackField + ")";
+ }
+
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ //System.out.println("find residue: " + this);
+ for (Iterator i = slots.iterator(); i.hasNext();) {
+ Slot slot = (Slot) i.next();
+ //System.out.println("slot: " + slot.formalIndex);
+ state.set(slot.formalIndex,
+ new BcelCflowAccessVar(slot.formalType, cflowStackField, slot.arrayIndex));
+ }
+
+ return Test.makeFieldGetCall(cflowStackField, cflowStackIsValidMethod, Expr.NONE);
+ }
+
+ private static final Member cflowStackIsValidMethod =
+ Member.method(TypeX.forName(NameMangler.CFLOW_STACK_TYPE), 0, "isValid", "()Z");
+
+
+ public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
+ throw new RuntimeException("unimplemented");
+ }
+
+
+ public static class Slot {
+ int formalIndex;
+ ResolvedTypeX formalType;
+ int arrayIndex;
+
+ public Slot(
+ int formalIndex,
+ ResolvedTypeX 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 String toString() {
+ return "Slot(" + formalIndex + ", " + formalType + ", " + arrayIndex + ")";
+ }
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/Declare.java b/weaver/src/org/aspectj/weaver/patterns/Declare.java
new file mode 100644
index 000000000..1dcb38bc0
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/Declare.java
@@ -0,0 +1,54 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.weaver.ISourceContext;
+
+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 Declare read(DataInputStream s, ISourceContext context) throws IOException {
+ byte kind = s.readByte();
+ switch (kind) {
+ case ERROR_OR_WARNING:
+ return DeclareErrorOrWarning.read(s, context);
+ case DOMINATES:
+ return DeclareDominates.read(s, context);
+ case PARENTS:
+ return DeclareParents.read(s, context);
+ case SOFT:
+ return DeclareSoft.read(s, context);
+ default:
+ throw new RuntimeException("unimplemented");
+ }
+ }
+
+ /**
+ * Returns this declare mutated
+ */
+ public abstract void resolve(IScope scope);
+
+ /**
+ * 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();
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/DeclareDominates.java b/weaver/src/org/aspectj/weaver/patterns/DeclareDominates.java
new file mode 100644
index 000000000..964f6659d
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/DeclareDominates.java
@@ -0,0 +1,110 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.util.List;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ResolvedTypeX;
+
+public class DeclareDominates extends Declare {
+ private TypePatternList patterns;
+
+
+ public DeclareDominates(List patterns) {
+ this(new TypePatternList(patterns));
+ }
+
+ private DeclareDominates(TypePatternList patterns) {
+ this.patterns = patterns;
+ }
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("declare dominates: ");
+ buf.append(patterns);
+ buf.append(";");
+ return buf.toString();
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof DeclareDominates)) return false;
+ DeclareDominates o = (DeclareDominates)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(DataInputStream s, ISourceContext context) throws IOException {
+ Declare ret = new DeclareDominates(TypePatternList.read(s, context));
+ ret.readLocation(context, s);
+ return ret;
+ }
+
+ public void resolve(IScope scope) {
+ patterns = patterns.resolveBindings(scope, Bindings.NONE, false);
+ }
+
+ public TypePatternList getPatterns() {
+ return patterns;
+ }
+
+ private int matchingIndex(ResolvedTypeX 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.matchesExactly(a)) {
+ if (knownMatch != -1) {
+ throw new BCException("multiple matches: " + this + " with " + a);
+ } else {
+ knownMatch = i;
+ }
+ }
+ }
+ if (knownMatch == -1) return starMatch;
+ else return knownMatch;
+ }
+
+
+ public int compare(ResolvedTypeX aspect1, ResolvedTypeX 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;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/DeclareErrorOrWarning.java b/weaver/src/org/aspectj/weaver/patterns/DeclareErrorOrWarning.java
new file mode 100644
index 000000000..f1e84cfa3
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/DeclareErrorOrWarning.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.weaver.ISourceContext;
+
+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;
+ }
+
+ 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 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(DataInputStream 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 boolean isAdviceLike() {
+ return true;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/DeclareParents.java b/weaver/src/org/aspectj/weaver/patterns/DeclareParents.java
new file mode 100644
index 000000000..d34d69ab1
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/DeclareParents.java
@@ -0,0 +1,100 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.util.List;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ResolvedTypeX;
+
+public class DeclareParents extends Declare {
+ private TypePattern child;
+ private TypePatternList parents;
+
+
+ public DeclareParents(TypePattern child, List parents) {
+ this(child, new TypePatternList(parents));
+ }
+
+ private DeclareParents(TypePattern child, TypePatternList parents) {
+ this.child = child;
+ this.parents = parents;
+ }
+
+ public boolean match(ResolvedTypeX typeX) {
+ return child.matchesStatically(typeX);
+ }
+
+
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("declare parents: ");
+ buf.append(child);
+ buf.append(" extends "); //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);
+ writeLocation(s);
+ }
+
+ public static Declare read(DataInputStream s, ISourceContext context) throws IOException {
+ Declare ret = new DeclareParents(TypePattern.read(s, context), TypePatternList.read(s, context));
+ ret.readLocation(context, s);
+ return ret;
+ }
+
+ public void resolve(IScope scope) {
+ child = child.resolveBindings(scope, Bindings.NONE, false);
+ parents = parents.resolveBindings(scope, Bindings.NONE, false);
+ for (int i=0; i < parents.size(); i++) {
+ parents.get(i).assertExactType(scope.getMessageHandler());
+ }
+ }
+
+ public TypePatternList getParents() {
+ return parents;
+ }
+
+ public TypePattern getChild() {
+ return child;
+ }
+
+ public boolean isAdviceLike() {
+ return false;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/DeclareSoft.java b/weaver/src/org/aspectj/weaver/patterns/DeclareSoft.java
new file mode 100644
index 000000000..b80c17a21
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/DeclareSoft.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.weaver.ISourceContext;
+
+public class DeclareSoft extends Declare {
+ private TypePattern exception;
+ private Pointcut pointcut;
+
+ public DeclareSoft(TypePattern exception, Pointcut pointcut) {
+ this.exception = exception;
+ this.pointcut = pointcut;
+ }
+
+ 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(DataInputStream 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);
+ pointcut = pointcut.resolve(scope);
+ }
+
+ public boolean isAdviceLike() {
+ return true;
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java
new file mode 100644
index 000000000..b98463ead
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.weaver.*;
+import org.aspectj.util.*;
+
+public class ExactTypePattern extends TypePattern {
+ protected TypeX type;
+
+ public ExactTypePattern(TypeX type, boolean includeSubtypes) {
+ super(includeSubtypes);
+ this.type = type;
+ }
+
+ protected boolean matchesExactly(ResolvedTypeX matchType) {
+ return this.type.equals(matchType);
+ }
+
+ public TypeX getType() { return type; }
+
+ public FuzzyBoolean matchesInstanceof(ResolvedTypeX matchType) {
+ // in our world, Object is assignable from anything
+ if (type.equals(ResolvedTypeX.OBJECT)) return FuzzyBoolean.YES;
+
+ if (type.isAssignableFrom(matchType, matchType.getWorld())) {
+ return FuzzyBoolean.YES;
+ }
+
+ return matchType.isCoerceableFrom(type) ? FuzzyBoolean.MAYBE : FuzzyBoolean.NO;
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof ExactTypePattern)) return false;
+ ExactTypePattern o = (ExactTypePattern)other;
+ return o.type.equals(this.type);
+ }
+
+ public int hashCode() {
+ return type.hashCode();
+ }
+
+ public void write(DataOutputStream out) throws IOException {
+ out.writeByte(TypePattern.EXACT);
+ type.write(out);
+ out.writeBoolean(includeSubtypes);
+ writeLocation(out);
+ }
+
+ public static TypePattern read(DataInputStream s, ISourceContext context) throws IOException {
+ TypePattern ret = new ExactTypePattern(TypeX.read(s), s.readBoolean());
+ ret.readLocation(context, s);
+ return ret;
+ }
+
+ public String toString() {
+ //Thread.currentThread().dumpStack();
+ return "ExactTypePattern(" + type.toString() + (includeSubtypes ? "+" : "") + ")";
+ }
+ public TypePattern resolveBindings(
+ IScope scope,
+ Bindings bindings,
+ boolean allowBinding)
+ {
+ throw new BCException("trying to re-resolve");
+
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/ExposedState.java b/weaver/src/org/aspectj/weaver/patterns/ExposedState.java
new file mode 100644
index 000000000..e5b35a03c
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/ExposedState.java
@@ -0,0 +1,57 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.util.Arrays;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+
+public class ExposedState {
+ public Var[] vars;
+ private Expr aspectInstance;
+
+ public ExposedState(int size) {
+ super();
+ vars = new Var[size];
+ }
+
+ public ExposedState(Member signature) {
+ // XXX there maybe something about target for non-static sigs
+ this(signature.getParameterTypes().length);
+ }
+
+ public void set(int i, Var var) {
+ //XXX add sanity checks
+ 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(" + Arrays.asList(vars) + ", " + aspectInstance + ")";
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/FormalBinding.java b/weaver/src/org/aspectj/weaver/patterns/FormalBinding.java
new file mode 100644
index 000000000..be34d4848
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/FormalBinding.java
@@ -0,0 +1,76 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.*;
+
+public class FormalBinding implements IHasPosition {
+ private final TypeX type;
+ private final String name;
+ private final int index;
+ private final int start, end;
+ private final String fileName;
+
+ public FormalBinding(TypeX type, String name, int index, int start, int end, String fileName) {
+ this.type = type;
+ this.name = name;
+ this.index = index;
+ this.start = start;
+ this.end = end;
+ this.fileName = fileName;
+ }
+
+ public FormalBinding(TypeX type, int index) {
+ this(type, "unknown", index, 0, 0, "unknown");
+ }
+
+ public FormalBinding(TypeX type, String name, int index) {
+ this(type, name, index, 0, 0, "unknown");
+ }
+
+ // ----
+
+ public String toString() {
+ return type.toString() + ":" + index;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public int getEnd() {
+ return end;
+ }
+
+ public int getStart() {
+ return start;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public TypeX getType() {
+ return type;
+ }
+
+ // ----
+
+ public static final FormalBinding[] NONE = new FormalBinding[0];
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java b/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java
new file mode 100644
index 000000000..4f9d16596
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java
@@ -0,0 +1,94 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.apache.bcel.classfile.JavaClass;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+
+/**
+ * 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;
+
+ public HandlerPointcut(TypePattern exceptionType) {
+ this.exceptionType = exceptionType;
+ }
+
+
+ public FuzzyBoolean match(Shadow shadow) {
+ if (shadow.getKind() != Shadow.ExceptionHandler) return FuzzyBoolean.NO;
+
+ // 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 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(DataInputStream 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);
+ //XXX add error if exact binding and not an exception
+ }
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
+ }
+
+ public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
+ return new HandlerPointcut(exceptionType);
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/IScope.java b/weaver/src/org/aspectj/weaver/patterns/IScope.java
new file mode 100644
index 000000000..d815326cd
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/IScope.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.*;
+import org.aspectj.bridge.*;
+import org.aspectj.bridge.IMessageHandler;
+
+public interface IScope {
+
+ /** returns the type corresponding to the name in this scope
+ * returns ResolvedTypeX.MISSING if no such type exists and reports a problem
+ */
+ TypeX lookupType(String name, IHasPosition location);
+
+ World getWorld();
+
+ ResolvedTypeX 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);
+
+ //ISourceLocation makeSourceLocation(ILocation location);
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/IToken.java b/weaver/src/org/aspectj/weaver/patterns/IToken.java
new file mode 100644
index 000000000..e7403287a
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/IToken.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.*;
+
+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/weaver/src/org/aspectj/weaver/patterns/ITokenSource.java b/weaver/src/org/aspectj/weaver/patterns/ITokenSource.java
new file mode 100644
index 000000000..4410e60d8
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/ITokenSource.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/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/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java b/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java
new file mode 100644
index 000000000..8a5d54ea9
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.util.*;
+import java.util.List;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.*;
+
+
+public class IfPointcut extends Pointcut {
+ public ResolvedMember testMethod;
+ public int extraParameterFlags;
+
+ public Pointcut residueSource;
+ int baseArgsCount;
+
+ //XXX some way to compute args
+
+
+ public IfPointcut(ResolvedMember testMethod, int extraParameterFlags) {
+ this.testMethod = testMethod;
+ this.extraParameterFlags = extraParameterFlags;
+ }
+
+ public FuzzyBoolean match(Shadow shadow) {
+ //??? this is not maximally efficient
+ return FuzzyBoolean.MAYBE;
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ s.writeByte(Pointcut.IF);
+ testMethod.write(s);
+ s.writeByte(extraParameterFlags);
+ writeLocation(s);
+ }
+ public static Pointcut read(DataInputStream s, ISourceContext context) throws IOException {
+ IfPointcut ret = new IfPointcut(ResolvedMember.readResolvedMember(s, context), 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;
+ return o.testMethod.equals(this.testMethod);
+ }
+ public int hashCode() {
+ int result = 17;
+ result = 37*result + testMethod.hashCode();
+ return result;
+ }
+ public String toString() {
+ return "if(" + testMethod + ")";
+ }
+
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ if (residueSource == null) return Literal.TRUE; //???
+
+ ExposedState myState = new ExposedState(baseArgsCount);
+ //System.out.println(residueSource);
+ residueSource.findResidue(shadow, myState); // don't care about Test
+
+ //System.out.println(myState);
+
+ List args = new ArrayList();
+ for (int i=0; i < baseArgsCount; i++) {
+ args.add(myState.get(i));
+ }
+
+ // 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());
+ }
+
+ return Test.makeCall(testMethod, (Expr[])args.toArray(new Expr[args.size()]));
+ }
+
+
+ public Pointcut concretize(ResolvedTypeX inAspect, IntMap bindings) {
+ return this.concretize1(inAspect, bindings);
+ }
+
+ public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
+ IfPointcut ret = new IfPointcut(testMethod, extraParameterFlags);
+ if (this.state == CONCRETE) return ret;
+ this.state = CONCRETE;
+ if (bindings.directlyInAdvice()) {
+ Advice advice = bindings.getEnclosingAdvice();
+ ret.baseArgsCount = advice.getBaseParameterCount();
+ ret.residueSource = advice.getPointcut().concretize(inAspect, ret.baseArgsCount, advice);
+ } else {
+ ResolvedPointcutDefinition def = bindings.peekEnclosingDefinitition();
+ if (def == CflowPointcut.CFLOW_MARKER) {
+ inAspect.getWorld().getMessageHandler().handleMessage(
+ MessageUtil.error("if not supported lexically within cflow (compiler limitation)",
+ null));
+ return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+ }
+ ret.baseArgsCount = def.getParameterTypes().length;
+
+ IntMap newBindings = IntMap.idMap(ret.baseArgsCount);
+ newBindings.copyContext(bindings);
+ ret.residueSource = def.getPointcut().concretize(inAspect, newBindings);
+ }
+
+ return ret;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java b/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java
new file mode 100644
index 000000000..2720596f5
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java
@@ -0,0 +1,115 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.apache.bcel.classfile.JavaClass;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+
+public class KindedPointcut extends Pointcut {
+ Shadow.Kind kind;
+ SignaturePattern signature;
+
+ public KindedPointcut(
+ Shadow.Kind kind,
+ SignaturePattern signature) {
+ this.kind = kind;
+ this.signature = signature;
+ }
+
+ public boolean fastMatch(JavaClass jc) { return true; }
+
+ public FuzzyBoolean match(Shadow shadow) {
+
+
+ if (shadow.getKind() != kind) return FuzzyBoolean.NO;
+
+ if (!signature.matches(shadow.getSignature(), shadow.getIWorld())) return FuzzyBoolean.NO;
+
+ return FuzzyBoolean.YES;
+ }
+
+ 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(ResolvedTypeX 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(DataInputStream 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);
+ }
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
+ }
+
+ public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
+ return new KindedPointcut(kind, signature);
+ //return this; //??? no pointers out of here so we're okay
+ }
+
+ public Shadow.Kind getKind() {
+ return kind;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/ModifiersPattern.java b/weaver/src/org/aspectj/weaver/patterns/ModifiersPattern.java
new file mode 100644
index 000000000..dc146a0ef
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/ModifiersPattern.java
@@ -0,0 +1,92 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+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(DataInputStream 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();
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/NameBindingPointcut.java b/weaver/src/org/aspectj/weaver/patterns/NameBindingPointcut.java
new file mode 100644
index 000000000..0a043ad51
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/NameBindingPointcut.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+
+/**
+ * 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);
+ }
+ TypeX myType = type.getExactType(); //should have failed earlier
+
+ return Test.makeInstanceof(var, myType.resolve(world));
+ }
+
+
+
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/NamePattern.java b/weaver/src/org/aspectj/weaver/patterns/NamePattern.java
new file mode 100644
index 000000000..043376fc1
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/NamePattern.java
@@ -0,0 +1,158 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+public class NamePattern extends PatternNode {
+ char[] pattern;
+ int starCount = 0;
+
+ 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++;
+ }
+ }
+
+ 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;
+ return otherPat.starCount == this.starCount &&
+ new String(otherPat.pattern).equals(new String(this.pattern));
+ }
+ return false;
+ }
+ public int hashCode() {
+ return new String(pattern).hashCode();
+ }
+
+
+ public void write(DataOutputStream out) throws IOException {
+ out.writeUTF(new String(pattern));
+ }
+
+ public static NamePattern read(DataInputStream 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;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java b/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java
new file mode 100644
index 000000000..64b919f69
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java
@@ -0,0 +1,96 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.util.*;
+
+public class NotPointcut extends Pointcut {
+ private Pointcut body;
+ public NotPointcut(Pointcut left) {
+ super();
+ this.body = left;
+ }
+
+ /**
+ * Constructor NotPointcut.
+ * @param pointcut
+ * @param startPos
+ */
+ public NotPointcut(Pointcut pointcut, int startPos) {
+ this(pointcut);
+ setLocation(pointcut.getSourceContext(), startPos, pointcut.getEnd());
+ }
+
+
+ /**
+ * @see org.aspectj.weaver.patterns.Pointcut#match(BcelShadow)
+ */
+ public FuzzyBoolean match(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(DataInputStream s, ISourceContext context) throws IOException {
+ NotPointcut ret = new NotPointcut(Pointcut.read(s, context));
+ ret.readLocation(context, s);
+ return ret;
+ }
+
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ return Test.makeNot(body.findResidue(shadow, state));
+ }
+
+ public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
+ return new NotPointcut(body.concretize1(inAspect, bindings));
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java
new file mode 100644
index 000000000..f62d693c7
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ResolvedTypeX;
+
+/**
+ * !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 pattern;
+
+ public NotTypePattern(TypePattern pattern) {
+ super(false); //??? we override all methods that care about includeSubtypes
+ this.pattern = pattern;
+ setLocation(pattern.getSourceContext(), pattern.getStart(), pattern.getEnd());
+ }
+
+ public FuzzyBoolean matchesInstanceof(ResolvedTypeX type) {
+ return pattern.matchesInstanceof(type).not();
+ }
+
+ protected boolean matchesExactly(ResolvedTypeX type) {
+ return !pattern.matchesExactly(type);
+ }
+
+ public boolean matchesStatically(ResolvedTypeX type) {
+ return !pattern.matchesStatically(type);
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ s.writeByte(TypePattern.NOT);
+ pattern.write(s);
+ writeLocation(s);
+ }
+
+ public static TypePattern read(DataInputStream s, ISourceContext context) throws IOException {
+ TypePattern ret = new NotTypePattern(TypePattern.read(s, context));
+ ret.readLocation(context, s);
+ return ret;
+ }
+
+ public TypePattern resolveBindings(
+ IScope scope,
+ Bindings bindings,
+ boolean allowBinding) {
+ pattern = pattern.resolveBindings(scope, bindings, false);
+ return this;
+ }
+
+ public String toString() {
+ return "!" + pattern;
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java b/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java
new file mode 100644
index 000000000..fc389acaf
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.util.*;
+
+public class OrPointcut extends Pointcut {
+ private Pointcut left, right;
+ /**
+ * Constructor for AndPointcut.
+ */
+ public OrPointcut(Pointcut left, Pointcut right) {
+ super();
+ this.left = left;
+ this.right = right;
+ setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
+ }
+
+ /**
+ * @see org.aspectj.weaver.patterns.Pointcut#match(BcelShadow)
+ */
+ public FuzzyBoolean match(Shadow shadow) {
+ return left.match(shadow).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(DataInputStream s, ISourceContext context) throws IOException {
+ OrPointcut ret = new OrPointcut(Pointcut.read(s, context), Pointcut.read(s, context));
+ ret.readLocation(context, s);
+ return ret;
+
+ }
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ return Test.makeOr(left.findResidue(shadow, state), right.findResidue(shadow, state));
+ }
+
+ public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
+ return new OrPointcut(left.concretize1(inAspect, bindings),
+ right.concretize1(inAspect, bindings));
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java
new file mode 100644
index 000000000..6cb043bc5
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java
@@ -0,0 +1,79 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ResolvedTypeX;
+
+/**
+ * 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); //??? we override all methods that care about includeSubtypes
+ this.left = left;
+ this.right = right;
+ setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
+ }
+
+ public FuzzyBoolean matchesInstanceof(ResolvedTypeX type) {
+ return left.matchesInstanceof(type).or(right.matchesInstanceof(type));
+ }
+
+ protected boolean matchesExactly(ResolvedTypeX type) {
+ //??? if these had side-effects, this sort-circuit could be a mistake
+ return left.matchesExactly(type) || right.matchesExactly(type);
+ }
+
+ public boolean matchesStatically(ResolvedTypeX type) {
+ return left.matchesStatically(type) || right.matchesStatically(type);
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ s.writeByte(TypePattern.OR);
+ left.write(s);
+ right.write(s);
+ writeLocation(s);
+ }
+
+ public static TypePattern read(DataInputStream s, ISourceContext context) throws IOException {
+ TypePattern ret = new OrTypePattern(TypePattern.read(s, context), TypePattern.read(s, context));
+ ret.readLocation(context, s);
+ return ret;
+ }
+
+ public TypePattern resolveBindings(
+ IScope scope,
+ Bindings bindings,
+ boolean allowBinding) {
+ left = left.resolveBindings(scope, bindings, false);
+ right = right.resolveBindings(scope, bindings, false);
+ return this;
+ }
+
+ public String toString() {
+ return "(" + left.toString() + " || " + right.toString() + ")";
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/ParserException.java b/weaver/src/org/aspectj/weaver/patterns/ParserException.java
new file mode 100644
index 000000000..af6f0cb49
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/ParserException.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.*;
+
+
+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/weaver/src/org/aspectj/weaver/patterns/PatternNode.java b/weaver/src/org/aspectj/weaver/patterns/PatternNode.java
new file mode 100644
index 000000000..4c09ad4b7
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/PatternNode.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.bridge.*;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.weaver.*;
+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;
+ }
+
+ public int getEnd() {
+ return end;
+ }
+
+ 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;
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java
new file mode 100644
index 000000000..eaeb71f20
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java
@@ -0,0 +1,781 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.util.*;
+
+import org.aspectj.weaver.*;
+
+//XXX doesn't handle errors for extra tokens very well (sometimes ignores)
+public class PatternParser {
+ private ITokenSource tokenSource;
+
+ private ISourceContext sourceContext;
+
+ /**
+ * Constructor for PatternParser.
+ */
+ public PatternParser(ITokenSource tokenSource) {
+ super();
+ this.tokenSource = tokenSource;
+ this.sourceContext = tokenSource.getSourceContext();
+ }
+
+ 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 {
+ 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 parsePerSingleton() {
+ parseIdentifier();
+ eat("(");
+ eat(")");
+ return new PerSingleton();
+ }
+
+
+ public Declare parseDeclare() {
+ int startPos = tokenSource.peek().getStart();
+
+ eatIdentifier("declare");
+ String kind = parseIdentifier();
+ eat(":");
+ Declare ret;
+ //XXX beta add soft, dominates
+ if (kind.equals("error")) {
+ ret = parseErrorOrWarning(true);
+ } else if (kind.equals("warning")) {
+ ret = parseErrorOrWarning(false);
+ } else if (kind.equals("dominates")) {
+ ret = parseDominates();
+ } else if (kind.equals("parents")) {
+ ret = parseParents();
+ } else if (kind.equals("soft")) {
+ ret = parseSoft();
+ } else {
+ throw new ParserException("expected one of error, warning, parents, soft, dominates",
+ tokenSource.peek(-1));
+ }
+ int endPos = tokenSource.peek(-1).getEnd();
+ ret.setLocation(sourceContext, startPos, endPos);
+ return ret;
+ }
+
+ public DeclareDominates parseDominates() {
+ List l = new ArrayList();
+ do {
+ l.add(parseTypePattern());
+ } while (maybeEat(","));
+
+ return new DeclareDominates(l);
+ }
+
+ private Declare parseParents() {
+ TypePattern p = parseTypePattern();
+ IToken t = tokenSource.next();
+ if (!(t.getString().equals("extends") || t.getString().equals("implements"))) {
+ throw new ParserException("extends or implements", t);
+ }
+
+ List l = new ArrayList();
+ do {
+ l.add(parseTypePattern());
+ } while (maybeEat(","));
+
+ //XXX somewhere in the chain we need to enforce that we have only ExactTypePatterns
+
+ return new DeclareParents(p, l);
+ }
+
+ 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 = parseStringLiteral();
+ 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;
+ }
+ 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();
+ tokenSource.setIndex(start);
+ if (kind.equals("execution") || kind.equals("call") ||
+ kind.equals("get") || kind.equals("set")) {
+ return parseKindedPointcut();
+ } else if (kind.equals("args")) {
+ return parseArgsPointcut();
+ } else if (kind.equals("this") || kind.equals("target")) {
+ return parseThisOrTargetPointcut();
+ } else if (kind.equals("within")) {
+ return parseWithinPointcut();
+ } else if (kind.equals("withincode")) {
+ return parseWithinCodePointcut();
+ } else if (kind.equals("cflow")) {
+ return parseCflowPointcut(false);
+ } else if (kind.equals("cflowbelow")) {
+ return parseCflowPointcut(true);
+ } else if (kind.equals("adviceexecution")) {
+ parseIdentifier(); eat("(");
+ eat(")");
+ return new KindedPointcut(Shadow.AdviceExecution,
+ new SignaturePattern(Member.ADVICE, ModifiersPattern.ANY,
+ TypePattern.ANY, TypePattern.ANY, NamePattern.ANY,
+ TypePatternList.ANY,
+ ThrowsPattern.ANY));
+ } else if (kind.equals("handler")) {
+ parseIdentifier(); eat("(");
+ TypePattern typePat = parseTypePattern();
+ eat(")");
+ return new HandlerPointcut(typePat);
+ } else if (kind.equals("initialization")) {
+ parseIdentifier(); eat("(");
+ SignaturePattern sig = parseConstructorSignaturePattern();
+ eat(")");
+ return new KindedPointcut(Shadow.Initialization, sig);
+ } else if (kind.equals("staticinitialization")) {
+ parseIdentifier(); eat("(");
+ TypePattern typePat = parseTypePattern();
+ eat(")");
+ return new KindedPointcut(Shadow.StaticInitialization,
+ new SignaturePattern(Member.STATIC_INITIALIZATION, ModifiersPattern.ANY,
+ TypePattern.ANY, typePat, NamePattern.ANY, TypePatternList.EMPTY,
+ ThrowsPattern.ANY));
+ } else if (kind.equals("preinitialization")) {
+ parseIdentifier(); eat("(");
+ SignaturePattern sig = parseConstructorSignaturePattern();
+ eat(")");
+ return new KindedPointcut(Shadow.PreInitialization, sig);
+ } else {
+ return parseReferencePointcut();
+ }
+ }
+
+ 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 = parseIdentifier();
+ eat("(");
+ TypePattern type = parseTypePattern();
+ eat(")");
+ return new ThisOrTargetPointcut(kind.equals("this"), type);
+ }
+
+
+ /**
+ * Method parseArgsPointcut.
+ * @return Pointcut
+ */
+ private Pointcut parseArgsPointcut() {
+ parseIdentifier();
+ TypePatternList arguments = parseArgumentsPattern();
+ return new ArgsPointcut(arguments);
+ }
+
+
+ private Pointcut parseReferencePointcut() {
+ TypePattern onType = parseTypePattern();
+ NamePattern name = tryToExtractName(onType);
+ if (name == null) {
+ throw new ParserException("name pattern", tokenSource.peek());
+ }
+ if (onType.toString().equals("")) {
+ onType = null;
+ }
+
+ TypePatternList arguments = parseArgumentsPattern();
+ return new ReferencePointcut(onType, name.maybeGetSimpleName(), arguments);
+ }
+
+
+ public List parseDottedIdentifier() {
+ List ret = new ArrayList();
+ ret.add(parseIdentifier());
+ while (maybeEat(".")) {
+ ret.add(parseIdentifier());
+ }
+ return ret;
+ }
+
+
+
+ private KindedPointcut parseKindedPointcut() {
+ String kind = parseIdentifier();
+ 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);
+ }
+
+ public TypePattern parseTypePattern() {
+ TypePattern p = parseAtomicTypePattern();
+ if (maybeEat("&&")) {
+ p = new AndTypePattern(p, parseNotOrTypePattern());
+ }
+
+ if (maybeEat("||")) {
+ p = new OrTypePattern(p, parseTypePattern());
+ }
+ return p;
+ }
+
+ private TypePattern parseNotOrTypePattern() {
+ TypePattern p = parseAtomicTypePattern();
+ if (maybeEat("&&")) {
+ p = new AndTypePattern(p, parseTypePattern());
+ }
+ return p;
+ }
+
+ private TypePattern parseAtomicTypePattern() {
+ if (maybeEat("!")) {
+ int startPos = tokenSource.peek(-1).getStart();
+ //??? we lose source location for true start of !type
+ TypePattern p = new NotTypePattern(parseAtomicTypePattern());
+ return p;
+ }
+ if (maybeEat("(")) {
+ TypePattern p = parseTypePattern();
+ eat(")");
+ return p;
+ }
+ int startPos = tokenSource.peek().getStart();
+ TypePattern p = parseSingleTypePattern();
+ int endPos = tokenSource.peek(-1).getEnd();
+ p.setLocation(sourceContext, startPos, endPos);
+ return p;
+ }
+
+ public TypePattern parseSingleTypePattern() {
+ List names = parseDottedNamePattern();
+// new ArrayList();
+// NamePattern p1 = parseNamePattern();
+// names.add(p1);
+// while (maybeEat(".")) {
+// if (maybeEat(".")) {
+// names.add(NamePattern.ELLIPSIS);
+// }
+// NamePattern p2 = parseNamePattern();
+// names.add(p2);
+// }
+ int dim = 0;
+ while (maybeEat("[")) {
+ eat("]");
+ dim++;
+ }
+
+
+ boolean includeSubtypes = maybeEat("+");
+ int endPos = tokenSource.peek(-1).getEnd();
+
+ //??? what about the source location of any's????
+ if (names.size() == 1 && ((NamePattern)names.get(0)).isAny() && dim == 0) return TypePattern.ANY;
+
+ return new WildTypePattern(names, includeSubtypes, dim, endPos);
+ }
+
+ public List parseDottedNamePattern() {
+ List names = new ArrayList();
+ StringBuffer buf = new StringBuffer();
+ IToken previous = null;
+ while (true) {
+ IToken tok;
+ int startPos = tokenSource.peek().getStart();
+ String afterDot = null;
+ 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();
+ 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("expected name pattern", tok);
+ }
+
+ if (buf.length() == 0) {
+ names.add(NamePattern.ELLIPSIS);
+ } else {
+ checkLegalName(buf.toString(), previous);
+ NamePattern ret = new NamePattern(buf.toString());
+ ret.setLocation(sourceContext, startPos, endPos);
+ names.add(ret);
+ }
+
+ if (afterDot == null) {
+ buf.setLength(0);
+ if (!maybeEat(".")) break;
+ else previous = tokenSource.peek(-1);
+ } else {
+ buf.setLength(0);
+ buf.append(afterDot);
+ afterDot = null;
+ }
+ }
+ //System.err.println("parsed: " + names);
+ return names;
+ }
+
+
+
+ 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("expected 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() {
+ List patterns = new ArrayList();
+ eat("(");
+ if (maybeEat(")")) {
+ return new TypePatternList();
+ }
+
+ do {
+ if (maybeEat(".")) {
+ eat(".");
+ patterns.add(TypePattern.ELLIPSIS);
+ } else {
+ patterns.add(parseTypePattern());
+ }
+ } while (maybeEat(","));
+ eat(")");
+ return new TypePatternList(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() {
+ ModifiersPattern modifiers = parseModifiersPattern();
+ TypePattern returnType = parseTypePattern();
+
+ TypePattern declaringType;
+ NamePattern name = null;
+ Member.Kind 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;
+ declaringType = parseTypePattern();
+ if (maybeEat(".")) {
+ name = parseNamePattern();
+ } else {
+ name = tryToExtractName(declaringType);
+ 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("constructor patterns have no return type",
+ tokenSource.peek());
+ }
+ if (declaringType.toString().equals("")) {
+ declaringType = declaringType.ANY;
+ }
+ }
+ }
+
+ TypePatternList parameterTypes = parseArgumentsPattern();
+
+ ThrowsPattern throwsPattern = parseOptionalThrowsPattern();
+
+ return new SignaturePattern(kind, modifiers, returnType, declaringType, name, parameterTypes, throwsPattern);
+ }
+
+ 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() {
+ 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 (declaringType.toString().equals("")) {
+ declaringType = declaringType.ANY;
+ }
+ }
+ return new SignaturePattern(Member.FIELD, modifiers, returnType,
+ declaringType, name, TypePatternList.ANY, ThrowsPattern.ANY);
+ }
+
+
+ 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;
+ }
+ }
+
+ 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) {
+ IToken next = tokenSource.next();
+ if (next.getString() != expectedValue) {
+ throw new ParserException(expectedValue, next);
+ }
+ }
+
+ 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 PatternParser(String data) {
+ this(BasicTokenSource.makeTokenSource(data));
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/PerCflow.java b/weaver/src/org/aspectj/weaver/patterns/PerCflow.java
new file mode 100644
index 000000000..35614041a
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/PerCflow.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.*;
+import java.util.List;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.util.FuzzyBoolean;
+
+public class PerCflow extends PerClause {
+ private boolean isBelow;
+ private Pointcut entry;
+
+ public PerCflow(Pointcut entry, boolean isBelow) {
+ this.entry = entry;
+ this.isBelow = isBelow;
+ }
+
+ // -----
+
+ public FuzzyBoolean match(Shadow shadow) {
+ return FuzzyBoolean.YES;
+ }
+
+ public void resolveBindings(IScope scope, Bindings bindings) {
+ // assert bindings == null;
+ entry.resolve(scope);
+ }
+
+ public Test findResidue(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(ResolvedTypeX inAspect) {
+ PerCflow ret = new PerCflow(entry, isBelow);
+ ret.inAspect = inAspect;
+ if (inAspect.isAbstract()) return ret;
+
+ Member cflowStackField = new ResolvedMember(
+ Member.FIELD, inAspect, Modifier.STATIC|Modifier.PUBLIC|Modifier.FINAL,
+ TypeX.forName(NameMangler.CFLOW_STACK_TYPE), NameMangler.PERCFLOW_FIELD_NAME, TypeX.NONE);
+
+ World world = inAspect.getWorld();
+
+ CrosscuttingMembers xcut = inAspect.crosscuttingMembers;
+
+ Collection previousCflowEntries = xcut.getCflowEntries();
+ Pointcut concreteEntry = entry.concretize(inAspect, IntMap.EMPTY);
+ List innerCflowEntries = new ArrayList(xcut.getCflowEntries());
+ innerCflowEntries.removeAll(previousCflowEntries);
+
+ xcut.addConcreteShadowMunger(
+ Advice.makePerCflowEntry(world, concreteEntry, isBelow, cflowStackField,
+ inAspect, innerCflowEntries));
+ return ret;
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ PERCFLOW.write(s);
+ entry.write(s);
+ s.writeBoolean(isBelow);
+ writeLocation(s);
+ }
+
+ public static PerClause readPerClause(DataInputStream 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 String toString() {
+ return "percflow(" + inAspect + " on " + entry + ")";
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/PerClause.java b/weaver/src/org/aspectj/weaver/patterns/PerClause.java
new file mode 100644
index 000000000..7ff029818
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/PerClause.java
@@ -0,0 +1,67 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.List;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.Test;
+import org.aspectj.util.*;
+import org.aspectj.util.FuzzyBoolean;
+
+public abstract class PerClause extends Pointcut {
+ protected ResolvedTypeX inAspect;
+
+ public static PerClause readPerClause(DataInputStream 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);
+
+ throw new BCException("unknown kind: " + kind);
+ }
+
+ public final Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
+ throw new RuntimeException("unimplemented: wrong concretize");
+ }
+
+ public abstract PerClause concretize(ResolvedTypeX inAspect);
+
+
+ public abstract PerClause.Kind getKind();
+
+
+ public static class Kind extends TypeSafeEnum {
+ public 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 SINGLETON;
+ case 2: return PERCFLOW;
+ case 3: return PEROBJECT;
+ case 4: return FROMSUPER;
+ }
+ 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);
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/PerFromSuper.java b/weaver/src/org/aspectj/weaver/patterns/PerFromSuper.java
new file mode 100644
index 000000000..e0fa53166
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/PerFromSuper.java
@@ -0,0 +1,94 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+
+public class PerFromSuper extends PerClause {
+ private PerClause.Kind kind;
+
+ public PerFromSuper(PerClause.Kind kind) {
+ this.kind = kind;
+ }
+
+ public FuzzyBoolean match(Shadow shadow) {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public void resolveBindings(IScope scope, Bindings bindings) {
+ // this method intentionally left blank
+ }
+
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ throw new RuntimeException("unimplemented");
+ }
+
+
+ public PerClause concretize(ResolvedTypeX inAspect) {
+ PerClause p = lookupConcretePerClause(inAspect.getSuperclass());
+ if (p == null) {
+ inAspect.getWorld().getMessageHandler().handleMessage(
+ MessageUtil.error("expected per clause on super aspect not found on " +
+ inAspect.getSuperclass(), getSourceLocation())
+ );
+ }
+ if (p.getKind() != kind) {
+ inAspect.getWorld().getMessageHandler().handleMessage(
+ MessageUtil.error("wrong kind of per clause on super, expected " +
+ kind + " but found " + p.getKind(),
+ getSourceLocation())
+ );
+ }
+ return p.concretize(inAspect);
+ }
+
+
+
+ private PerClause lookupConcretePerClause(ResolvedTypeX 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(DataInputStream 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 PerClause.Kind getKind() {
+ return kind;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/PerObject.java b/weaver/src/org/aspectj/weaver/patterns/PerObject.java
new file mode 100644
index 000000000..de73e7066
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/PerObject.java
@@ -0,0 +1,104 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.*;
+import java.util.List;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.util.FuzzyBoolean;
+
+public class PerObject extends PerClause {
+ private boolean isThis;
+ private Pointcut entry;
+
+ public PerObject(Pointcut entry, boolean isThis) {
+ this.entry = entry;
+ this.isThis = isThis;
+ }
+
+ // -----
+
+ public FuzzyBoolean match(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);
+ }
+
+ private Var getVar(Shadow shadow) {
+ return isThis ? shadow.getThisVar() : shadow.getTargetVar();
+ }
+
+ public Test findResidue(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(ResolvedTypeX inAspect) {
+ PerObject ret = new PerObject(entry, isThis);
+
+ ret.inAspect = inAspect;
+ if (inAspect.isAbstract()) return ret;
+
+
+ World world = inAspect.getWorld();
+
+ Pointcut concreteEntry = entry.concretize(inAspect, IntMap.EMPTY);
+ //concreteEntry = new AndPointcut(this, concreteEntry);
+ //concreteEntry.state = Pointcut.CONCRETE;
+ inAspect.crosscuttingMembers.addConcreteShadowMunger(
+ Advice.makePerObjectEntry(world, concreteEntry, isThis, inAspect));
+ ResolvedTypeMunger munger =
+ new PerObjectInterfaceTypeMunger(inAspect, concreteEntry);
+ inAspect.crosscuttingMembers.addTypeMunger(world.concreteTypeMunger(munger, 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(DataInputStream 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 String toString() {
+ return "per" + (isThis ? "this" : "target") +
+ "(" + entry + ")";
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java b/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java
new file mode 100644
index 000000000..e95065ece
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java
@@ -0,0 +1,68 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.util.FuzzyBoolean;
+
+public class PerSingleton extends PerClause {
+ public PerSingleton() {
+ }
+
+ public FuzzyBoolean match(Shadow shadow) {
+ return FuzzyBoolean.YES;
+ }
+
+ public void resolveBindings(IScope scope, Bindings bindings) {
+ // this method intentionally left blank
+ }
+
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ state.setAspectInstance(
+ Expr.makeFieldGet(AjcMemberMaker.perSingletonField(inAspect), inAspect));
+ // XXX we need to think about whether it's null...
+ return Literal.TRUE;
+ }
+
+ public PerClause concretize(ResolvedTypeX inAspect) {
+ PerSingleton ret = new PerSingleton();
+ ret.inAspect = inAspect;
+ return ret;
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ SINGLETON.write(s);
+ writeLocation(s);
+ }
+
+ public static PerClause readPerClause(DataInputStream 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 + ")";
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/Pointcut.java b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java
new file mode 100644
index 000000000..99f7f6bc8
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java
@@ -0,0 +1,228 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.util.Map;
+
+import org.apache.bcel.classfile.*;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.util.*;
+
+/**
+ * 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
+ */
+public abstract class Pointcut extends PatternNode {
+ public static final class State extends TypeSafeEnum {
+ public State(String name, int key) {
+ super(name, key);
+ }
+ }
+
+ 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);
+
+
+ public State state;
+
+ /**
+ * Constructor for Pattern.
+ */
+ public Pointcut() {
+ super();
+ this.state = SYMBOLIC;
+ }
+
+
+ /**
+ * Could I match any shadows in this JavaClass
+ */
+ public boolean fastMatch(JavaClass jc) { return true; }
+
+ /**
+ * Do I really match this shadow?
+ * XXX implementors need to handle state
+ */
+ public abstract FuzzyBoolean match(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 NONE = 20;
+
+
+ // internal, only called from resolve
+ protected abstract void resolveBindings(IScope scope, Bindings bindings);
+
+ /**
+ * Returns this pointcut mutated
+ */
+ public Pointcut resolve(IScope scope) {
+ assertState(SYMBOLIC);
+ Bindings bindingTable = new Bindings(scope.getFormalCount());
+ this.resolveBindings(scope, bindingTable);
+ bindingTable.checkAllBound(scope);
+ this.state = RESOLVED;
+ return this;
+ }
+
+ /**
+ * Returns a new pointcut
+ */
+ public Pointcut concretize(ResolvedTypeX inAspect, int arity) {
+ return concretize(inAspect, IntMap.idMap(arity));
+ }
+
+
+ //XXX this is the signature we're moving to
+ public Pointcut concretize(ResolvedTypeX inAspect, int arity, Advice advice) {
+ //if (state == CONCRETE) return this; //???
+ IntMap map = IntMap.idMap(arity);
+ map.setEnclosingAdvice(advice);
+ return concretize(inAspect, map);
+ }
+
+
+
+ public Pointcut concretize(ResolvedTypeX inAspect, IntMap bindings) {
+ assertState(RESOLVED);
+ Pointcut ret = this.concretize1(inAspect, bindings);
+ ret.state = CONCRETE;
+ return ret;
+ }
+
+
+ /**
+ * 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
+ *
+ * ??? does this return a new pointcut
+ * XXX fix implementors to handle state
+ */
+ protected abstract Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings);
+
+
+ //XXX implementors need to handle state
+ /**
+ * This can be called from NotPointcut even for Pointcuts that
+ * don't match the shadow
+ */
+ public abstract Test findResidue(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(ResolvedTypeX enclosingType) {}
+
+ public static Pointcut read(DataInputStream 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 NONE: ret = makeMatchesNothing(RESOLVED); break;
+ default:
+ throw new BCException("unknown kind: " + kind);
+ }
+ ret.state = RESOLVED;
+ return ret;
+ }
+
+
+ //public void prepare(Shadow shadow) {}
+
+ // ---- test method
+
+ public static Pointcut fromString(String str) {
+ PatternParser parser = new PatternParser(str);
+ return parser.parsePointcut();
+ }
+
+ private static class MatchesNothingPointcut extends Pointcut {
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ return Literal.FALSE; // can only get here if an earlier error occurred
+ }
+
+ public FuzzyBoolean match(Shadow shadow) {
+ return FuzzyBoolean.NO;
+ }
+
+ public void resolveBindings(IScope scope, Bindings bindings) {
+ }
+
+ public void postRead(ResolvedTypeX enclosingType) {
+ }
+
+ public Pointcut concretize1(
+ ResolvedTypeX inAspect,
+ IntMap bindings) {
+ return this;
+ }
+
+
+ public void write(DataOutputStream s) throws IOException {
+ s.writeByte(NONE);
+ }
+
+ public String toString() { return ""; }
+ }
+
+ //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);
+ }
+ }
+
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java b/weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java
new file mode 100644
index 000000000..518172ed5
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java
@@ -0,0 +1,266 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.*;
+import java.util.Map;
+
+import org.apache.bcel.classfile.*;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.bridge.*;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.*;
+
+/**
+ */
+
+//XXX needs check that arguments contains no WildTypePatterns
+public class ReferencePointcut extends Pointcut {
+ public TypeX onType;
+ public TypePattern onTypeSymbolic;
+ public String name;
+ public TypePatternList arguments;
+
+ //public ResolvedPointcut binding;
+
+ public ReferencePointcut(TypePattern onTypeSymbolic, String name, TypePatternList arguments) {
+ this.onTypeSymbolic = onTypeSymbolic;
+ this.name = name;
+ this.arguments = arguments;
+ }
+
+ public ReferencePointcut(TypeX onType, String name, TypePatternList arguments) {
+ this.onType = onType;
+ this.name = name;
+ this.arguments = arguments;
+ }
+
+ /**
+ * Could I match any shadows in this JavaClass
+ */
+ public boolean fastMatch(JavaClass jc) { return true; }
+
+ /**
+ * Do I really match this shadow?
+ */
+ public FuzzyBoolean match(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(DataInputStream s, ISourceContext context) throws IOException {
+ TypeX onType = null;
+ if (s.readBoolean()) {
+ onType = TypeX.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);
+ }
+
+ ResolvedTypeX searchType;
+ if (onType != null) {
+ searchType = scope.getWorld().resolve(onType);
+ } else {
+ searchType = scope.getEnclosingType();
+ }
+
+
+ arguments.resolveBindings(scope, bindings, 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 (onType == null) {
+ while (true) {
+ TypeX 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");
+ return;
+ }
+
+ if (Modifier.isAbstract(pointcutDef.getModifiers())) {
+ if (onType != null) {
+ 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;
+ }
+ }
+
+
+ ResolvedTypeX[] 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;
+ }
+
+
+
+ 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 (!p.matchesSubtypes(parameterTypes[i])) {
+ scope.message(IMessage.ERROR, p, "incompatible type, expected " +
+ parameterTypes[i] + " found " + p);
+ return;
+ }
+ }
+ }
+
+ public void postRead(ResolvedTypeX enclosingType) {
+ arguments.postRead(enclosingType);
+ }
+
+ public Test findResidue(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;
+ public Pointcut concretize1(ResolvedTypeX searchStart, IntMap bindings) {
+ if (concretizing) {
+ Thread.currentThread().dumpStack();
+ searchStart.getWorld().getMessageHandler().handleMessage(
+ MessageUtil.error("circular pointcut declaration involving: " + this,
+ getSourceLocation()));
+ return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+ }
+
+ try {
+ concretizing = true;
+
+ ResolvedPointcutDefinition pointcutDec;
+ if (onType != null) {
+ searchStart = onType.resolve(searchStart.getWorld());
+ if (searchStart == ResolvedTypeX.MISSING) {
+ return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+ }
+ }
+ pointcutDec = searchStart.findPointcut(name);
+ if (pointcutDec == null) {
+ searchStart.getWorld().getMessageHandler().handleMessage(
+ MessageUtil.error("can't find pointcut \'" + name + "\' on " + searchStart.getName(),
+ getSourceLocation())
+ );
+ return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+ }
+ //??? error if we don't find
+
+ //System.err.println("start: " + searchStart);
+ ResolvedTypeX[] parameterTypes = searchStart.getWorld().resolve(pointcutDec.getParameterTypes());
+
+ arguments = arguments.resolveReferences(bindings);
+
+ IntMap newBindings = new IntMap();
+ 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 (!p.matchesSubtypes(parameterTypes[i])) {
+ throw new BCException("illegal change to pointcut declaration: " + this);
+ }
+
+ if (p instanceof BindingTypePattern) {
+ newBindings.put(i, ((BindingTypePattern)p).getFormalIndex());
+ }
+ }
+
+ newBindings.copyContext(bindings);
+ newBindings.pushEnclosingDefinition(pointcutDec);
+ try {
+ return pointcutDec.getPointcut().concretize1(searchStart, newBindings);
+ } finally {
+ newBindings.popEnclosingDefinitition();
+ }
+
+ } finally {
+ concretizing = false;
+ }
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof ReferencePointcut)) return false;
+ 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;
+ }
+
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java b/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java
new file mode 100644
index 000000000..fe47e13f4
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java
@@ -0,0 +1,224 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.util.*;
+import java.util.Collection;
+
+import org.aspectj.weaver.*;
+
+
+public class SignaturePattern extends PatternNode {
+ private Member.Kind kind;
+ private ModifiersPattern modifiers;
+ private TypePattern returnType;
+ private TypePattern declaringType;
+ private NamePattern name;
+ private TypePatternList parameterTypes;
+ private ThrowsPattern throwsPattern;
+
+ public SignaturePattern(Member.Kind kind, ModifiersPattern modifiers,
+ TypePattern returnType, TypePattern declaringType,
+ NamePattern name, TypePatternList parameterTypes,
+ ThrowsPattern throwsPattern) {
+ this.kind = kind;
+ this.modifiers = modifiers;
+ this.returnType = returnType;
+ this.name = name;
+ this.declaringType = declaringType;
+ this.parameterTypes = parameterTypes;
+ this.throwsPattern = throwsPattern;
+ }
+
+
+ public SignaturePattern resolveBindings(IScope scope, Bindings bindings) {
+ if (returnType != null) {
+ returnType = returnType.resolveBindings(scope, bindings, false);
+ }
+ if (declaringType != null) {
+ declaringType = declaringType.resolveBindings(scope, bindings, false);
+ }
+ if (parameterTypes != null) {
+ parameterTypes = parameterTypes.resolveBindings(scope, bindings, false);
+ }
+ if (throwsPattern != null) {
+ throwsPattern = throwsPattern.resolveBindings(scope, bindings);
+ }
+
+ return this;
+ }
+
+
+ public void postRead(ResolvedTypeX enclosingType) {
+ if (returnType != null) {
+ returnType.postRead(enclosingType);
+ }
+ if (declaringType != null) {
+ declaringType.postRead(enclosingType);
+ }
+ if (parameterTypes != null) {
+ parameterTypes.postRead(enclosingType);
+ }
+ }
+
+ public boolean matches(Member member, World world) {
+ //XXX performance gains would come from matching on name before resolving
+ // to fail fast
+ ResolvedMember sig = member.resolve(world);
+ if (sig == null) {
+ //XXX
+ if (member.getName().startsWith(NameMangler.PREFIX)) {
+ return false;
+ }
+ world.getLint().unresolvableMember.signal(member.toString(), getSourceLocation());
+ return false;
+ }
+ if (!modifiers.matches(sig.getModifiers())) return false;
+
+ if (kind == Member.STATIC_INITIALIZATION) {
+ //System.err.println("match static init: " + sig.getDeclaringType() + " with " + this);
+ return declaringType.matchesStatically(sig.getDeclaringType().resolve(world));
+ } else if (kind == Member.FIELD) {
+
+ if (!returnType.matchesStatically(sig.getReturnType().resolve(world))) return false;
+ if (!name.matches(sig.getName())) return false;
+ boolean ret = declaringTypeMatch(member.getDeclaringType(), member, world);
+ //System.out.println(" ret: " + ret);
+ return ret;
+ } else if (kind == Member.METHOD) {
+ if (!returnType.matchesStatically(sig.getReturnType().resolve(world))) return false;
+ if (!name.matches(sig.getName())) return false;
+ if (!parameterTypes.matches(world.resolve(sig.getParameterTypes()), TypePattern.STATIC).alwaysTrue()) {
+ return false;
+ }
+ if (!throwsPattern.matches(sig.getExceptions(), world)) return false;
+ return declaringTypeMatch(member.getDeclaringType(), member, world);
+ } else if (kind == Member.CONSTRUCTOR) {
+ if (!parameterTypes.matches(world.resolve(sig.getParameterTypes()), TypePattern.STATIC).alwaysTrue()) {
+ return false;
+ }
+ if (!throwsPattern.matches(sig.getExceptions(), world)) return false;
+ return declaringType.matchesStatically(member.getDeclaringType().resolve(world));
+ //return declaringTypeMatch(member.getDeclaringType(), member, world);
+ }
+
+ return false;
+ }
+
+ private boolean declaringTypeMatch(TypeX onTypeUnresolved, Member member, World world) {
+ ResolvedTypeX onType = onTypeUnresolved.resolve(world);
+
+ // fastmatch
+ if (declaringType.matchesStatically(onType)) return true;
+
+ Collection declaringTypes = member.getDeclaringTypes(world);
+
+ for (Iterator i = declaringTypes.iterator(); i.hasNext(); ) {
+ ResolvedTypeX type = (ResolvedTypeX)i.next();
+ if (declaringType.matchesStatically(type)) return true;
+ }
+ return false;
+ }
+
+
+ public NamePattern getName() { return name; }
+ public TypePattern getDeclaringType() { return declaringType; }
+
+ public Member.Kind getKind() {
+ return kind;
+ }
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ if (modifiers != ModifiersPattern.ANY) {
+ buf.append(modifiers.toString());
+ buf.append(' ');
+ }
+
+ if (kind == Member.STATIC_INITIALIZATION) {
+ buf.append(declaringType.toString());
+ buf.append(".<clinit>()");
+ } 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());
+ }
+ }
+ 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);
+ }
+ public int hashCode() {
+ int result = 17;
+ result = 37*result + kind.hashCode();
+ result = 37*result + modifiers.hashCode();
+ result = 37*result + returnType.hashCode();
+ result = 37*result + declaringType.hashCode();
+ result = 37*result + name.hashCode();
+ result = 37*result + parameterTypes.hashCode();
+ return result;
+ }
+
+ 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);
+ writeLocation(s);
+ }
+
+ public static SignaturePattern read(DataInputStream s, ISourceContext context) throws IOException {
+ Member.Kind kind = Member.Kind.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);
+ SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType,
+ name, parameterTypes, throwsPattern);
+ ret.readLocation(context, s);
+ return ret;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/SimpleScope.java b/weaver/src/org/aspectj/weaver/patterns/SimpleScope.java
new file mode 100644
index 000000000..2821e67ae
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/SimpleScope.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.*;
+import org.aspectj.bridge.*;
+import org.aspectj.bridge.IMessageHandler;
+
+public class SimpleScope implements IScope {
+
+ private World world;
+ private ResolvedTypeX enclosingType;
+ private FormalBinding[] bindings;
+
+ private String[] importedPrefixes = javaLangPrefixArray;
+ private String[] importedNames = ZERO_STRINGS;
+
+ public SimpleScope(World world, FormalBinding[] bindings) {
+ super();
+ this.world = world;
+ this.bindings = bindings;
+ }
+
+ // ---- impl
+
+ //XXX doesn't report any problems
+ public TypeX lookupType(String name, IHasPosition location) {
+ for (int i=0; i<importedNames.length; i++) {
+ String importedName = importedNames[i];
+ if (importedName.endsWith(name)) {
+ return world.resolve(importedName);
+ }
+ }
+
+ for (int i=0; i<importedPrefixes.length; i++) {
+ String importedPrefix = importedPrefixes[i];
+ TypeX tryType = world.resolve(TypeX.forName(importedPrefix + name), true);
+ if (tryType != ResolvedTypeX.MISSING) {
+ return tryType;
+ }
+ }
+
+ return world.resolve(TypeX.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(TypeX[] 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 static final String[] ZERO_STRINGS = new String[0];
+
+ public static final String[] javaLangPrefixArray =
+ new String[] { "java.lang.", };
+
+
+
+ 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 World getWorld() {
+ return world;
+ }
+
+ public ResolvedTypeX getEnclosingType() {
+ return enclosingType;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java
new file mode 100644
index 000000000..9baf92e10
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java
@@ -0,0 +1,108 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+
+//
+
+/**
+ * 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;
+
+ public ThisOrTargetPointcut(boolean isThis, TypePattern type) {
+ this.isThis = isThis;
+ this.type = type;
+ }
+
+ private boolean couldMatch(Shadow shadow) {
+ return isThis ? shadow.hasThis() : shadow.hasTarget();
+ }
+
+ public FuzzyBoolean match(Shadow shadow) {
+ if (!couldMatch(shadow)) return FuzzyBoolean.NO;
+ TypeX typeToMatch = isThis ? shadow.getThisType() : shadow.getTargetType();
+ //if (typeToMatch == ResolvedTypeX.MISSING) return FuzzyBoolean.NO;
+
+ return type.matches(typeToMatch.resolve(shadow.getIWorld()), TypePattern.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(DataInputStream 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);
+ // ??? handle non-formal
+ }
+
+ public void postRead(ResolvedTypeX enclosingType) {
+ type.postRead(enclosingType);
+ }
+
+ 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 (isThis ? "this(" : "target(") + type + ")";
+ }
+
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ if (!couldMatch(shadow)) return Literal.FALSE;
+
+ if (type == TypePattern.ANY) return Literal.TRUE;
+
+ Var var = isThis ? shadow.getThisVar() : shadow.getTargetVar();
+ return exposeStateForVar(var, type, state, shadow.getIWorld());
+ }
+
+ public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
+ return new ThisOrTargetPointcut(isThis, type.remapAdviceFormals(bindings));
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/ThrowsPattern.java b/weaver/src/org/aspectj/weaver/patterns/ThrowsPattern.java
new file mode 100644
index 000000000..591787911
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/ThrowsPattern.java
@@ -0,0 +1,110 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.util.*;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.TypeX;
+
+
+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 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;
+ return o.required.equals(this.required) &&
+ o.forbidden.equals(this.forbidden);
+ }
+ 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);
+ forbidden = forbidden.resolveBindings(scope, bindings, false);
+ return this;
+ }
+
+ public boolean matches(TypeX[] tys, World world) {
+ if (this == ANY) return true;
+
+ //System.out.println("matching: " + this + " with " + Arrays.asList(tys));
+
+ ResolvedTypeX[] 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,
+ ResolvedTypeX[] types)
+ {
+ for (int i = types.length - 1; i >= 0; i--) {
+ if (typePattern.matchesExactly(types[i])) return true;
+ }
+ return false;
+ }
+
+ public static ThrowsPattern read(DataInputStream 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);
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/TypePattern.java b/weaver/src/org/aspectj/weaver/patterns/TypePattern.java
new file mode 100644
index 000000000..341138756
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/TypePattern.java
@@ -0,0 +1,263 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.util.*;
+
+import org.aspectj.weaver.*;
+import org.aspectj.bridge.*;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.util.*;
+/**
+ * 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();
+
+
+ protected boolean includeSubtypes;
+
+ protected TypePattern(boolean includeSubtypes) {
+ this.includeSubtypes = includeSubtypes;
+ }
+
+ //XXX non-final for Not, && and ||
+ public boolean matchesStatically(ResolvedTypeX type) {
+ if (includeSubtypes) {
+ return matchesSubtypes(type);
+ } else {
+ return matchesExactly(type);
+ }
+ }
+ public abstract FuzzyBoolean matchesInstanceof(ResolvedTypeX type);
+
+
+ public final FuzzyBoolean matches(ResolvedTypeX type, MatchKind kind) {
+ if (kind == STATIC) {
+ return FuzzyBoolean.fromBoolean(matchesStatically(type));
+ } else if (kind == DYNAMIC) {
+ //System.err.println("matching: " + this + " with " + type);
+ FuzzyBoolean ret = matchesInstanceof(type);
+ //System.err.println(" got: " + ret);
+ return ret;
+ } else {
+ throw new IllegalArgumentException("kind must be DYNAMIC or STATIC");
+ }
+ }
+
+
+ protected abstract boolean matchesExactly(ResolvedTypeX type);
+ protected boolean matchesSubtypes(ResolvedTypeX type) {
+ //System.out.println("matching: " + this + " to " + type);
+ if (matchesExactly(type)) {
+ //System.out.println(" true");
+ return true;
+ }
+
+ FuzzyBoolean ret = FuzzyBoolean.NO; // ??? -eh
+ for (Iterator i = type.getDirectSupertypes(); i.hasNext(); ) {
+ ResolvedTypeX superType = (ResolvedTypeX)i.next();
+ if (matchesSubtypes(superType)) return true;
+ }
+ return false;
+ }
+
+ public TypeX resolveExactType(IScope scope, Bindings bindings) {
+ TypePattern p = resolveBindings(scope, bindings, false);
+ if (!p.assertExactType(scope.getMessageHandler())) return ResolvedTypeX.MISSING;
+
+ return ((ExactTypePattern)p).getType();
+ }
+
+ public TypeX getExactType() {
+ if (this instanceof ExactTypePattern) return ((ExactTypePattern)this).getType();
+ else return ResolvedTypeX.MISSING;
+ }
+
+ 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) {
+ return this;
+ }
+
+ public void postRead(ResolvedTypeX 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 TypePattern read(DataInputStream 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 NOT: return NotTypePattern.read(s, context);
+ case OR: return OrTypePattern.read(s, context);
+ case AND: return AndTypePattern.read(s, context);
+ }
+ throw new BCException("unknown TypePattern kind: " + key);
+ }
+}
+
+class EllipsisTypePattern extends TypePattern {
+
+ /**
+ * Constructor for EllipsisTypePattern.
+ * @param includeSubtypes
+ */
+ public EllipsisTypePattern() {
+ super(false);
+ }
+
+ /**
+ * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
+ */
+ protected boolean matchesExactly(ResolvedTypeX type) {
+ return false;
+ }
+
+ /**
+ * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
+ */
+ public FuzzyBoolean matchesInstanceof(ResolvedTypeX 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 ".."; }
+}
+
+class AnyTypePattern extends TypePattern {
+
+ /**
+ * Constructor for EllipsisTypePattern.
+ * @param includeSubtypes
+ */
+ public AnyTypePattern() {
+ super(false);
+ }
+
+ /**
+ * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
+ */
+ protected boolean matchesExactly(ResolvedTypeX type) {
+ return true;
+ }
+
+ /**
+ * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
+ */
+ public FuzzyBoolean matchesInstanceof(ResolvedTypeX 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(ResolvedTypeX type) {
+ return true;
+ }
+
+
+ public boolean isStar() {
+ return true;
+ }
+
+ public String toString() { return "*"; }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/TypePatternList.java b/weaver/src/org/aspectj/weaver/patterns/TypePatternList.java
new file mode 100644
index 000000000..1f7abffc0
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/TypePatternList.java
@@ -0,0 +1,234 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.util.*;
+
+import org.aspectj.weaver.*;
+import org.aspectj.util.*;
+
+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[] {TypePattern.ELLIPSIS});
+
+ 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();
+ }
+
+ //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(ResolvedTypeX[] types, TypePattern.MatchKind kind) {
+ 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) {
+ FuzzyBoolean ret = typePatterns[patternIndex++].matches(types[nameIndex++], kind);
+ 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 {
+ FuzzyBoolean ret = p.matches(types[nameIndex++], kind);
+ 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 ResolvedTypeX[] 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 ResolvedTypeX[] 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--;
+ }
+ }
+
+ public TypePatternList resolveBindings(IScope scope, Bindings bindings, boolean allowBinding) {
+ for (int i=0; i<typePatterns.length; i++) {
+ TypePattern p = typePatterns[i];
+ if (p != null) {
+ typePatterns[i] = typePatterns[i].resolveBindings(scope, bindings, allowBinding);
+ }
+ }
+ 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(ResolvedTypeX 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(DataInputStream 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;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/TypePatternQuestions.java b/weaver/src/org/aspectj/weaver/patterns/TypePatternQuestions.java
new file mode 100644
index 000000000..d9ebe0983
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/TypePatternQuestions.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.util.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ResolvedTypeX;
+import org.aspectj.weaver.TypeX;
+import org.aspectj.util.FuzzyBoolean;
+
+
+public class TypePatternQuestions {
+ private Map questionsAndAnswers = new HashMap();
+
+ public FuzzyBoolean askQuestion(TypePattern pattern, ResolvedTypeX 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;
+ ResolvedTypeX type;
+ TypePattern.MatchKind kind;
+
+ public Question(TypePattern pattern, ResolvedTypeX 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/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java
new file mode 100644
index 000000000..1aed2f2ea
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java
@@ -0,0 +1,428 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.util.*;
+
+import org.aspectj.weaver.*;
+import org.aspectj.bridge.*;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.util.*;
+
+//XXX need to use dim in matching
+public class WildTypePattern extends TypePattern {
+ NamePattern[] namePatterns;
+ int ellipsisCount;
+ String[] importedPrefixes;
+ String[] knownMatches;
+ int dim;
+
+ WildTypePattern(NamePattern[] namePatterns, boolean includeSubtypes, int dim) {
+ super(includeSubtypes);
+ this.namePatterns = namePatterns;
+ this.ellipsisCount = ellipsisCount;
+ 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);
+
+ }
+
+ public WildTypePattern(List names, boolean includeSubtypes, int dim, int endPos) {
+ this(names, includeSubtypes, dim);
+ this.end = endPos;
+ }
+
+ //XXX inefficient implementation
+ public static char[][] splitNames(String s) {
+ List ret = new ArrayList();
+ int startIndex = 0;
+ while (true) {
+ int breakIndex = s.indexOf('.', startIndex); // what about /
+ if (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(ResolvedTypeX type) {
+ String targetTypeName = type.getName();
+
+ //XXX hack
+ if (knownMatches == null) {
+ return innerMatchesExactly(targetTypeName);
+ }
+
+ // 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) {
+ 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))) {
+ 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];
+ if (targetTypeName.startsWith(prefix)) {
+ if (innerMatchesExactly(targetTypeName.substring(prefix.length()))) {
+ return true;
+ }
+ }
+ }
+
+ return innerMatchesExactly(targetTypeName);
+ }
+
+ private int lastIndexOfDotOrDollar(String string) {
+ int dot = string.lastIndexOf('.');
+ int dollar = string.lastIndexOf('$');
+ return Math.max(dot, dollar);
+ }
+
+
+ private boolean innerMatchesExactly(String targetTypeName) {
+ //??? doing this everytime is not very efficient
+ char[][] names = splitNames(targetTypeName);
+
+
+
+ return innerMatchesExactly(names);
+ }
+
+ private boolean innerMatchesExactly(char[][] names) {
+
+ int namesLength = names.length;
+ int patternsLength = namePatterns.length;
+
+ int namesIndex = 0;
+ int patternsIndex = 0;
+
+ if (ellipsisCount == 0) {
+ if (namesLength != patternsLength) return false;
+ while (patternsIndex < patternsLength) {
+ if (!namePatterns[patternsIndex++].matches(names[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(names[namesIndex++])) {
+ return false;
+ }
+ }
+ }
+ return true;
+ } else {
+ // System.err.print("match(\"" + Arrays.asList(namePatterns) + "\", \"" + Arrays.asList(names) + "\") -> ");
+ boolean b = outOfStar(namePatterns, names, 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(ResolvedTypeX 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() {
+ //System.err.println("extract from : " + Arrays.asList(namePatterns));
+ int len = namePatterns.length;
+ 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();
+ }
+
+
+ /**
+ * 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) {
+ if (isStar()) {
+ return TypePattern.ANY; //??? loses source location
+ }
+
+ String simpleName = maybeGetSimpleName();
+ if (simpleName != null) {
+ FormalBinding formalBinding = scope.lookupFormal(simpleName);
+ if (formalBinding != null) {
+ if (!allowBinding || bindings == null) {
+ scope.message(IMessage.ERROR, this, "negation doesn't allow binding");
+ return this;
+ }
+ BindingTypePattern binding = new BindingTypePattern(formalBinding);
+ binding.copyLocationFrom(this);
+ bindings.register(binding, scope);
+
+ return binding;
+ }
+ }
+
+ String cleanName = maybeGetCleanName();
+ if (cleanName != null) {
+ TypeX type;
+
+ //System.out.println("resolve: " + cleanName);
+ //??? this loop has too many inefficiencies to count
+ while ((type = scope.lookupType(cleanName, this)) == ResolvedTypeX.MISSING) {
+ int lastDot = cleanName.lastIndexOf('.');
+ if (lastDot == -1) break;
+ cleanName = cleanName.substring(0, lastDot) + '$' + cleanName.substring(lastDot+1);
+ }
+ if (type == ResolvedTypeX.MISSING) {
+ if (scope.getWorld().getLint().invalidAbsoluteTypeName.isEnabled()) {
+ scope.getWorld().getLint().invalidAbsoluteTypeName.signal(cleanName, getSourceLocation());
+ }
+ } else {
+ TypePattern ret = new ExactTypePattern(type, includeSubtypes);
+ ret.copyLocationFrom(this);
+ return ret;
+ }
+ } else {
+ //XXX need to implement behavior for Lint.invalidWildcardTypeName
+ }
+
+ importedPrefixes = scope.getImportedPrefixes();
+ knownMatches = preMatch(scope.getImportedNames());
+
+ return this;
+ }
+
+ public boolean isStar() {
+ 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]); //??? 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(ResolvedTypeX enclosingType) {
+// this.importedPrefixes = enclosingType.getImportedPrefixes();
+// this.knownNames = prematch(enclosingType.getImportedNames());
+// }
+
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ 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());
+ }
+ }
+ 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;
+ for (int i=0; i < len; i++) {
+ if (!o.namePatterns[i].equals(this.namePatterns[i])) return false;
+ }
+ return true;
+ }
+
+ public int hashCode() {
+ int result = 17;
+ for (int i = 0, len = namePatterns.length; i < len; i++) {
+ result = 37*result + namePatterns[i].hashCode();
+ }
+ return result;
+ }
+
+ /**
+ * @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
+ */
+ public void write(DataOutputStream s) throws IOException {
+ s.writeByte(TypePattern.WILD);
+ s.writeShort(namePatterns.length);
+ for (int i = 0; i < namePatterns.length; i++) {
+ namePatterns[i].write(s);
+ }
+ s.writeBoolean(includeSubtypes);
+ s.writeInt(dim);
+ writeLocation(s);
+ }
+
+ public static TypePattern read(DataInputStream 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();
+ TypePattern ret = new WildTypePattern(namePatterns, includeSubtypes, dim);
+ ret.readLocation(context, s);
+ return ret;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java b/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java
new file mode 100644
index 000000000..2b931985b
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java
@@ -0,0 +1,83 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.util.*;
+
+public class WithinPointcut extends Pointcut {
+ TypePattern type;
+
+ public WithinPointcut(TypePattern type) {
+ this.type = type;
+ }
+
+ public FuzzyBoolean match(Shadow shadow) {
+ TypeX enclosingType = shadow.getEnclosingType();
+ while (enclosingType != null) {
+ if (type.matchesStatically(shadow.getIWorld().resolve(enclosingType))) {
+ return FuzzyBoolean.YES;
+ }
+ enclosingType = enclosingType.getDeclaringType();
+ }
+ return FuzzyBoolean.NO;
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ s.writeByte(Pointcut.WITHIN);
+ type.write(s);
+ writeLocation(s);
+ }
+ public static Pointcut read(DataInputStream 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) {
+ type = type.resolveBindings(scope, bindings, false);
+ }
+
+ public void postRead(ResolvedTypeX enclosingType) {
+ type.postRead(enclosingType);
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof WithinPointcut)) return false;
+ WithinPointcut o = (WithinPointcut)other;
+ return o.type.equals(this.type);
+ }
+ public int hashCode() {
+ int result = 43;
+ result = 37*result + type.hashCode();
+ return result;
+ }
+
+ public String toString() {
+ return "within(" + type + ")";
+ }
+
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
+ }
+
+
+ public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
+ return this; //??? no pointers out of here so we're okay
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java b/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java
new file mode 100644
index 000000000..328f31fb4
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java
@@ -0,0 +1,79 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ast.*;
+import org.aspectj.util.*;
+
+public class WithincodePointcut extends Pointcut {
+ SignaturePattern signature;
+
+ public WithincodePointcut(SignaturePattern signature) {
+ this.signature = signature;
+ }
+
+ public FuzzyBoolean match(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()));
+ }
+
+ public void write(DataOutputStream s) throws IOException {
+ s.writeByte(Pointcut.WITHINCODE);
+ signature.write(s);
+ writeLocation(s);
+ }
+
+ public static Pointcut read(DataInputStream 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);
+ }
+
+ public void postRead(ResolvedTypeX 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 + ")";
+ }
+
+ public Test findResidue(Shadow shadow, ExposedState state) {
+ return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
+ }
+
+
+ public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
+ return this; //??? no pointers out of here so we're okay
+ }
+}
diff --git a/weaver/testdata/AddNotResidueDynamicHelloWorld.txt b/weaver/testdata/AddNotResidueDynamicHelloWorld.txt
new file mode 100644
index 000000000..48a5bfd77
--- /dev/null
+++ b/weaver/testdata/AddNotResidueDynamicHelloWorld.txt
@@ -0,0 +1,82 @@
+public class DynamicHelloWorld extends java.lang.Object implements java.io.Serializable:
+ public void <init>():
+ ALOAD_0 // DynamicHelloWorld this (line 8)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void DynamicHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void DynamicHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ | catch java.lang.UnsupportedOperationException -> E0
+ | | NEW DynamicHelloWorld (line 12)
+ | | DUP
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | | INVOKESPECIAL DynamicHelloWorld.<init> ()V
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | LDC "hello"
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | | GETSTATIC java.util.Collections.EMPTY_LIST Ljava/util/List;
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | | INVOKEVIRTUAL DynamicHelloWorld.doit (Ljava/lang/String;Ljava/util/List;)Ljava/lang/String;
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | POP
+ | | GOTO L0
+ | catch java.lang.UnsupportedOperationException -> E0
+ | E0: ASTORE_1 (line 13)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 14)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | NEW java.lang.StringBuffer
+ | DUP
+ | LDC "expected and caught: "
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ALOAD_1 // java.lang.UnsupportedOperationException t
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 15)
+ | L0: NEW java.lang.RuntimeException (line 17)
+ | DUP
+ | LDC "should have caught exception"
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.RuntimeException.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | ATHROW
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ String doit(String, java.util.List):
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | ALOAD_2 // java.util.List l (line 21)
+ | ALOAD_1 // java.lang.String arg0
+ | ASTORE_3
+ | ASTORE 4
+ | method-call(boolean java.util.List.add(java.lang.Object))
+ | | ALOAD 4
+ | | INSTANCEOF java.util.ArrayList
+ | | IFNE L0
+ | | INVOKESTATIC Aspect.ajc_before_0 ()V
+ | | L0: ALOAD 4
+ | | ALOAD_3
+ | | INVOKEINTERFACE java.util.List.add (Ljava/lang/Object;)Z
+ | method-call(boolean java.util.List.add(java.lang.Object))
+ | POP
+ | ALOAD_2 // java.util.List l (line 22)
+ | method-call(java.lang.String java.lang.Object.toString())
+ | | INVOKEVIRTUAL java.lang.Object.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.Object.toString())
+ | ARETURN
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ end String doit(String, java.util.List)
+end public class DynamicHelloWorld
diff --git a/weaver/testdata/AddResidueDynamicHelloWorld.txt b/weaver/testdata/AddResidueDynamicHelloWorld.txt
new file mode 100644
index 000000000..16f438647
--- /dev/null
+++ b/weaver/testdata/AddResidueDynamicHelloWorld.txt
@@ -0,0 +1,82 @@
+public class DynamicHelloWorld extends java.lang.Object implements java.io.Serializable:
+ public void <init>():
+ ALOAD_0 // DynamicHelloWorld this (line 8)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void DynamicHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void DynamicHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ | catch java.lang.UnsupportedOperationException -> E0
+ | | NEW DynamicHelloWorld (line 12)
+ | | DUP
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | | INVOKESPECIAL DynamicHelloWorld.<init> ()V
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | LDC "hello"
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | | GETSTATIC java.util.Collections.EMPTY_LIST Ljava/util/List;
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | | INVOKEVIRTUAL DynamicHelloWorld.doit (Ljava/lang/String;Ljava/util/List;)Ljava/lang/String;
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | POP
+ | | GOTO L0
+ | catch java.lang.UnsupportedOperationException -> E0
+ | E0: ASTORE_1 (line 13)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 14)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | NEW java.lang.StringBuffer
+ | DUP
+ | LDC "expected and caught: "
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ALOAD_1 // java.lang.UnsupportedOperationException t
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 15)
+ | L0: NEW java.lang.RuntimeException (line 17)
+ | DUP
+ | LDC "should have caught exception"
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.RuntimeException.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | ATHROW
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ String doit(String, java.util.List):
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | ALOAD_2 // java.util.List l (line 21)
+ | ALOAD_1 // java.lang.String arg0
+ | ASTORE_3
+ | ASTORE 4
+ | method-call(boolean java.util.List.add(java.lang.Object))
+ | | ALOAD 4
+ | | INSTANCEOF java.util.ArrayList
+ | | IFEQ L0
+ | | INVOKESTATIC Aspect.ajc_before_0 ()V
+ | | L0: ALOAD 4
+ | | ALOAD_3
+ | | INVOKEINTERFACE java.util.List.add (Ljava/lang/Object;)Z
+ | method-call(boolean java.util.List.add(java.lang.Object))
+ | POP
+ | ALOAD_2 // java.util.List l (line 22)
+ | method-call(java.lang.String java.lang.Object.toString())
+ | | INVOKEVIRTUAL java.lang.Object.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.Object.toString())
+ | ARETURN
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ end String doit(String, java.util.List)
+end public class DynamicHelloWorld
diff --git a/weaver/testdata/AddStateResidueDynamicHelloWorld.txt b/weaver/testdata/AddStateResidueDynamicHelloWorld.txt
new file mode 100644
index 000000000..f0c96df34
--- /dev/null
+++ b/weaver/testdata/AddStateResidueDynamicHelloWorld.txt
@@ -0,0 +1,84 @@
+public class DynamicHelloWorld extends java.lang.Object implements java.io.Serializable:
+ public void <init>():
+ ALOAD_0 // DynamicHelloWorld this (line 8)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void DynamicHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void DynamicHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ | catch java.lang.UnsupportedOperationException -> E0
+ | | NEW DynamicHelloWorld (line 12)
+ | | DUP
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | | INVOKESPECIAL DynamicHelloWorld.<init> ()V
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | LDC "hello"
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | | GETSTATIC java.util.Collections.EMPTY_LIST Ljava/util/List;
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | | INVOKEVIRTUAL DynamicHelloWorld.doit (Ljava/lang/String;Ljava/util/List;)Ljava/lang/String;
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | POP
+ | | GOTO L0
+ | catch java.lang.UnsupportedOperationException -> E0
+ | E0: ASTORE_1 (line 13)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 14)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | NEW java.lang.StringBuffer
+ | DUP
+ | LDC "expected and caught: "
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ALOAD_1 // java.lang.UnsupportedOperationException t
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 15)
+ | L0: NEW java.lang.RuntimeException (line 17)
+ | DUP
+ | LDC "should have caught exception"
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.RuntimeException.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | ATHROW
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ String doit(String, java.util.List):
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | ALOAD_2 // java.util.List l (line 21)
+ | ALOAD_1 // java.lang.String arg0
+ | ASTORE_3
+ | ASTORE 4
+ | method-call(boolean java.util.List.add(java.lang.Object))
+ | | ALOAD 4
+ | | INSTANCEOF java.util.ArrayList
+ | | IFEQ L0
+ | | ALOAD 4
+ | | CHECKCAST java.util.ArrayList
+ | | INVOKESTATIC Aspect.ajc_before_0 (Ljava/util/ArrayList;)V
+ | | L0: ALOAD 4
+ | | ALOAD_3
+ | | INVOKEINTERFACE java.util.List.add (Ljava/lang/Object;)Z
+ | method-call(boolean java.util.List.add(java.lang.Object))
+ | POP
+ | ALOAD_2 // java.util.List l (line 22)
+ | method-call(java.lang.String java.lang.Object.toString())
+ | | INVOKEVIRTUAL java.lang.Object.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.Object.toString())
+ | ARETURN
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ end String doit(String, java.util.List)
+end public class DynamicHelloWorld
diff --git a/weaver/testdata/AfterFancyHelloWorld.txt b/weaver/testdata/AfterFancyHelloWorld.txt
new file mode 100644
index 000000000..16b04e4b1
--- /dev/null
+++ b/weaver/testdata/AfterFancyHelloWorld.txt
@@ -0,0 +1,183 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | catch java.lang.Throwable -> E0
+ | | GOTO L0
+ | catch java.lang.Throwable -> E0
+ | E0: ASTORE_1
+ | INVOKESTATIC Aspect.ajc_after_constructor_execution ()V
+ | ALOAD_1
+ | ATHROW
+ | L0: INVOKESTATIC Aspect.ajc_after_constructor_execution ()V
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | catch java.lang.Throwable -> E6
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | | catch java.lang.Throwable -> E3
+ | | | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | | | catch java.lang.Throwable -> E3
+ | | | GOTO L0
+ | | | E3: ASTORE 5
+ | | | INVOKESTATIC Aspect.ajc_after_field_get ()V
+ | | | ALOAD 5
+ | | | ATHROW
+ | | | L0: NOP
+ | | | INVOKESTATIC Aspect.ajc_after_field_get ()V
+ | | | NOP
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | ASTORE_1
+ | | finally -> E5
+ | | | catch java.lang.Exception -> E4
+ | | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | | LDC "bye"
+ | | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | | catch java.lang.Throwable -> E2
+ | | | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | | | catch java.lang.Throwable -> E2
+ | | | | | GOTO L1
+ | | | | | E2: ASTORE 6
+ | | | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | | | ALOAD 6
+ | | | | | ATHROW
+ | | | | | L1: NOP
+ | | | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | | | NOP
+ | | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | GOTO L3
+ | | | catch java.lang.Exception -> E4
+ | | | E4: ASTORE_2 (line 12)
+ | | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | | ALOAD_2 // java.lang.Exception e
+ | | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | | catch java.lang.Throwable -> E1
+ | | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | | | catch java.lang.Throwable -> E1
+ | | | | GOTO L2
+ | | | | E1: ASTORE 7
+ | | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | | ALOAD 7
+ | | | | ATHROW
+ | | | | L2: NOP
+ | | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | | NOP
+ | | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | finally -> E5
+ | | GOTO L3
+ | | E5: ASTORE 4 (line 14)
+ | | JSR L4
+ | | ALOAD 4
+ | | ATHROW
+ | | L3: JSR L4
+ | | GOTO L6
+ | | L4: ASTORE_3
+ | | ALOAD_1 // java.io.PrintStream out (line 15)
+ | | LDC "finally"
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | catch java.lang.Throwable -> E0
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | catch java.lang.Throwable -> E0
+ | | | GOTO L5
+ | | | E0: ASTORE 8
+ | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | ALOAD 8
+ | | | ATHROW
+ | | | L5: NOP
+ | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | NOP
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | RET 3 (line 10)
+ | | L6: GOTO L7 (line 17)
+ | catch java.lang.Throwable -> E6
+ | E6: ASTORE 9
+ | INVOKESTATIC Aspect.ajc_after_method_execution ()V
+ | ALOAD 9
+ | ATHROW
+ | L7: INVOKESTATIC Aspect.ajc_after_method_execution ()V
+ | RETURN
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | catch java.lang.Throwable -> E4
+ | | ICONST_0 (line 20)
+ | | ISTORE_0
+ | | ILOAD_0 // int x (line 21)
+ | | LDC "name"
+ | | method-call(int java.lang.String.hashCode())
+ | | | catch java.lang.Throwable -> E3
+ | | | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | | | catch java.lang.Throwable -> E3
+ | | | GOTO L0
+ | | | E3: ASTORE_1
+ | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | ALOAD_1
+ | | | ATHROW
+ | | | L0: NOP
+ | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | NOP
+ | | method-call(int java.lang.String.hashCode())
+ | | IADD
+ | | ISTORE_0 // int x
+ | | LDC "name" (line 22)
+ | | ASTORE_2
+ | | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | | catch java.lang.Throwable -> E2
+ | | | | NEW java.lang.StringBuffer
+ | | | | DUP
+ | | | | ALOAD_2
+ | | | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | | | catch java.lang.Throwable -> E2
+ | | | GOTO L1
+ | | | E2: ASTORE_3
+ | | | INVOKESTATIC Aspect.ajc_after_constructor_call ()V
+ | | | ALOAD_3
+ | | | ATHROW
+ | | | L1: NOP
+ | | | INVOKESTATIC Aspect.ajc_after_constructor_call ()V
+ | | | NOP
+ | | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | ILOAD_0 // int x
+ | | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | | catch java.lang.Throwable -> E1
+ | | | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | | | catch java.lang.Throwable -> E1
+ | | | GOTO L2
+ | | | E1: ASTORE 4
+ | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | ALOAD 4
+ | | | ATHROW
+ | | | L2: NOP
+ | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | NOP
+ | | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | | catch java.lang.Throwable -> E0
+ | | | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | | | catch java.lang.Throwable -> E0
+ | | | GOTO L3
+ | | | E0: ASTORE 5
+ | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | ALOAD 5
+ | | | ATHROW
+ | | | L3: NOP
+ | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | NOP
+ | | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | GOTO L4
+ | catch java.lang.Throwable -> E4
+ | E4: ASTORE 6
+ | INVOKESTATIC Aspect.ajc_after_method_execution ()V
+ | ALOAD 6
+ | ATHROW
+ | L4: INVOKESTATIC Aspect.ajc_after_method_execution ()V
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/AfterHelloWorld.txt b/weaver/testdata/AfterHelloWorld.txt
new file mode 100644
index 000000000..4c0e6db53
--- /dev/null
+++ b/weaver/testdata/AfterHelloWorld.txt
@@ -0,0 +1,58 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | catch java.lang.Throwable -> E0
+ | | GOTO L0
+ | catch java.lang.Throwable -> E0
+ | E0: ASTORE_1
+ | INVOKESTATIC Aspect.ajc_after_constructor_execution ()V
+ | ALOAD_1
+ | ATHROW
+ | L0: INVOKESTATIC Aspect.ajc_after_constructor_execution ()V
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | catch java.lang.Throwable -> E2
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | | catch java.lang.Throwable -> E1
+ | | | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | | | catch java.lang.Throwable -> E1
+ | | | GOTO L0
+ | | | E1: ASTORE_1
+ | | | INVOKESTATIC Aspect.ajc_after_field_get ()V
+ | | | ALOAD_1
+ | | | ATHROW
+ | | | L0: NOP
+ | | | INVOKESTATIC Aspect.ajc_after_field_get ()V
+ | | | NOP
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | LDC "hello world" (line 9)
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | catch java.lang.Throwable -> E0
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | catch java.lang.Throwable -> E0
+ | | | GOTO L1
+ | | | E0: ASTORE_2
+ | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | ALOAD_2
+ | | | ATHROW
+ | | | L1: NOP
+ | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
+ | | | NOP
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | GOTO L2 (line 11)
+ | catch java.lang.Throwable -> E2
+ | E2: ASTORE_3
+ | INVOKESTATIC Aspect.ajc_after_method_execution ()V
+ | ALOAD_3
+ | ATHROW
+ | L2: INVOKESTATIC Aspect.ajc_after_method_execution ()V
+ | RETURN
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/AfterReturningCheckcastParamFancyHelloWorld.txt b/weaver/testdata/AfterReturningCheckcastParamFancyHelloWorld.txt
new file mode 100644
index 000000000..868a63429
--- /dev/null
+++ b/weaver/testdata/AfterReturningCheckcastParamFancyHelloWorld.txt
@@ -0,0 +1,86 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | | DUP
+ | | ASTORE 5
+ | | ALOAD 5
+ | | INSTANCEOF java.rmi.server.LogStream
+ | | IFEQ L0
+ | | ALOAD 5
+ | | CHECKCAST java.rmi.server.LogStream
+ | | INVOKESTATIC Aspect.ajc_afterReturning_field_get (Ljava/rmi/server/LogStream;)V
+ | | L0: NOP
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | ASTORE_1
+ | finally -> E1
+ | | catch java.lang.Exception -> E0
+ | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | LDC "bye"
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | GOTO L1
+ | | catch java.lang.Exception -> E0
+ | | E0: ASTORE_2 (line 12)
+ | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | ALOAD_2 // java.lang.Exception e
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | finally -> E1
+ | GOTO L1
+ | E1: ASTORE 4 (line 14)
+ | JSR L2
+ | ALOAD 4
+ | ATHROW
+ | L1: JSR L2
+ | GOTO L3
+ | L2: ASTORE_3
+ | ALOAD_1 // java.io.PrintStream out (line 15)
+ | LDC "finally"
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RET 3 (line 10)
+ | L3: RETURN (line 17)
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | NEW java.lang.StringBuffer (line 22)
+ | DUP
+ | LDC "name"
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/AfterReturningCheckcastParamHelloWorld.txt b/weaver/testdata/AfterReturningCheckcastParamHelloWorld.txt
new file mode 100644
index 000000000..0aa498026
--- /dev/null
+++ b/weaver/testdata/AfterReturningCheckcastParamHelloWorld.txt
@@ -0,0 +1,31 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | | DUP
+ | | ASTORE_1
+ | | ALOAD_1
+ | | INSTANCEOF java.rmi.server.LogStream
+ | | IFEQ L0
+ | | ALOAD_1
+ | | CHECKCAST java.rmi.server.LogStream
+ | | INVOKESTATIC Aspect.ajc_afterReturning_field_get (Ljava/rmi/server/LogStream;)V
+ | | L0: NOP
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/AfterReturningConversionParam.txt b/weaver/testdata/AfterReturningConversionParam.txt
new file mode 100644
index 000000000..7920b30d2
--- /dev/null
+++ b/weaver/testdata/AfterReturningConversionParam.txt
@@ -0,0 +1,83 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | ASTORE_1
+ | finally -> E1
+ | | catch java.lang.Exception -> E0
+ | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | LDC "bye"
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | GOTO L0
+ | | catch java.lang.Exception -> E0
+ | | E0: ASTORE_2 (line 12)
+ | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | ALOAD_2 // java.lang.Exception e
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | finally -> E1
+ | GOTO L0
+ | E1: ASTORE 4 (line 14)
+ | JSR L1
+ | ALOAD 4
+ | ATHROW
+ | L0: JSR L1
+ | GOTO L2
+ | L1: ASTORE_3
+ | ALOAD_1 // java.io.PrintStream out (line 15)
+ | LDC "finally"
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RET 3 (line 10)
+ | L2: RETURN (line 17)
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | | DUP
+ | | ISTORE_1
+ | | ILOAD_1
+ | | INVOKESTATIC org.aspectj.runtime.internal.Conversions.intObject (I)Ljava/lang/Object;
+ | | INVOKESTATIC Aspect.ajc_afterReturning_field_get (Ljava/lang/Object;)V
+ | | NOP
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | NEW java.lang.StringBuffer (line 22)
+ | DUP
+ | LDC "name"
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/AfterReturningConversionParamFancyHelloWorld.txt b/weaver/testdata/AfterReturningConversionParamFancyHelloWorld.txt
new file mode 100644
index 000000000..ab6c18583
--- /dev/null
+++ b/weaver/testdata/AfterReturningConversionParamFancyHelloWorld.txt
@@ -0,0 +1,88 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ local 0: FancyHelloWorld this
+ | ALOAD_0
+ | INVOKESPECIAL java.lang.Object.<init> ()V
+ local 0: FancyHelloWorld this
+ RETURN
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | local 0: java.lang.String[] args
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | | GETSTATIC java.lang.System.out Ljava/io/PrintStream;
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | ASTORE_1
+ | | local 1: java.io.PrintStream out
+ | | | finally -> E1
+ | | | | catch java.lang.Exception -> E0
+ | | | | | ALOAD_1
+ | | | | | LDC "bye"
+ | | | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | | GOTO L0
+ | | | | catch java.lang.Exception -> E0
+ | | | | E0: ASTORE_2
+ | | | | local 2: java.lang.Exception e
+ | | | | | ALOAD_1
+ | | | | | ALOAD_2
+ | | | | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | | | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | | local 2: java.lang.Exception e
+ | | | finally -> E1
+ | | | GOTO L0
+ | | | E1: ASTORE 4
+ | | | JSR L1
+ | | | ALOAD 4
+ | | | ATHROW
+ | | | L0: JSR L1
+ | | | GOTO L2
+ | | | L1: ASTORE_3
+ | | | ALOAD_1
+ | | | LDC "finally"
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | RET 3
+ | | local 1: java.io.PrintStream out
+ | local 0: java.lang.String[] args
+ | L2: RETURN
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0
+ | ISTORE_0
+ | local 0: int x
+ | | ILOAD_0
+ | | LDC "name"
+ | | method-call(int java.lang.String.hashCode())
+ | | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | | | DUP
+ | | | ISTORE_1
+ | | | ILOAD_1
+ | | | INVOKESTATIC org.aspectj.runtime.internal.Conversions.intObject (I)Ljava/lang/Object;
+ | | | INVOKESTATIC Aspect.ajc_afterReturning_field_get (Ljava/lang/Object;)V
+ | | method-call(int java.lang.String.hashCode())
+ | | IADD
+ | | ISTORE_0
+ | | NEW java.lang.StringBuffer
+ | | DUP
+ | | LDC "name"
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | | ILOAD_0
+ | | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | local 0: int x
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/AfterReturningFancyHelloWorld.txt b/weaver/testdata/AfterReturningFancyHelloWorld.txt
new file mode 100644
index 000000000..1bcdad132
--- /dev/null
+++ b/weaver/testdata/AfterReturningFancyHelloWorld.txt
@@ -0,0 +1,101 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | GOTO L0
+ | L0: INVOKESTATIC Aspect.ajc_afterReturning_constructor_execution ()V
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | | INVOKESTATIC Aspect.ajc_afterReturning_field_get ()V
+ | | NOP
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | ASTORE_1
+ | finally -> E1
+ | | catch java.lang.Exception -> E0
+ | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | LDC "bye"
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | | INVOKESTATIC Aspect.ajc_afterReturning_method_call ()V
+ | | | | NOP
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | GOTO L0
+ | | catch java.lang.Exception -> E0
+ | | E0: ASTORE_2 (line 12)
+ | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | ALOAD_2 // java.lang.Exception e
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | | INVOKESTATIC Aspect.ajc_afterReturning_method_call ()V
+ | | | NOP
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | finally -> E1
+ | GOTO L0
+ | E1: ASTORE 4 (line 14)
+ | JSR L1
+ | ALOAD 4
+ | ATHROW
+ | L0: JSR L1
+ | GOTO L2
+ | L1: ASTORE_3
+ | ALOAD_1 // java.io.PrintStream out (line 15)
+ | LDC "finally"
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | INVOKESTATIC Aspect.ajc_afterReturning_method_call ()V
+ | | NOP
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RET 3 (line 10)
+ | L2: GOTO L3 (line 17)
+ | L3: INVOKESTATIC Aspect.ajc_afterReturning_method_execution ()V
+ | RETURN
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | | INVOKESTATIC Aspect.ajc_afterReturning_method_call ()V
+ | | NOP
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | LDC "name" (line 22)
+ | ASTORE_1
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | NEW java.lang.StringBuffer
+ | | DUP
+ | | ALOAD_1
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | | INVOKESTATIC Aspect.ajc_afterReturning_constructor_call ()V
+ | | NOP
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | | INVOKESTATIC Aspect.ajc_afterReturning_method_call ()V
+ | | NOP
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | | INVOKESTATIC Aspect.ajc_afterReturning_method_call ()V
+ | | NOP
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | GOTO L0
+ | L0: INVOKESTATIC Aspect.ajc_afterReturning_method_execution ()V
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/AfterReturningHelloWorld.txt b/weaver/testdata/AfterReturningHelloWorld.txt
new file mode 100644
index 000000000..271a34b38
--- /dev/null
+++ b/weaver/testdata/AfterReturningHelloWorld.txt
@@ -0,0 +1,30 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | GOTO L0
+ | L0: INVOKESTATIC Aspect.ajc_afterReturning_constructor_execution ()V
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | | INVOKESTATIC Aspect.ajc_afterReturning_field_get ()V
+ | | NOP
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | INVOKESTATIC Aspect.ajc_afterReturning_method_call ()V
+ | | NOP
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | GOTO L0 (line 11)
+ | L0: INVOKESTATIC Aspect.ajc_afterReturning_method_execution ()V
+ | RETURN
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/AfterReturningParamFancyHelloWorld.txt b/weaver/testdata/AfterReturningParamFancyHelloWorld.txt
new file mode 100644
index 000000000..959862843
--- /dev/null
+++ b/weaver/testdata/AfterReturningParamFancyHelloWorld.txt
@@ -0,0 +1,82 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | | DUP
+ | | ASTORE 5
+ | | ALOAD 5
+ | | INVOKESTATIC Aspect.ajc_afterReturning_field_get (Ljava/lang/Object;)V
+ | | NOP
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | ASTORE_1
+ | finally -> E1
+ | | catch java.lang.Exception -> E0
+ | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | LDC "bye"
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | GOTO L0
+ | | catch java.lang.Exception -> E0
+ | | E0: ASTORE_2 (line 12)
+ | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | ALOAD_2 // java.lang.Exception e
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | finally -> E1
+ | GOTO L0
+ | E1: ASTORE 4 (line 14)
+ | JSR L1
+ | ALOAD 4
+ | ATHROW
+ | L0: JSR L1
+ | GOTO L2
+ | L1: ASTORE_3
+ | ALOAD_1 // java.io.PrintStream out (line 15)
+ | LDC "finally"
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RET 3 (line 10)
+ | L2: RETURN (line 17)
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | NEW java.lang.StringBuffer (line 22)
+ | DUP
+ | LDC "name"
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/AfterReturningParamHelloWorld.txt b/weaver/testdata/AfterReturningParamHelloWorld.txt
new file mode 100644
index 000000000..6da75a8f8
--- /dev/null
+++ b/weaver/testdata/AfterReturningParamHelloWorld.txt
@@ -0,0 +1,27 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | | DUP
+ | | ASTORE_1
+ | | ALOAD_1
+ | | INVOKESTATIC Aspect.ajc_afterReturning_field_get (Ljava/lang/Object;)V
+ | | NOP
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/AfterThrowingFancyHelloWorld.txt b/weaver/testdata/AfterThrowingFancyHelloWorld.txt
new file mode 100644
index 000000000..ed9e89bfd
--- /dev/null
+++ b/weaver/testdata/AfterThrowingFancyHelloWorld.txt
@@ -0,0 +1,161 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | catch java.lang.Throwable -> E0
+ | | RETURN
+ | catch java.lang.Throwable -> E0
+ | E0: ASTORE_1
+ | INVOKESTATIC Aspect.ajc_afterThrowing_constructor_execution ()V
+ | ALOAD_1
+ | ATHROW
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | catch java.lang.Throwable -> E6
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | | catch java.lang.Throwable -> E3
+ | | | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | | | catch java.lang.Throwable -> E3
+ | | | GOTO L0
+ | | | E3: ASTORE 5
+ | | | INVOKESTATIC Aspect.ajc_afterThrowing_field_get ()V
+ | | | ALOAD 5
+ | | | ATHROW
+ | | | L0: NOP
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | ASTORE_1
+ | | finally -> E5
+ | | | catch java.lang.Exception -> E4
+ | | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | | LDC "bye"
+ | | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | | catch java.lang.Throwable -> E2
+ | | | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | | | catch java.lang.Throwable -> E2
+ | | | | | GOTO L1
+ | | | | | E2: ASTORE 6
+ | | | | | INVOKESTATIC Aspect.ajc_afterThrowing_method_call ()V
+ | | | | | ALOAD 6
+ | | | | | ATHROW
+ | | | | | L1: NOP
+ | | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | GOTO L3
+ | | | catch java.lang.Exception -> E4
+ | | | E4: ASTORE_2 (line 12)
+ | | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | | ALOAD_2 // java.lang.Exception e
+ | | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | | catch java.lang.Throwable -> E1
+ | | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | | | catch java.lang.Throwable -> E1
+ | | | | GOTO L2
+ | | | | E1: ASTORE 7
+ | | | | INVOKESTATIC Aspect.ajc_afterThrowing_method_call ()V
+ | | | | ALOAD 7
+ | | | | ATHROW
+ | | | | L2: NOP
+ | | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | finally -> E5
+ | | GOTO L3
+ | | E5: ASTORE 4 (line 14)
+ | | JSR L4
+ | | ALOAD 4
+ | | ATHROW
+ | | L3: JSR L4
+ | | GOTO L6
+ | | L4: ASTORE_3
+ | | ALOAD_1 // java.io.PrintStream out (line 15)
+ | | LDC "finally"
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | catch java.lang.Throwable -> E0
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | catch java.lang.Throwable -> E0
+ | | | GOTO L5
+ | | | E0: ASTORE 8
+ | | | INVOKESTATIC Aspect.ajc_afterThrowing_method_call ()V
+ | | | ALOAD 8
+ | | | ATHROW
+ | | | L5: NOP
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | RET 3 (line 10)
+ | | L6: RETURN (line 17)
+ | catch java.lang.Throwable -> E6
+ | E6: ASTORE 9
+ | INVOKESTATIC Aspect.ajc_afterThrowing_method_execution ()V
+ | ALOAD 9
+ | ATHROW
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | catch java.lang.Throwable -> E4
+ | | ICONST_0 (line 20)
+ | | ISTORE_0
+ | | ILOAD_0 // int x (line 21)
+ | | LDC "name"
+ | | method-call(int java.lang.String.hashCode())
+ | | | catch java.lang.Throwable -> E3
+ | | | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | | | catch java.lang.Throwable -> E3
+ | | | GOTO L0
+ | | | E3: ASTORE_1
+ | | | INVOKESTATIC Aspect.ajc_afterThrowing_method_call ()V
+ | | | ALOAD_1
+ | | | ATHROW
+ | | | L0: NOP
+ | | method-call(int java.lang.String.hashCode())
+ | | IADD
+ | | ISTORE_0 // int x
+ | | LDC "name" (line 22)
+ | | ASTORE_2
+ | | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | | catch java.lang.Throwable -> E2
+ | | | | NEW java.lang.StringBuffer
+ | | | | DUP
+ | | | | ALOAD_2
+ | | | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | | | catch java.lang.Throwable -> E2
+ | | | GOTO L1
+ | | | E2: ASTORE_3
+ | | | INVOKESTATIC Aspect.ajc_afterThrowing_constructor_call ()V
+ | | | ALOAD_3
+ | | | ATHROW
+ | | | L1: NOP
+ | | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | ILOAD_0 // int x
+ | | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | | catch java.lang.Throwable -> E1
+ | | | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | | | catch java.lang.Throwable -> E1
+ | | | GOTO L2
+ | | | E1: ASTORE 4
+ | | | INVOKESTATIC Aspect.ajc_afterThrowing_method_call ()V
+ | | | ALOAD 4
+ | | | ATHROW
+ | | | L2: NOP
+ | | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | | catch java.lang.Throwable -> E0
+ | | | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | | | catch java.lang.Throwable -> E0
+ | | | GOTO L3
+ | | | E0: ASTORE 5
+ | | | INVOKESTATIC Aspect.ajc_afterThrowing_method_call ()V
+ | | | ALOAD 5
+ | | | ATHROW
+ | | | L3: NOP
+ | | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | ARETURN
+ | catch java.lang.Throwable -> E4
+ | E4: ASTORE 6
+ | INVOKESTATIC Aspect.ajc_afterThrowing_method_execution ()V
+ | ALOAD 6
+ | ATHROW
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/AfterThrowingHelloWorld.txt b/weaver/testdata/AfterThrowingHelloWorld.txt
new file mode 100644
index 000000000..6b307e761
--- /dev/null
+++ b/weaver/testdata/AfterThrowingHelloWorld.txt
@@ -0,0 +1,50 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | catch java.lang.Throwable -> E0
+ | | RETURN
+ | catch java.lang.Throwable -> E0
+ | E0: ASTORE_1
+ | INVOKESTATIC Aspect.ajc_afterThrowing_constructor_execution ()V
+ | ALOAD_1
+ | ATHROW
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | catch java.lang.Throwable -> E2
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | | catch java.lang.Throwable -> E1
+ | | | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | | | catch java.lang.Throwable -> E1
+ | | | GOTO L0
+ | | | E1: ASTORE_1
+ | | | INVOKESTATIC Aspect.ajc_afterThrowing_field_get ()V
+ | | | ALOAD_1
+ | | | ATHROW
+ | | | L0: NOP
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | LDC "hello world" (line 9)
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | catch java.lang.Throwable -> E0
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | catch java.lang.Throwable -> E0
+ | | | GOTO L1
+ | | | E0: ASTORE_2
+ | | | INVOKESTATIC Aspect.ajc_afterThrowing_method_call ()V
+ | | | ALOAD_2
+ | | | ATHROW
+ | | | L1: NOP
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | RETURN (line 11)
+ | catch java.lang.Throwable -> E2
+ | E2: ASTORE_3
+ | INVOKESTATIC Aspect.ajc_afterThrowing_method_execution ()V
+ | ALOAD_3
+ | ATHROW
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/AfterThrowingParamFancyHelloWorld.txt b/weaver/testdata/AfterThrowingParamFancyHelloWorld.txt
new file mode 100644
index 000000000..351d35649
--- /dev/null
+++ b/weaver/testdata/AfterThrowingParamFancyHelloWorld.txt
@@ -0,0 +1,86 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | catch java.lang.Throwable -> E0
+ | | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | | catch java.lang.Throwable -> E0
+ | | GOTO L0
+ | | E0: ASTORE 5
+ | | ALOAD 5
+ | | INVOKESTATIC Aspect.ajc_afterThrowing_field_get (Ljava/lang/Throwable;)V
+ | | ALOAD 5
+ | | ATHROW
+ | | L0: NOP
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | ASTORE_1
+ | finally -> E2
+ | | catch java.lang.Exception -> E1
+ | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | LDC "bye"
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | GOTO L1
+ | | catch java.lang.Exception -> E1
+ | | E1: ASTORE_2 (line 12)
+ | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | ALOAD_2 // java.lang.Exception e
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | finally -> E2
+ | GOTO L1
+ | E2: ASTORE 4 (line 14)
+ | JSR L2
+ | ALOAD 4
+ | ATHROW
+ | L1: JSR L2
+ | GOTO L3
+ | L2: ASTORE_3
+ | ALOAD_1 // java.io.PrintStream out (line 15)
+ | LDC "finally"
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RET 3 (line 10)
+ | L3: RETURN (line 17)
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | NEW java.lang.StringBuffer (line 22)
+ | DUP
+ | LDC "name"
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/AfterThrowingParamHelloWorld.txt b/weaver/testdata/AfterThrowingParamHelloWorld.txt
new file mode 100644
index 000000000..c94486d22
--- /dev/null
+++ b/weaver/testdata/AfterThrowingParamHelloWorld.txt
@@ -0,0 +1,31 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | catch java.lang.Throwable -> E0
+ | | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | | catch java.lang.Throwable -> E0
+ | | GOTO L0
+ | | E0: ASTORE_1
+ | | ALOAD_1
+ | | INVOKESTATIC Aspect.ajc_afterThrowing_field_get (Ljava/lang/Throwable;)V
+ | | ALOAD_1
+ | | ATHROW
+ | | L0: NOP
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/ArgsAfterReturningFancyHelloWorld.txt b/weaver/testdata/ArgsAfterReturningFancyHelloWorld.txt
new file mode 100644
index 000000000..1aa2a4f09
--- /dev/null
+++ b/weaver/testdata/ArgsAfterReturningFancyHelloWorld.txt
@@ -0,0 +1,108 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ ALOAD_0
+ ASTORE 8
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | ASTORE_1
+ | finally -> E1
+ | | catch java.lang.Exception -> E0
+ | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | LDC "bye"
+ | | | ASTORE 5
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | ALOAD 5
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | | ALOAD 5
+ | | | | INVOKESTATIC Aspect.ajc_afterReturning_method_call (Ljava/lang/Object;)V
+ | | | | NOP
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | GOTO L0
+ | | catch java.lang.Exception -> E0
+ | | E0: ASTORE_2 (line 12)
+ | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | ALOAD_2 // java.lang.Exception e
+ | | ASTORE 6
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | ALOAD 6
+ | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | | ALOAD 6
+ | | | INVOKESTATIC Aspect.ajc_afterReturning_method_call (Ljava/lang/Object;)V
+ | | | NOP
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | finally -> E1
+ | GOTO L0
+ | E1: ASTORE 4 (line 14)
+ | JSR L1
+ | ALOAD 4
+ | ATHROW
+ | L0: JSR L1
+ | GOTO L2
+ | L1: ASTORE_3
+ | ALOAD_1 // java.io.PrintStream out (line 15)
+ | LDC "finally"
+ | ASTORE 7
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | ALOAD 7
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | ALOAD 7
+ | | INVOKESTATIC Aspect.ajc_afterReturning_method_call (Ljava/lang/Object;)V
+ | | NOP
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RET 3 (line 10)
+ | L2: GOTO L3 (line 17)
+ | L3: ALOAD 8
+ | INVOKESTATIC Aspect.ajc_afterReturning_method_execution (Ljava/lang/Object;)V
+ | RETURN
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | LDC "name" (line 22)
+ | ASTORE_1
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | NEW java.lang.StringBuffer
+ | | DUP
+ | | ALOAD_1
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | | ALOAD_1
+ | | INVOKESTATIC Aspect.ajc_afterReturning_constructor_call (Ljava/lang/Object;)V
+ | | NOP
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | ISTORE_2
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | ILOAD_2
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | | ILOAD_2
+ | | INVOKESTATIC org.aspectj.runtime.internal.Conversions.intObject (I)Ljava/lang/Object;
+ | | INVOKESTATIC Aspect.ajc_afterReturning_method_call (Ljava/lang/Object;)V
+ | | NOP
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/ArgsAfterReturningHelloWorld.txt b/weaver/testdata/ArgsAfterReturningHelloWorld.txt
new file mode 100644
index 000000000..1b3c0e0e7
--- /dev/null
+++ b/weaver/testdata/ArgsAfterReturningHelloWorld.txt
@@ -0,0 +1,32 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ ALOAD_0
+ ASTORE_2
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | ASTORE_1
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | ALOAD_1
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | ALOAD_1
+ | | INVOKESTATIC Aspect.ajc_afterReturning_method_call (Ljava/lang/Object;)V
+ | | NOP
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | GOTO L0 (line 11)
+ | L0: ALOAD_2
+ | INVOKESTATIC Aspect.ajc_afterReturning_method_execution (Ljava/lang/Object;)V
+ | RETURN
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/ArgsAfterThrowingHelloWorld.txt b/weaver/testdata/ArgsAfterThrowingHelloWorld.txt
new file mode 100644
index 000000000..e71e5a4f1
--- /dev/null
+++ b/weaver/testdata/ArgsAfterThrowingHelloWorld.txt
@@ -0,0 +1,42 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ ALOAD_0
+ ASTORE_3
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | catch java.lang.Throwable -> E1
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | LDC "hello world" (line 9)
+ | | ASTORE_1
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | catch java.lang.Throwable -> E0
+ | | | | ALOAD_1
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | catch java.lang.Throwable -> E0
+ | | | GOTO L0
+ | | | E0: ASTORE_2
+ | | | ALOAD_1
+ | | | INVOKESTATIC Aspect.ajc_afterThrowing_method_call (Ljava/lang/Object;)V
+ | | | ALOAD_2
+ | | | ATHROW
+ | | | L0: NOP
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | RETURN (line 11)
+ | catch java.lang.Throwable -> E1
+ | E1: ASTORE 4
+ | ALOAD_3
+ | INVOKESTATIC Aspect.ajc_afterThrowing_method_execution (Ljava/lang/Object;)V
+ | ALOAD 4
+ | ATHROW
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/ArgsBeforeAfterHelloWorld.txt b/weaver/testdata/ArgsBeforeAfterHelloWorld.txt
new file mode 100644
index 000000000..cddac2323
--- /dev/null
+++ b/weaver/testdata/ArgsBeforeAfterHelloWorld.txt
@@ -0,0 +1,52 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ ALOAD_0
+ ASTORE_3
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | catch java.lang.Throwable -> E1
+ | | ALOAD_3
+ | | INVOKESTATIC Aspect.ajc_before_method_execution (Ljava/lang/Object;)V
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | LDC "hello world" (line 9)
+ | | ASTORE_1
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | catch java.lang.Throwable -> E0
+ | | | | ALOAD_1
+ | | | | INVOKESTATIC Aspect.ajc_before_method_call (Ljava/lang/Object;)V
+ | | | | ALOAD_1
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | catch java.lang.Throwable -> E0
+ | | | GOTO L0
+ | | | E0: ASTORE_2
+ | | | ALOAD_1
+ | | | INVOKESTATIC Aspect.ajc_afterThrowing_method_call (Ljava/lang/Object;)V
+ | | | ALOAD_2
+ | | | ATHROW
+ | | | L0: NOP
+ | | | ALOAD_1
+ | | | INVOKESTATIC Aspect.ajc_afterReturning_method_call (Ljava/lang/Object;)V
+ | | | NOP
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | GOTO L1 (line 11)
+ | catch java.lang.Throwable -> E1
+ | E1: ASTORE 4
+ | ALOAD_3
+ | INVOKESTATIC Aspect.ajc_afterThrowing_method_execution (Ljava/lang/Object;)V
+ | ALOAD 4
+ | ATHROW
+ | L1: ALOAD_3
+ | INVOKESTATIC Aspect.ajc_afterReturning_method_execution (Ljava/lang/Object;)V
+ | RETURN
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/AroundAllAndOthersFancyHelloWorld.txt b/weaver/testdata/AroundAllAndOthersFancyHelloWorld.txt
new file mode 100644
index 000000000..fd5984ed4
--- /dev/null
+++ b/weaver/testdata/AroundAllAndOthersFancyHelloWorld.txt
@@ -0,0 +1,1003 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | INVOKESTATIC Aspect.ajc_before_constructor_execution ()V
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE_2
+ | ALOAD_2
+ | BIPUSH 0
+ | ALOAD_0
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure3
+ | DUP
+ | ALOAD_2
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure3.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | POP
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ ALOAD_0
+ ASTORE 19
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE 21
+ | ALOAD 21
+ | BIPUSH 0
+ | ALOAD 19
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure23
+ | DUP
+ | ALOAD 21
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure23.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | POP
+ | RETURN
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ | BIPUSH 0
+ | ANEWARRAY java.lang.Object
+ | ASTORE 15
+ | NEW FancyHelloWorld$AjcClosure43
+ | DUP
+ | ALOAD 15
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure43.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | CHECKCAST java.lang.String
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+
+ static final void init$_aroundBody0(FancyHelloWorld):
+ RETURN (line 7)
+ end static final void init$_aroundBody0(FancyHelloWorld)
+
+ static final void init$_aroundBody2(FancyHelloWorld):
+ INVOKESTATIC Aspect.ajc_before_constructor_execution ()V
+ BIPUSH 1
+ ANEWARRAY java.lang.Object
+ ASTORE_1
+ ALOAD_1
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ NEW FancyHelloWorld$AjcClosure1
+ DUP
+ ALOAD_1
+ INVOKESPECIAL FancyHelloWorld$AjcClosure1.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void init$_aroundBody2(FancyHelloWorld)
+
+ static final java.io.PrintStream out_aroundBody4():
+ GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ ARETURN
+ end static final java.io.PrintStream out_aroundBody4()
+
+ static final java.io.PrintStream out_aroundBody6():
+ INVOKESTATIC Aspect.ajc_before_field_get ()V
+ BIPUSH 0
+ ANEWARRAY java.lang.Object
+ ASTORE_0
+ NEW FancyHelloWorld$AjcClosure5
+ DUP
+ ALOAD_0
+ INVOKESPECIAL FancyHelloWorld$AjcClosure5.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ CHECKCAST java.io.PrintStream
+ ARETURN
+ end static final java.io.PrintStream out_aroundBody6()
+
+ static final void println_aroundBody8(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 11)
+ RETURN
+ end static final void println_aroundBody8(java.io.PrintStream, String)
+
+ static final void println_aroundBody10(java.io.PrintStream, String):
+ INVOKESTATIC Aspect.ajc_before_method_call ()V
+ BIPUSH 2
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ ALOAD_2
+ BIPUSH 1
+ ALOAD_1
+ AASTORE
+ NEW FancyHelloWorld$AjcClosure9
+ DUP
+ ALOAD_2
+ INVOKESPECIAL FancyHelloWorld$AjcClosure9.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void println_aroundBody10(java.io.PrintStream, String)
+
+ static final void println_aroundBody12(java.io.PrintStream, Object):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V (line 13)
+ RETURN
+ end static final void println_aroundBody12(java.io.PrintStream, Object)
+
+ static final void println_aroundBody14(java.io.PrintStream, Object):
+ INVOKESTATIC Aspect.ajc_before_method_call ()V
+ BIPUSH 2
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ ALOAD_2
+ BIPUSH 1
+ ALOAD_1
+ AASTORE
+ NEW FancyHelloWorld$AjcClosure13
+ DUP
+ ALOAD_2
+ INVOKESPECIAL FancyHelloWorld$AjcClosure13.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void println_aroundBody14(java.io.PrintStream, Object)
+
+ static final void println_aroundBody16(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 15)
+ RETURN
+ end static final void println_aroundBody16(java.io.PrintStream, String)
+
+ static final void println_aroundBody18(java.io.PrintStream, String):
+ INVOKESTATIC Aspect.ajc_before_method_call ()V
+ BIPUSH 2
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ ALOAD_2
+ BIPUSH 1
+ ALOAD_1
+ AASTORE
+ NEW FancyHelloWorld$AjcClosure17
+ DUP
+ ALOAD_2
+ INVOKESPECIAL FancyHelloWorld$AjcClosure17.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void println_aroundBody18(java.io.PrintStream, String)
+
+ static final void main_aroundBody20(String[]):
+ field-get(java.io.PrintStream java.lang.System.out)
+ | INVOKESTATIC Aspect.ajc_before_field_get ()V
+ | BIPUSH 0
+ | ANEWARRAY java.lang.Object
+ | ASTORE_1
+ | NEW FancyHelloWorld$AjcClosure7
+ | DUP
+ | ALOAD_1
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure7.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | CHECKCAST java.io.PrintStream
+ field-get(java.io.PrintStream java.lang.System.out)
+ ASTORE_3 (line 9)
+ finally -> E1
+ | catch java.lang.Exception -> E0
+ | | ALOAD_3 (line 11)
+ | | LDC "bye"
+ | | ASTORE 5
+ | | ASTORE 7
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | | | BIPUSH 2
+ | | | ANEWARRAY java.lang.Object
+ | | | ASTORE 9
+ | | | ALOAD 9
+ | | | BIPUSH 0
+ | | | ALOAD 7
+ | | | AASTORE
+ | | | ALOAD 9
+ | | | BIPUSH 1
+ | | | ALOAD 5
+ | | | AASTORE
+ | | | NEW FancyHelloWorld$AjcClosure11
+ | | | DUP
+ | | | ALOAD 9
+ | | | INVOKESPECIAL FancyHelloWorld$AjcClosure11.<init> ([Ljava/lang/Object;)V
+ | | | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | | | POP
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | GOTO L0
+ | catch java.lang.Exception -> E0
+ | E0: ASTORE 11 (line 12)
+ | ALOAD_3 (line 13)
+ | ALOAD 11
+ | ASTORE 13
+ | ASTORE 15
+ | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | | BIPUSH 2
+ | | ANEWARRAY java.lang.Object
+ | | ASTORE 17
+ | | ALOAD 17
+ | | BIPUSH 0
+ | | ALOAD 15
+ | | AASTORE
+ | | ALOAD 17
+ | | BIPUSH 1
+ | | ALOAD 13
+ | | AASTORE
+ | | NEW FancyHelloWorld$AjcClosure15
+ | | DUP
+ | | ALOAD 17
+ | | INVOKESPECIAL FancyHelloWorld$AjcClosure15.<init> ([Ljava/lang/Object;)V
+ | | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | | POP
+ | method-call(void java.io.PrintStream.println(java.lang.Object))
+ finally -> E1
+ GOTO L0
+ E1: ASTORE 19 (line 14)
+ JSR L1
+ ALOAD 19
+ ATHROW
+ L0: JSR L1
+ GOTO L2
+ L1: ASTORE 21
+ ALOAD_3 (line 15)
+ LDC "finally"
+ ASTORE 23
+ ASTORE 25
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | BIPUSH 2
+ | ANEWARRAY java.lang.Object
+ | ASTORE 27
+ | ALOAD 27
+ | BIPUSH 0
+ | ALOAD 25
+ | AASTORE
+ | ALOAD 27
+ | BIPUSH 1
+ | ALOAD 23
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure19
+ | DUP
+ | ALOAD 27
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure19.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | POP
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ RET 21 (line 10)
+ L2: RETURN (line 17)
+ end static final void main_aroundBody20(String[])
+
+ static final void main_aroundBody22(String[]):
+ INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ BIPUSH 1
+ ANEWARRAY java.lang.Object
+ ASTORE_1
+ ALOAD_1
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ NEW FancyHelloWorld$AjcClosure21
+ DUP
+ ALOAD_1
+ INVOKESPECIAL FancyHelloWorld$AjcClosure21.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void main_aroundBody22(String[])
+
+ static final int hashCode_aroundBody24(String):
+ ALOAD_0
+ INVOKEVIRTUAL java.lang.String.hashCode ()I (line 21)
+ IRETURN
+ end static final int hashCode_aroundBody24(String)
+
+ static final int hashCode_aroundBody26(String):
+ INVOKESTATIC Aspect.ajc_before_method_call ()V
+ BIPUSH 1
+ ANEWARRAY java.lang.Object
+ ASTORE_1
+ ALOAD_1
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ NEW FancyHelloWorld$AjcClosure25
+ DUP
+ ALOAD_1
+ INVOKESPECIAL FancyHelloWorld$AjcClosure25.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ INVOKESTATIC org.aspectj.runtime.internal.Conversions.intValue (Ljava/lang/Object;)I
+ IRETURN
+ end static final int hashCode_aroundBody26(String)
+
+ static final StringBuffer init$_aroundBody28(String):
+ NEW java.lang.StringBuffer
+ DUP
+ ALOAD_0
+ INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V (line 22)
+ ARETURN
+ end static final StringBuffer init$_aroundBody28(String)
+
+ static final StringBuffer init$_aroundBody30(String):
+ INVOKESTATIC Aspect.ajc_before_constructor_call ()V
+ BIPUSH 1
+ ANEWARRAY java.lang.Object
+ ASTORE_1
+ ALOAD_1
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ NEW FancyHelloWorld$AjcClosure29
+ DUP
+ ALOAD_1
+ INVOKESPECIAL FancyHelloWorld$AjcClosure29.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ CHECKCAST java.lang.StringBuffer
+ ARETURN
+ end static final StringBuffer init$_aroundBody30(String)
+
+ static final StringBuffer append_aroundBody32(StringBuffer, int):
+ ALOAD_0
+ ILOAD_1
+ INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer; (line 22)
+ ARETURN
+ end static final StringBuffer append_aroundBody32(StringBuffer, int)
+
+ static final StringBuffer append_aroundBody34(StringBuffer, int):
+ INVOKESTATIC Aspect.ajc_before_method_call ()V
+ BIPUSH 2
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ ALOAD_2
+ BIPUSH 1
+ ILOAD_1
+ INVOKESTATIC org.aspectj.runtime.internal.Conversions.intObject (I)Ljava/lang/Object;
+ AASTORE
+ NEW FancyHelloWorld$AjcClosure33
+ DUP
+ ALOAD_2
+ INVOKESPECIAL FancyHelloWorld$AjcClosure33.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ CHECKCAST java.lang.StringBuffer
+ ARETURN
+ end static final StringBuffer append_aroundBody34(StringBuffer, int)
+
+ static final String toString_aroundBody36(StringBuffer):
+ ALOAD_0
+ INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String; (line 22)
+ ARETURN
+ end static final String toString_aroundBody36(StringBuffer)
+
+ static final String toString_aroundBody38(StringBuffer):
+ INVOKESTATIC Aspect.ajc_before_method_call ()V
+ BIPUSH 1
+ ANEWARRAY java.lang.Object
+ ASTORE_1
+ ALOAD_1
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ NEW FancyHelloWorld$AjcClosure37
+ DUP
+ ALOAD_1
+ INVOKESPECIAL FancyHelloWorld$AjcClosure37.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ CHECKCAST java.lang.String
+ ARETURN
+ end static final String toString_aroundBody38(StringBuffer)
+
+ static final String getName_aroundBody40():
+ ICONST_0 (line 20)
+ ISTORE_0
+ ILOAD_0 (line 21)
+ LDC "name"
+ ASTORE_2
+ method-call(int java.lang.String.hashCode())
+ | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE 4
+ | ALOAD 4
+ | BIPUSH 0
+ | ALOAD_2
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure27
+ | DUP
+ | ALOAD 4
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure27.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | INVOKESTATIC org.aspectj.runtime.internal.Conversions.intValue (Ljava/lang/Object;)I
+ method-call(int java.lang.String.hashCode())
+ IADD
+ ISTORE_0
+ LDC "name" (line 22)
+ ASTORE 6
+ constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | INVOKESTATIC Aspect.ajc_before_constructor_call ()V
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE 8
+ | ALOAD 8
+ | BIPUSH 0
+ | ALOAD 6
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure31
+ | DUP
+ | ALOAD 8
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure31.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | CHECKCAST java.lang.StringBuffer
+ constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ ILOAD_0
+ ISTORE 10
+ ASTORE 12
+ method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | BIPUSH 2
+ | ANEWARRAY java.lang.Object
+ | ASTORE 14
+ | ALOAD 14
+ | BIPUSH 0
+ | ALOAD 12
+ | AASTORE
+ | ALOAD 14
+ | BIPUSH 1
+ | ILOAD 10
+ | INVOKESTATIC org.aspectj.runtime.internal.Conversions.intObject (I)Ljava/lang/Object;
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure35
+ | DUP
+ | ALOAD 14
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure35.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | CHECKCAST java.lang.StringBuffer
+ method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ ASTORE 16
+ method-call(java.lang.String java.lang.StringBuffer.toString())
+ | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE 18
+ | ALOAD 18
+ | BIPUSH 0
+ | ALOAD 16
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure39
+ | DUP
+ | ALOAD 18
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure39.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | CHECKCAST java.lang.String
+ method-call(java.lang.String java.lang.StringBuffer.toString())
+ ARETURN
+ end static final String getName_aroundBody40()
+
+ static final String getName_aroundBody42():
+ INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ BIPUSH 0
+ ANEWARRAY java.lang.Object
+ ASTORE_0
+ NEW FancyHelloWorld$AjcClosure41
+ DUP
+ ALOAD_0
+ INVOKESPECIAL FancyHelloWorld$AjcClosure41.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ CHECKCAST java.lang.String
+ ARETURN
+ end static final String getName_aroundBody42()
+end public abstract class FancyHelloWorld
+
+public class FancyHelloWorld$AjcClosure1 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST FancyHelloWorld
+ INVOKESTATIC FancyHelloWorld.init$_aroundBody0 (LFancyHelloWorld;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure1
+
+public class FancyHelloWorld$AjcClosure3 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST FancyHelloWorld
+ INVOKESTATIC FancyHelloWorld.init$_aroundBody2 (LFancyHelloWorld;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure3
+
+public class FancyHelloWorld$AjcClosure5 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ INVOKESTATIC FancyHelloWorld.out_aroundBody4 ()Ljava/io/PrintStream;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure5
+
+public class FancyHelloWorld$AjcClosure7 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ INVOKESTATIC FancyHelloWorld.out_aroundBody6 ()Ljava/io/PrintStream;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure7
+
+public class FancyHelloWorld$AjcClosure9 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.println_aroundBody8 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure9
+
+public class FancyHelloWorld$AjcClosure11 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.println_aroundBody10 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure11
+
+public class FancyHelloWorld$AjcClosure13 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ INVOKESTATIC FancyHelloWorld.println_aroundBody12 (Ljava/io/PrintStream;Ljava/lang/Object;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure13
+
+public class FancyHelloWorld$AjcClosure15 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ INVOKESTATIC FancyHelloWorld.println_aroundBody14 (Ljava/io/PrintStream;Ljava/lang/Object;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure15
+
+public class FancyHelloWorld$AjcClosure17 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.println_aroundBody16 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure17
+
+public class FancyHelloWorld$AjcClosure19 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.println_aroundBody18 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure19
+
+public class FancyHelloWorld$AjcClosure21 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST [Ljava.lang.String;
+ INVOKESTATIC FancyHelloWorld.main_aroundBody20 ([Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure21
+
+public class FancyHelloWorld$AjcClosure23 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST [Ljava.lang.String;
+ INVOKESTATIC FancyHelloWorld.main_aroundBody22 ([Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure23
+
+public class FancyHelloWorld$AjcClosure25 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.hashCode_aroundBody24 (Ljava/lang/String;)I
+ INVOKESTATIC org.aspectj.runtime.internal.Conversions.intObject (I)Ljava/lang/Object;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure25
+
+public class FancyHelloWorld$AjcClosure27 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.hashCode_aroundBody26 (Ljava/lang/String;)I
+ INVOKESTATIC org.aspectj.runtime.internal.Conversions.intObject (I)Ljava/lang/Object;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure27
+
+public class FancyHelloWorld$AjcClosure29 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.init$_aroundBody28 (Ljava/lang/String;)Ljava/lang/StringBuffer;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure29
+
+public class FancyHelloWorld$AjcClosure31 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.init$_aroundBody30 (Ljava/lang/String;)Ljava/lang/StringBuffer;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure31
+
+public class FancyHelloWorld$AjcClosure33 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.lang.StringBuffer
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ INVOKESTATIC org.aspectj.runtime.internal.Conversions.intValue (Ljava/lang/Object;)I
+ INVOKESTATIC FancyHelloWorld.append_aroundBody32 (Ljava/lang/StringBuffer;I)Ljava/lang/StringBuffer;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure33
+
+public class FancyHelloWorld$AjcClosure35 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.lang.StringBuffer
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ INVOKESTATIC org.aspectj.runtime.internal.Conversions.intValue (Ljava/lang/Object;)I
+ INVOKESTATIC FancyHelloWorld.append_aroundBody34 (Ljava/lang/StringBuffer;I)Ljava/lang/StringBuffer;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure35
+
+public class FancyHelloWorld$AjcClosure37 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.lang.StringBuffer
+ INVOKESTATIC FancyHelloWorld.toString_aroundBody36 (Ljava/lang/StringBuffer;)Ljava/lang/String;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure37
+
+public class FancyHelloWorld$AjcClosure39 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.lang.StringBuffer
+ INVOKESTATIC FancyHelloWorld.toString_aroundBody38 (Ljava/lang/StringBuffer;)Ljava/lang/String;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure39
+
+public class FancyHelloWorld$AjcClosure41 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ INVOKESTATIC FancyHelloWorld.getName_aroundBody40 ()Ljava/lang/String;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure41
+
+public class FancyHelloWorld$AjcClosure43 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ INVOKESTATIC FancyHelloWorld.getName_aroundBody42 ()Ljava/lang/String;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure43
diff --git a/weaver/testdata/AroundAllAndOthersHelloWorld.txt b/weaver/testdata/AroundAllAndOthersHelloWorld.txt
new file mode 100644
index 000000000..2175e03c6
--- /dev/null
+++ b/weaver/testdata/AroundAllAndOthersHelloWorld.txt
@@ -0,0 +1,346 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | INVOKESTATIC Aspect.ajc_before_constructor_execution ()V
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE_2
+ | ALOAD_2
+ | BIPUSH 0
+ | ALOAD_0
+ | AASTORE
+ | NEW HelloWorld$AjcClosure3
+ | DUP
+ | ALOAD_2
+ | INVOKESPECIAL HelloWorld$AjcClosure3.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | POP
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ ALOAD_0
+ ASTORE 7
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE 9
+ | ALOAD 9
+ | BIPUSH 0
+ | ALOAD 7
+ | AASTORE
+ | NEW HelloWorld$AjcClosure15
+ | DUP
+ | ALOAD 9
+ | INVOKESPECIAL HelloWorld$AjcClosure15.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | POP
+ | RETURN
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static final void init$_aroundBody0(HelloWorld):
+ RETURN (line 5)
+ end static final void init$_aroundBody0(HelloWorld)
+
+ static final void init$_aroundBody2(HelloWorld):
+ INVOKESTATIC Aspect.ajc_before_constructor_execution ()V
+ BIPUSH 1
+ ANEWARRAY java.lang.Object
+ ASTORE_1
+ ALOAD_1
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ NEW HelloWorld$AjcClosure1
+ DUP
+ ALOAD_1
+ INVOKESPECIAL HelloWorld$AjcClosure1.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void init$_aroundBody2(HelloWorld)
+
+ static final java.io.PrintStream out_aroundBody4():
+ GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ ARETURN
+ end static final java.io.PrintStream out_aroundBody4()
+
+ static final java.io.PrintStream out_aroundBody6():
+ INVOKESTATIC Aspect.ajc_before_field_get ()V
+ BIPUSH 0
+ ANEWARRAY java.lang.Object
+ ASTORE_0
+ NEW HelloWorld$AjcClosure5
+ DUP
+ ALOAD_0
+ INVOKESPECIAL HelloWorld$AjcClosure5.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ CHECKCAST java.io.PrintStream
+ ARETURN
+ end static final java.io.PrintStream out_aroundBody6()
+
+ static final void println_aroundBody8(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 9)
+ RETURN
+ end static final void println_aroundBody8(java.io.PrintStream, String)
+
+ static final void println_aroundBody10(java.io.PrintStream, String):
+ INVOKESTATIC Aspect.ajc_before_method_call ()V
+ BIPUSH 2
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ ALOAD_2
+ BIPUSH 1
+ ALOAD_1
+ AASTORE
+ NEW HelloWorld$AjcClosure9
+ DUP
+ ALOAD_2
+ INVOKESPECIAL HelloWorld$AjcClosure9.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void println_aroundBody10(java.io.PrintStream, String)
+
+ static final void main_aroundBody12(String[]):
+ field-get(java.io.PrintStream java.lang.System.out)
+ | INVOKESTATIC Aspect.ajc_before_field_get ()V
+ | BIPUSH 0
+ | ANEWARRAY java.lang.Object
+ | ASTORE_1
+ | NEW HelloWorld$AjcClosure7
+ | DUP
+ | ALOAD_1
+ | INVOKESPECIAL HelloWorld$AjcClosure7.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | CHECKCAST java.io.PrintStream
+ field-get(java.io.PrintStream java.lang.System.out)
+ LDC "hello world" (line 9)
+ ASTORE_3
+ ASTORE 5
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | BIPUSH 2
+ | ANEWARRAY java.lang.Object
+ | ASTORE 7
+ | ALOAD 7
+ | BIPUSH 0
+ | ALOAD 5
+ | AASTORE
+ | ALOAD 7
+ | BIPUSH 1
+ | ALOAD_3
+ | AASTORE
+ | NEW HelloWorld$AjcClosure11
+ | DUP
+ | ALOAD 7
+ | INVOKESPECIAL HelloWorld$AjcClosure11.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | POP
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ RETURN (line 11)
+ end static final void main_aroundBody12(String[])
+
+ static final void main_aroundBody14(String[]):
+ INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ BIPUSH 1
+ ANEWARRAY java.lang.Object
+ ASTORE_1
+ ALOAD_1
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ NEW HelloWorld$AjcClosure13
+ DUP
+ ALOAD_1
+ INVOKESPECIAL HelloWorld$AjcClosure13.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void main_aroundBody14(String[])
+end public class HelloWorld
+
+public class HelloWorld$AjcClosure1 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST HelloWorld
+ INVOKESTATIC HelloWorld.init$_aroundBody0 (LHelloWorld;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure1
+
+public class HelloWorld$AjcClosure3 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST HelloWorld
+ INVOKESTATIC HelloWorld.init$_aroundBody2 (LHelloWorld;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure3
+
+public class HelloWorld$AjcClosure5 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ INVOKESTATIC HelloWorld.out_aroundBody4 ()Ljava/io/PrintStream;
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure5
+
+public class HelloWorld$AjcClosure7 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ INVOKESTATIC HelloWorld.out_aroundBody6 ()Ljava/io/PrintStream;
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure7
+
+public class HelloWorld$AjcClosure9 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC HelloWorld.println_aroundBody8 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure9
+
+public class HelloWorld$AjcClosure11 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC HelloWorld.println_aroundBody10 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure11
+
+public class HelloWorld$AjcClosure13 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST [Ljava.lang.String;
+ INVOKESTATIC HelloWorld.main_aroundBody12 ([Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure13
+
+public class HelloWorld$AjcClosure15 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST [Ljava.lang.String;
+ INVOKESTATIC HelloWorld.main_aroundBody14 ([Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure15
diff --git a/weaver/testdata/AroundAllFancyHelloWorld.txt b/weaver/testdata/AroundAllFancyHelloWorld.txt
new file mode 100644
index 000000000..ab5412705
--- /dev/null
+++ b/weaver/testdata/AroundAllFancyHelloWorld.txt
@@ -0,0 +1,541 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE_1
+ | ALOAD_1
+ | BIPUSH 0
+ | ALOAD_0
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure1
+ | DUP
+ | ALOAD_1
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure1.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | POP
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ ALOAD_0
+ ASTORE 15
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE 16
+ | ALOAD 16
+ | BIPUSH 0
+ | ALOAD 15
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure11
+ | DUP
+ | ALOAD 16
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure11.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | POP
+ | RETURN
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | BIPUSH 0
+ | ANEWARRAY java.lang.Object
+ | ASTORE 10
+ | NEW FancyHelloWorld$AjcClosure21
+ | DUP
+ | ALOAD 10
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure21.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | CHECKCAST java.lang.String
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+
+ static final void init$_aroundBody0(FancyHelloWorld):
+ RETURN (line 7)
+ end static final void init$_aroundBody0(FancyHelloWorld)
+
+ static final java.io.PrintStream out_aroundBody2():
+ GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ ARETURN
+ end static final java.io.PrintStream out_aroundBody2()
+
+ static final void println_aroundBody4(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 11)
+ RETURN
+ end static final void println_aroundBody4(java.io.PrintStream, String)
+
+ static final void println_aroundBody6(java.io.PrintStream, Object):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V (line 13)
+ RETURN
+ end static final void println_aroundBody6(java.io.PrintStream, Object)
+
+ static final void println_aroundBody8(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 15)
+ RETURN
+ end static final void println_aroundBody8(java.io.PrintStream, String)
+
+ static final void main_aroundBody10(String[]):
+ field-get(java.io.PrintStream java.lang.System.out)
+ | BIPUSH 0
+ | ANEWARRAY java.lang.Object
+ | ASTORE_1
+ | NEW FancyHelloWorld$AjcClosure3
+ | DUP
+ | ALOAD_1
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure3.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | CHECKCAST java.io.PrintStream
+ field-get(java.io.PrintStream java.lang.System.out)
+ ASTORE_3 (line 9)
+ finally -> E1
+ | catch java.lang.Exception -> E0
+ | | ALOAD_3 (line 11)
+ | | LDC "bye"
+ | | ASTORE 5
+ | | ASTORE 7
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | BIPUSH 2
+ | | | ANEWARRAY java.lang.Object
+ | | | ASTORE 9
+ | | | ALOAD 9
+ | | | BIPUSH 0
+ | | | ALOAD 7
+ | | | AASTORE
+ | | | ALOAD 9
+ | | | BIPUSH 1
+ | | | ALOAD 5
+ | | | AASTORE
+ | | | NEW FancyHelloWorld$AjcClosure5
+ | | | DUP
+ | | | ALOAD 9
+ | | | INVOKESPECIAL FancyHelloWorld$AjcClosure5.<init> ([Ljava/lang/Object;)V
+ | | | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | | | POP
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | GOTO L0
+ | catch java.lang.Exception -> E0
+ | E0: ASTORE 11 (line 12)
+ | ALOAD_3 (line 13)
+ | ALOAD 11
+ | ASTORE 13
+ | ASTORE 15
+ | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | BIPUSH 2
+ | | ANEWARRAY java.lang.Object
+ | | ASTORE 17
+ | | ALOAD 17
+ | | BIPUSH 0
+ | | ALOAD 15
+ | | AASTORE
+ | | ALOAD 17
+ | | BIPUSH 1
+ | | ALOAD 13
+ | | AASTORE
+ | | NEW FancyHelloWorld$AjcClosure7
+ | | DUP
+ | | ALOAD 17
+ | | INVOKESPECIAL FancyHelloWorld$AjcClosure7.<init> ([Ljava/lang/Object;)V
+ | | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | | POP
+ | method-call(void java.io.PrintStream.println(java.lang.Object))
+ finally -> E1
+ GOTO L0
+ E1: ASTORE 19 (line 14)
+ JSR L1
+ ALOAD 19
+ ATHROW
+ L0: JSR L1
+ GOTO L2
+ L1: ASTORE 21
+ ALOAD_3 (line 15)
+ LDC "finally"
+ ASTORE 23
+ ASTORE 25
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ | BIPUSH 2
+ | ANEWARRAY java.lang.Object
+ | ASTORE 27
+ | ALOAD 27
+ | BIPUSH 0
+ | ALOAD 25
+ | AASTORE
+ | ALOAD 27
+ | BIPUSH 1
+ | ALOAD 23
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure9
+ | DUP
+ | ALOAD 27
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure9.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | POP
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ RET 21 (line 10)
+ L2: RETURN (line 17)
+ end static final void main_aroundBody10(String[])
+
+ static final int hashCode_aroundBody12(String):
+ ALOAD_0
+ INVOKEVIRTUAL java.lang.String.hashCode ()I (line 21)
+ IRETURN
+ end static final int hashCode_aroundBody12(String)
+
+ static final StringBuffer init$_aroundBody14(String):
+ NEW java.lang.StringBuffer
+ DUP
+ ALOAD_0
+ INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V (line 22)
+ ARETURN
+ end static final StringBuffer init$_aroundBody14(String)
+
+ static final StringBuffer append_aroundBody16(StringBuffer, int):
+ ALOAD_0
+ ILOAD_1
+ INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer; (line 22)
+ ARETURN
+ end static final StringBuffer append_aroundBody16(StringBuffer, int)
+
+ static final String toString_aroundBody18(StringBuffer):
+ ALOAD_0
+ INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String; (line 22)
+ ARETURN
+ end static final String toString_aroundBody18(StringBuffer)
+
+ static final String getName_aroundBody20():
+ ICONST_0 (line 20)
+ ISTORE_0
+ ILOAD_0 (line 21)
+ LDC "name"
+ ASTORE_2
+ method-call(int java.lang.String.hashCode())
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE 4
+ | ALOAD 4
+ | BIPUSH 0
+ | ALOAD_2
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure13
+ | DUP
+ | ALOAD 4
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure13.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | INVOKESTATIC org.aspectj.runtime.internal.Conversions.intValue (Ljava/lang/Object;)I
+ method-call(int java.lang.String.hashCode())
+ IADD
+ ISTORE_0
+ LDC "name" (line 22)
+ ASTORE 6
+ constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE 8
+ | ALOAD 8
+ | BIPUSH 0
+ | ALOAD 6
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure15
+ | DUP
+ | ALOAD 8
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure15.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | CHECKCAST java.lang.StringBuffer
+ constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ ILOAD_0
+ ISTORE 10
+ ASTORE 12
+ method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | BIPUSH 2
+ | ANEWARRAY java.lang.Object
+ | ASTORE 14
+ | ALOAD 14
+ | BIPUSH 0
+ | ALOAD 12
+ | AASTORE
+ | ALOAD 14
+ | BIPUSH 1
+ | ILOAD 10
+ | INVOKESTATIC org.aspectj.runtime.internal.Conversions.intObject (I)Ljava/lang/Object;
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure17
+ | DUP
+ | ALOAD 14
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure17.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | CHECKCAST java.lang.StringBuffer
+ method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ ASTORE 16
+ method-call(java.lang.String java.lang.StringBuffer.toString())
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE 18
+ | ALOAD 18
+ | BIPUSH 0
+ | ALOAD 16
+ | AASTORE
+ | NEW FancyHelloWorld$AjcClosure19
+ | DUP
+ | ALOAD 18
+ | INVOKESPECIAL FancyHelloWorld$AjcClosure19.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | CHECKCAST java.lang.String
+ method-call(java.lang.String java.lang.StringBuffer.toString())
+ ARETURN
+ end static final String getName_aroundBody20()
+end public abstract class FancyHelloWorld
+
+public class FancyHelloWorld$AjcClosure1 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST FancyHelloWorld
+ INVOKESTATIC FancyHelloWorld.init$_aroundBody0 (LFancyHelloWorld;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure1
+
+public class FancyHelloWorld$AjcClosure3 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ INVOKESTATIC FancyHelloWorld.out_aroundBody2 ()Ljava/io/PrintStream;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure3
+
+public class FancyHelloWorld$AjcClosure5 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.println_aroundBody4 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure5
+
+public class FancyHelloWorld$AjcClosure7 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ INVOKESTATIC FancyHelloWorld.println_aroundBody6 (Ljava/io/PrintStream;Ljava/lang/Object;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure7
+
+public class FancyHelloWorld$AjcClosure9 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.println_aroundBody8 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure9
+
+public class FancyHelloWorld$AjcClosure11 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST [Ljava.lang.String;
+ INVOKESTATIC FancyHelloWorld.main_aroundBody10 ([Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure11
+
+public class FancyHelloWorld$AjcClosure13 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.hashCode_aroundBody12 (Ljava/lang/String;)I
+ INVOKESTATIC org.aspectj.runtime.internal.Conversions.intObject (I)Ljava/lang/Object;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure13
+
+public class FancyHelloWorld$AjcClosure15 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.init$_aroundBody14 (Ljava/lang/String;)Ljava/lang/StringBuffer;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure15
+
+public class FancyHelloWorld$AjcClosure17 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.lang.StringBuffer
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ INVOKESTATIC org.aspectj.runtime.internal.Conversions.intValue (Ljava/lang/Object;)I
+ INVOKESTATIC FancyHelloWorld.append_aroundBody16 (Ljava/lang/StringBuffer;I)Ljava/lang/StringBuffer;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure17
+
+public class FancyHelloWorld$AjcClosure19 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.lang.StringBuffer
+ INVOKESTATIC FancyHelloWorld.toString_aroundBody18 (Ljava/lang/StringBuffer;)Ljava/lang/String;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure19
+
+public class FancyHelloWorld$AjcClosure21 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ INVOKESTATIC FancyHelloWorld.getName_aroundBody20 ()Ljava/lang/String;
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure21
diff --git a/weaver/testdata/AroundAllHelloWorld.txt b/weaver/testdata/AroundAllHelloWorld.txt
new file mode 100644
index 000000000..ea505e316
--- /dev/null
+++ b/weaver/testdata/AroundAllHelloWorld.txt
@@ -0,0 +1,183 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE_1
+ | ALOAD_1
+ | BIPUSH 0
+ | ALOAD_0
+ | AASTORE
+ | NEW HelloWorld$AjcClosure1
+ | DUP
+ | ALOAD_1
+ | INVOKESPECIAL HelloWorld$AjcClosure1.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | POP
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ ALOAD_0
+ ASTORE 5
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE 6
+ | ALOAD 6
+ | BIPUSH 0
+ | ALOAD 5
+ | AASTORE
+ | NEW HelloWorld$AjcClosure7
+ | DUP
+ | ALOAD 6
+ | INVOKESPECIAL HelloWorld$AjcClosure7.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | POP
+ | RETURN
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static final void init$_aroundBody0(HelloWorld):
+ RETURN (line 5)
+ end static final void init$_aroundBody0(HelloWorld)
+
+ static final java.io.PrintStream out_aroundBody2():
+ GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ ARETURN
+ end static final java.io.PrintStream out_aroundBody2()
+
+ static final void println_aroundBody4(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 9)
+ RETURN
+ end static final void println_aroundBody4(java.io.PrintStream, String)
+
+ static final void main_aroundBody6(String[]):
+ field-get(java.io.PrintStream java.lang.System.out)
+ | BIPUSH 0
+ | ANEWARRAY java.lang.Object
+ | ASTORE_1
+ | NEW HelloWorld$AjcClosure3
+ | DUP
+ | ALOAD_1
+ | INVOKESPECIAL HelloWorld$AjcClosure3.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | CHECKCAST java.io.PrintStream
+ field-get(java.io.PrintStream java.lang.System.out)
+ LDC "hello world" (line 9)
+ ASTORE_3
+ ASTORE 5
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ | BIPUSH 2
+ | ANEWARRAY java.lang.Object
+ | ASTORE 7
+ | ALOAD 7
+ | BIPUSH 0
+ | ALOAD 5
+ | AASTORE
+ | ALOAD 7
+ | BIPUSH 1
+ | ALOAD_3
+ | AASTORE
+ | NEW HelloWorld$AjcClosure5
+ | DUP
+ | ALOAD 7
+ | INVOKESPECIAL HelloWorld$AjcClosure5.<init> ([Ljava/lang/Object;)V
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | POP
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ RETURN (line 11)
+ end static final void main_aroundBody6(String[])
+end public class HelloWorld
+
+public class HelloWorld$AjcClosure1 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST HelloWorld
+ INVOKESTATIC HelloWorld.init$_aroundBody0 (LHelloWorld;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure1
+
+public class HelloWorld$AjcClosure3 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ INVOKESTATIC HelloWorld.out_aroundBody2 ()Ljava/io/PrintStream;
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure3
+
+public class HelloWorld$AjcClosure5 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC HelloWorld.println_aroundBody4 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure5
+
+public class HelloWorld$AjcClosure7 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST [Ljava.lang.String;
+ INVOKESTATIC HelloWorld.main_aroundBody6 ([Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure7
diff --git a/weaver/testdata/AroundAndOthersFancyHelloWorld.txt b/weaver/testdata/AroundAndOthersFancyHelloWorld.txt
new file mode 100644
index 000000000..a8a2bd44e
--- /dev/null
+++ b/weaver/testdata/AroundAndOthersFancyHelloWorld.txt
@@ -0,0 +1,375 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | ASTORE_1
+ | finally -> E1
+ | | catch java.lang.Exception -> E0
+ | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | LDC "bye"
+ | | | ASTORE 5
+ | | | ASTORE 6
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ | | | | BIPUSH 2
+ | | | | ANEWARRAY java.lang.Object
+ | | | | ASTORE 8
+ | | | | ALOAD 8
+ | | | | BIPUSH 0
+ | | | | ALOAD 6
+ | | | | AASTORE
+ | | | | ALOAD 8
+ | | | | BIPUSH 1
+ | | | | ALOAD 5
+ | | | | AASTORE
+ | | | | NEW FancyHelloWorld$AjcClosure3
+ | | | | DUP
+ | | | | ALOAD 8
+ | | | | INVOKESPECIAL FancyHelloWorld$AjcClosure3.<init> ([Ljava/lang/Object;)V
+ | | | | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | | | | POP
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | GOTO L0
+ | | catch java.lang.Exception -> E0
+ | | E0: ASTORE_2 (line 12)
+ | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | ALOAD_2 // java.lang.Exception e
+ | | ASTORE 9
+ | | ASTORE 10
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ | | | BIPUSH 2
+ | | | ANEWARRAY java.lang.Object
+ | | | ASTORE 12
+ | | | ALOAD 12
+ | | | BIPUSH 0
+ | | | ALOAD 10
+ | | | AASTORE
+ | | | ALOAD 12
+ | | | BIPUSH 1
+ | | | ALOAD 9
+ | | | AASTORE
+ | | | NEW FancyHelloWorld$AjcClosure7
+ | | | DUP
+ | | | ALOAD 12
+ | | | INVOKESPECIAL FancyHelloWorld$AjcClosure7.<init> ([Ljava/lang/Object;)V
+ | | | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | | | POP
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | finally -> E1
+ | GOTO L0
+ | E1: ASTORE 4 (line 14)
+ | JSR L1
+ | ALOAD 4
+ | ATHROW
+ | L0: JSR L1
+ | GOTO L2
+ | L1: ASTORE_3
+ | ALOAD_1 // java.io.PrintStream out (line 15)
+ | LDC "finally"
+ | ASTORE 13
+ | ASTORE 14
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ | | BIPUSH 2
+ | | ANEWARRAY java.lang.Object
+ | | ASTORE 16
+ | | ALOAD 16
+ | | BIPUSH 0
+ | | ALOAD 14
+ | | AASTORE
+ | | ALOAD 16
+ | | BIPUSH 1
+ | | ALOAD 13
+ | | AASTORE
+ | | NEW FancyHelloWorld$AjcClosure11
+ | | DUP
+ | | ALOAD 16
+ | | INVOKESPECIAL FancyHelloWorld$AjcClosure11.<init> ([Ljava/lang/Object;)V
+ | | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | | POP
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RET 3 (line 10)
+ | L2: RETURN (line 17)
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | NEW java.lang.StringBuffer (line 22)
+ | DUP
+ | LDC "name"
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+
+ static final void println_aroundBody0(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 11)
+ RETURN
+ end static final void println_aroundBody0(java.io.PrintStream, String)
+
+ static final void println_aroundBody2(java.io.PrintStream, String):
+ INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ BIPUSH 2
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ ALOAD_2
+ BIPUSH 1
+ ALOAD_1
+ AASTORE
+ NEW FancyHelloWorld$AjcClosure1
+ DUP
+ ALOAD_2
+ INVOKESPECIAL FancyHelloWorld$AjcClosure1.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void println_aroundBody2(java.io.PrintStream, String)
+
+ static final void println_aroundBody4(java.io.PrintStream, Object):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V (line 13)
+ RETURN
+ end static final void println_aroundBody4(java.io.PrintStream, Object)
+
+ static final void println_aroundBody6(java.io.PrintStream, Object):
+ INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ BIPUSH 2
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ ALOAD_2
+ BIPUSH 1
+ ALOAD_1
+ AASTORE
+ NEW FancyHelloWorld$AjcClosure5
+ DUP
+ ALOAD_2
+ INVOKESPECIAL FancyHelloWorld$AjcClosure5.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void println_aroundBody6(java.io.PrintStream, Object)
+
+ static final void println_aroundBody8(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 15)
+ RETURN
+ end static final void println_aroundBody8(java.io.PrintStream, String)
+
+ static final void println_aroundBody10(java.io.PrintStream, String):
+ INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ BIPUSH 2
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ ALOAD_2
+ BIPUSH 1
+ ALOAD_1
+ AASTORE
+ NEW FancyHelloWorld$AjcClosure9
+ DUP
+ ALOAD_2
+ INVOKESPECIAL FancyHelloWorld$AjcClosure9.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void println_aroundBody10(java.io.PrintStream, String)
+end public abstract class FancyHelloWorld
+
+public class FancyHelloWorld$AjcClosure1 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.println_aroundBody0 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure1
+
+public class FancyHelloWorld$AjcClosure3 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.println_aroundBody2 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure3
+
+public class FancyHelloWorld$AjcClosure5 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ INVOKESTATIC FancyHelloWorld.println_aroundBody4 (Ljava/io/PrintStream;Ljava/lang/Object;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure5
+
+public class FancyHelloWorld$AjcClosure7 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ INVOKESTATIC FancyHelloWorld.println_aroundBody6 (Ljava/io/PrintStream;Ljava/lang/Object;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure7
+
+public class FancyHelloWorld$AjcClosure9 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.println_aroundBody8 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure9
+
+public class FancyHelloWorld$AjcClosure11 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.println_aroundBody10 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure11
diff --git a/weaver/testdata/AroundAndOthersHelloWorld.txt b/weaver/testdata/AroundAndOthersHelloWorld.txt
new file mode 100644
index 000000000..66240b877
--- /dev/null
+++ b/weaver/testdata/AroundAndOthersHelloWorld.txt
@@ -0,0 +1,122 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | ASTORE_1
+ | ASTORE_2
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ | | BIPUSH 2
+ | | ANEWARRAY java.lang.Object
+ | | ASTORE 4
+ | | ALOAD 4
+ | | BIPUSH 0
+ | | ALOAD_2
+ | | AASTORE
+ | | ALOAD 4
+ | | BIPUSH 1
+ | | ALOAD_1
+ | | AASTORE
+ | | NEW HelloWorld$AjcClosure3
+ | | DUP
+ | | ALOAD 4
+ | | INVOKESPECIAL HelloWorld$AjcClosure3.<init> ([Ljava/lang/Object;)V
+ | | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | | POP
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static final void println_aroundBody0(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 9)
+ RETURN
+ end static final void println_aroundBody0(java.io.PrintStream, String)
+
+ static final void println_aroundBody2(java.io.PrintStream, String):
+ INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ BIPUSH 2
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ ALOAD_2
+ BIPUSH 1
+ ALOAD_1
+ AASTORE
+ NEW HelloWorld$AjcClosure1
+ DUP
+ ALOAD_2
+ INVOKESPECIAL HelloWorld$AjcClosure1.<init> ([Ljava/lang/Object;)V
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void println_aroundBody2(java.io.PrintStream, String)
+end public class HelloWorld
+
+public class HelloWorld$AjcClosure1 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC HelloWorld.println_aroundBody0 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure1
+
+public class HelloWorld$AjcClosure3 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC HelloWorld.println_aroundBody2 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure3
diff --git a/weaver/testdata/AroundArgsDynamicHelloWorld.txt b/weaver/testdata/AroundArgsDynamicHelloWorld.txt
new file mode 100644
index 000000000..5ca21c9b5
--- /dev/null
+++ b/weaver/testdata/AroundArgsDynamicHelloWorld.txt
@@ -0,0 +1,133 @@
+public class DynamicHelloWorld extends java.lang.Object implements java.io.Serializable:
+ public void <init>():
+ ALOAD_0 // DynamicHelloWorld this (line 8)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void DynamicHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void DynamicHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ | catch java.lang.UnsupportedOperationException -> E0
+ | | NEW DynamicHelloWorld (line 12)
+ | | DUP
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | | INVOKESPECIAL DynamicHelloWorld.<init> ()V
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | LDC "hello"
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | | GETSTATIC java.util.Collections.EMPTY_LIST Ljava/util/List;
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | | INVOKEVIRTUAL DynamicHelloWorld.doit (Ljava/lang/String;Ljava/util/List;)Ljava/lang/String;
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | POP
+ | | GOTO L0
+ | catch java.lang.UnsupportedOperationException -> E0
+ | E0: ASTORE_1 (line 13)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 14)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | NEW java.lang.StringBuffer
+ | DUP
+ | LDC "expected and caught: "
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ALOAD_1 // java.lang.UnsupportedOperationException t
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 15)
+ | L0: NEW java.lang.RuntimeException (line 17)
+ | DUP
+ | LDC "should have caught exception"
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.RuntimeException.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | ATHROW
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ String doit(String, java.util.List):
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | ALOAD_2 // java.util.List l (line 21)
+ | ALOAD_1 // java.lang.String arg0
+ | ASTORE_3
+ | ASTORE 4
+ | method-call(boolean java.util.List.add(java.lang.Object))
+ | | ALOAD 4
+ | | INSTANCEOF java.util.ArrayList
+ | | IFEQ L0
+ | | ALOAD 4
+ | | CHECKCAST java.util.ArrayList
+ | | BIPUSH 2
+ | | ANEWARRAY java.lang.Object
+ | | ASTORE 5
+ | | ALOAD 5
+ | | BIPUSH 0
+ | | ALOAD 4
+ | | AASTORE
+ | | ALOAD 5
+ | | BIPUSH 1
+ | | ALOAD_3
+ | | AASTORE
+ | | NEW DynamicHelloWorld$AjcClosure1
+ | | DUP
+ | | ALOAD 5
+ | | INVOKESPECIAL DynamicHelloWorld$AjcClosure1.<init> ([Ljava/lang/Object;)V
+ | | INVOKESTATIC Aspect.ajc_around0 (Ljava/util/ArrayList;Lorg/aspectj/runtime/internal/AroundClosure;)Z
+ | | GOTO L1
+ | | L0: ALOAD 4
+ | | ALOAD_3
+ | | INVOKESTATIC DynamicHelloWorld.add_aroundBody0 (Ljava/util/List;Ljava/lang/Object;)Z
+ | | L1: NOP
+ | method-call(boolean java.util.List.add(java.lang.Object))
+ | POP
+ | ALOAD_2 // java.util.List l (line 22)
+ | method-call(java.lang.String java.lang.Object.toString())
+ | | INVOKEVIRTUAL java.lang.Object.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.Object.toString())
+ | ARETURN
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ end String doit(String, java.util.List)
+
+ static final boolean add_aroundBody0(java.util.List, Object):
+ ALOAD_0
+ ALOAD_1
+ INVOKEINTERFACE java.util.List.add (Ljava/lang/Object;)Z (line 21)
+ IRETURN
+ end static final boolean add_aroundBody0(java.util.List, Object)
+end public class DynamicHelloWorld
+
+public class DynamicHelloWorld$AjcClosure1 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_1
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.util.List
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ INVOKESTATIC DynamicHelloWorld.add_aroundBody0 (Ljava/util/List;Ljava/lang/Object;)Z
+ INVOKESTATIC org.aspectj.runtime.internal.Conversions.booleanObject (Z)Ljava/lang/Object;
+ ARETURN
+ end public Object run(Object[])
+end public class DynamicHelloWorld$AjcClosure1
diff --git a/weaver/testdata/AroundFancyHelloWorld.txt b/weaver/testdata/AroundFancyHelloWorld.txt
new file mode 100644
index 000000000..f558cb548
--- /dev/null
+++ b/weaver/testdata/AroundFancyHelloWorld.txt
@@ -0,0 +1,229 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | ASTORE_1
+ | finally -> E1
+ | | catch java.lang.Exception -> E0
+ | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | LDC "bye"
+ | | | ASTORE 5
+ | | | ASTORE 6
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | BIPUSH 2
+ | | | | ANEWARRAY java.lang.Object
+ | | | | ASTORE 7
+ | | | | ALOAD 7
+ | | | | BIPUSH 0
+ | | | | ALOAD 6
+ | | | | AASTORE
+ | | | | ALOAD 7
+ | | | | BIPUSH 1
+ | | | | ALOAD 5
+ | | | | AASTORE
+ | | | | NEW FancyHelloWorld$AjcClosure1
+ | | | | DUP
+ | | | | ALOAD 7
+ | | | | INVOKESPECIAL FancyHelloWorld$AjcClosure1.<init> ([Ljava/lang/Object;)V
+ | | | | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | | | | POP
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | GOTO L0
+ | | catch java.lang.Exception -> E0
+ | | E0: ASTORE_2 (line 12)
+ | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | ALOAD_2 // java.lang.Exception e
+ | | ASTORE 8
+ | | ASTORE 9
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | BIPUSH 2
+ | | | ANEWARRAY java.lang.Object
+ | | | ASTORE 10
+ | | | ALOAD 10
+ | | | BIPUSH 0
+ | | | ALOAD 9
+ | | | AASTORE
+ | | | ALOAD 10
+ | | | BIPUSH 1
+ | | | ALOAD 8
+ | | | AASTORE
+ | | | NEW FancyHelloWorld$AjcClosure3
+ | | | DUP
+ | | | ALOAD 10
+ | | | INVOKESPECIAL FancyHelloWorld$AjcClosure3.<init> ([Ljava/lang/Object;)V
+ | | | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | | | POP
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | finally -> E1
+ | GOTO L0
+ | E1: ASTORE 4 (line 14)
+ | JSR L1
+ | ALOAD 4
+ | ATHROW
+ | L0: JSR L1
+ | GOTO L2
+ | L1: ASTORE_3
+ | ALOAD_1 // java.io.PrintStream out (line 15)
+ | LDC "finally"
+ | ASTORE 11
+ | ASTORE 12
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | BIPUSH 2
+ | | ANEWARRAY java.lang.Object
+ | | ASTORE 13
+ | | ALOAD 13
+ | | BIPUSH 0
+ | | ALOAD 12
+ | | AASTORE
+ | | ALOAD 13
+ | | BIPUSH 1
+ | | ALOAD 11
+ | | AASTORE
+ | | NEW FancyHelloWorld$AjcClosure5
+ | | DUP
+ | | ALOAD 13
+ | | INVOKESPECIAL FancyHelloWorld$AjcClosure5.<init> ([Ljava/lang/Object;)V
+ | | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | | POP
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RET 3 (line 10)
+ | L2: RETURN (line 17)
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | NEW java.lang.StringBuffer (line 22)
+ | DUP
+ | LDC "name"
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+
+ static final void println_aroundBody0(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 11)
+ RETURN
+ end static final void println_aroundBody0(java.io.PrintStream, String)
+
+ static final void println_aroundBody2(java.io.PrintStream, Object):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V (line 13)
+ RETURN
+ end static final void println_aroundBody2(java.io.PrintStream, Object)
+
+ static final void println_aroundBody4(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 15)
+ RETURN
+ end static final void println_aroundBody4(java.io.PrintStream, String)
+end public abstract class FancyHelloWorld
+
+public class FancyHelloWorld$AjcClosure1 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.println_aroundBody0 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure1
+
+public class FancyHelloWorld$AjcClosure3 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ INVOKESTATIC FancyHelloWorld.println_aroundBody2 (Ljava/io/PrintStream;Ljava/lang/Object;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure3
+
+public class FancyHelloWorld$AjcClosure5 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC FancyHelloWorld.println_aroundBody4 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class FancyHelloWorld$AjcClosure5
diff --git a/weaver/testdata/AroundHelloWorld.txt b/weaver/testdata/AroundHelloWorld.txt
new file mode 100644
index 000000000..dcddb75fa
--- /dev/null
+++ b/weaver/testdata/AroundHelloWorld.txt
@@ -0,0 +1,73 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | ASTORE_1
+ | ASTORE_2
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | BIPUSH 2
+ | | ANEWARRAY java.lang.Object
+ | | ASTORE_3
+ | | ALOAD_3
+ | | BIPUSH 0
+ | | ALOAD_2
+ | | AASTORE
+ | | ALOAD_3
+ | | BIPUSH 1
+ | | ALOAD_1
+ | | AASTORE
+ | | NEW HelloWorld$AjcClosure1
+ | | DUP
+ | | ALOAD_3
+ | | INVOKESPECIAL HelloWorld$AjcClosure1.<init> ([Ljava/lang/Object;)V
+ | | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | | POP
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static final void println_aroundBody0(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 9)
+ RETURN
+ end static final void println_aroundBody0(java.io.PrintStream, String)
+end public class HelloWorld
+
+public class HelloWorld$AjcClosure1 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ INVOKESTATIC HelloWorld.println_aroundBody0 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure1
diff --git a/weaver/testdata/BeforeFancyHelloWorld.txt b/weaver/testdata/BeforeFancyHelloWorld.txt
new file mode 100644
index 000000000..18136b693
--- /dev/null
+++ b/weaver/testdata/BeforeFancyHelloWorld.txt
@@ -0,0 +1,90 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | INVOKESTATIC Aspect.ajc_before_constructor_execution ()V
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | INVOKESTATIC Aspect.ajc_before_field_get ()V
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | ASTORE_1
+ | finally -> E1
+ | | catch java.lang.Exception -> E0
+ | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | LDC "bye"
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | GOTO L0
+ | | catch java.lang.Exception -> E0
+ | | E0: ASTORE_2 (line 12)
+ | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | ALOAD_2 // java.lang.Exception e
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | finally -> E1
+ | GOTO L0
+ | E1: ASTORE 4 (line 14)
+ | JSR L1
+ | ALOAD 4
+ | ATHROW
+ | L0: JSR L1
+ | GOTO L2
+ | L1: ASTORE_3
+ | ALOAD_1 // java.io.PrintStream out (line 15)
+ | LDC "finally"
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RET 3 (line 10)
+ | L2: RETURN (line 17)
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | LDC "name" (line 22)
+ | ASTORE_1
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESTATIC Aspect.ajc_before_constructor_call ()V
+ | | NEW java.lang.StringBuffer
+ | | DUP
+ | | ALOAD_1
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/BeforeHelloWorld.txt b/weaver/testdata/BeforeHelloWorld.txt
new file mode 100644
index 000000000..3fc3fa818
--- /dev/null
+++ b/weaver/testdata/BeforeHelloWorld.txt
@@ -0,0 +1,26 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | INVOKESTATIC Aspect.ajc_before_constructor_execution ()V
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | INVOKESTATIC Aspect.ajc_before_field_get ()V
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/CflowNonStaticBeforeFancyHelloWorld.txt b/weaver/testdata/CflowNonStaticBeforeFancyHelloWorld.txt
new file mode 100644
index 000000000..cb71eca4b
--- /dev/null
+++ b/weaver/testdata/CflowNonStaticBeforeFancyHelloWorld.txt
@@ -0,0 +1,92 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | INVOKESTATIC Aspect.ajc$perCflowPush ()V
+ | catch java.lang.Throwable -> E2
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | | INVOKESTATIC Aspect.hasAspect ()Z
+ | | | IFEQ L0
+ | | | INVOKESTATIC Aspect.aspectOf ()LAspect;
+ | | | INVOKEVIRTUAL Aspect.ajc_before ()V
+ | | | L0: GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | ASTORE_1
+ | | finally -> E1
+ | | | catch java.lang.Exception -> E0
+ | | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | | LDC "bye"
+ | | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | GOTO L1
+ | | | catch java.lang.Exception -> E0
+ | | | E0: ASTORE_2 (line 12)
+ | | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | | ALOAD_2 // java.lang.Exception e
+ | | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | finally -> E1
+ | | GOTO L1
+ | | E1: ASTORE 4 (line 14)
+ | | JSR L2
+ | | ALOAD 4
+ | | ATHROW
+ | | L1: JSR L2
+ | | GOTO L3
+ | | L2: ASTORE_3
+ | | ALOAD_1 // java.io.PrintStream out (line 15)
+ | | LDC "finally"
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | RET 3 (line 10)
+ | | L3: GOTO L4 (line 17)
+ | catch java.lang.Throwable -> E2
+ | E2: ASTORE 6
+ | GETSTATIC Aspect.ajc$perCflowStack Lorg/aspectj/runtime/internal/CFlowStack;
+ | INVOKEVIRTUAL org.aspectj.runtime.internal.CFlowStack.pop ()V
+ | ALOAD 6
+ | ATHROW
+ | L4: GETSTATIC Aspect.ajc$perCflowStack Lorg/aspectj/runtime/internal/CFlowStack;
+ | INVOKEVIRTUAL org.aspectj.runtime.internal.CFlowStack.pop ()V
+ | RETURN
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | NEW java.lang.StringBuffer (line 22)
+ | DUP
+ | LDC "name"
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/CflowNonStaticBeforeHelloWorld.txt b/weaver/testdata/CflowNonStaticBeforeHelloWorld.txt
new file mode 100644
index 000000000..a2a9d3cc0
--- /dev/null
+++ b/weaver/testdata/CflowNonStaticBeforeHelloWorld.txt
@@ -0,0 +1,37 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | INVOKESTATIC Aspect.ajc$perCflowPush ()V
+ | catch java.lang.Throwable -> E0
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | | INVOKESTATIC Aspect.hasAspect ()Z
+ | | | IFEQ L0
+ | | | INVOKESTATIC Aspect.aspectOf ()LAspect;
+ | | | INVOKEVIRTUAL Aspect.ajc_before ()V
+ | | | L0: GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | | field-get(java.io.PrintStream java.lang.System.out)
+ | | LDC "hello world" (line 9)
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | GOTO L1 (line 11)
+ | catch java.lang.Throwable -> E0
+ | E0: ASTORE_2
+ | GETSTATIC Aspect.ajc$perCflowStack Lorg/aspectj/runtime/internal/CFlowStack;
+ | INVOKEVIRTUAL org.aspectj.runtime.internal.CFlowStack.pop ()V
+ | ALOAD_2
+ | ATHROW
+ | L1: GETSTATIC Aspect.ajc$perCflowStack Lorg/aspectj/runtime/internal/CFlowStack;
+ | INVOKEVIRTUAL org.aspectj.runtime.internal.CFlowStack.pop ()V
+ | RETURN
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/CflowStateResidueDynamicHelloWorld.txt b/weaver/testdata/CflowStateResidueDynamicHelloWorld.txt
new file mode 100644
index 000000000..fd6bfd650
--- /dev/null
+++ b/weaver/testdata/CflowStateResidueDynamicHelloWorld.txt
@@ -0,0 +1,119 @@
+public class DynamicHelloWorld extends java.lang.Object implements java.io.Serializable:
+ public void <init>():
+ ALOAD_0 // DynamicHelloWorld this (line 8)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void DynamicHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void DynamicHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ | GETSTATIC Aspect.ajc$cflowStack$0 Lorg/aspectj/runtime/internal/CFlowStack;
+ | INVOKEVIRTUAL org.aspectj.runtime.internal.CFlowStack.isValid ()Z
+ | IFEQ L0
+ | GETSTATIC Aspect.ajc$cflowStack$0 Lorg/aspectj/runtime/internal/CFlowStack;
+ | BIPUSH 0
+ | INVOKEVIRTUAL org.aspectj.runtime.internal.CFlowStack.get (I)Ljava/lang/Object;
+ | CHECKCAST java.util.ArrayList
+ | INVOKESTATIC Aspect.ajc_before_0 (Ljava/util/ArrayList;)V
+ | catch java.lang.UnsupportedOperationException -> E0
+ | | L0: NEW DynamicHelloWorld (line 12)
+ | | DUP
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | | INVOKESPECIAL DynamicHelloWorld.<init> ()V
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | LDC "hello"
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | | GETSTATIC java.util.Collections.EMPTY_LIST Ljava/util/List;
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | | INVOKEVIRTUAL DynamicHelloWorld.doit (Ljava/lang/String;Ljava/util/List;)Ljava/lang/String;
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | POP
+ | | GOTO L1
+ | catch java.lang.UnsupportedOperationException -> E0
+ | E0: ASTORE_1 (line 13)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 14)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | NEW java.lang.StringBuffer
+ | DUP
+ | LDC "expected and caught: "
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ALOAD_1 // java.lang.UnsupportedOperationException t
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 15)
+ | L1: NEW java.lang.RuntimeException (line 17)
+ | DUP
+ | LDC "should have caught exception"
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.RuntimeException.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | ATHROW
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ String doit(String, java.util.List):
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | ALOAD_2 // java.util.List l (line 21)
+ | ALOAD_1 // java.lang.String arg0
+ | ASTORE_3
+ | ASTORE 4
+ | method-call(boolean java.util.List.add(java.lang.Object))
+ | | BIPUSH 0
+ | | ISTORE 5
+ | | ALOAD 4
+ | | INSTANCEOF java.util.ArrayList
+ | | IFEQ L0
+ | | BIPUSH 1
+ | | ISTORE 5
+ | | BIPUSH 1
+ | | ANEWARRAY java.lang.Object
+ | | ASTORE 6
+ | | ALOAD 6
+ | | BIPUSH 0
+ | | ALOAD 4
+ | | AASTORE
+ | | GETSTATIC Aspect.ajc$cflowStack$0 Lorg/aspectj/runtime/internal/CFlowStack;
+ | | ALOAD 6
+ | | INVOKEVIRTUAL org.aspectj.runtime.internal.CFlowStack.push ([Ljava/lang/Object;)V
+ | | catch java.lang.Throwable -> E0
+ | | | L0: ALOAD 4
+ | | | ALOAD_3
+ | | | INVOKEINTERFACE java.util.List.add (Ljava/lang/Object;)Z
+ | | catch java.lang.Throwable -> E0
+ | | GOTO L2
+ | | E0: ASTORE 7
+ | | ILOAD 5
+ | | IFEQ L1
+ | | GETSTATIC Aspect.ajc$cflowStack$0 Lorg/aspectj/runtime/internal/CFlowStack;
+ | | INVOKEVIRTUAL org.aspectj.runtime.internal.CFlowStack.pop ()V
+ | | L1: ALOAD 7
+ | | ATHROW
+ | | L2: NOP
+ | | ILOAD 5
+ | | IFEQ L3
+ | | GETSTATIC Aspect.ajc$cflowStack$0 Lorg/aspectj/runtime/internal/CFlowStack;
+ | | INVOKEVIRTUAL org.aspectj.runtime.internal.CFlowStack.pop ()V
+ | | L3: NOP
+ | method-call(boolean java.util.List.add(java.lang.Object))
+ | POP
+ | ALOAD_2 // java.util.List l (line 22)
+ | method-call(java.lang.String java.lang.Object.toString())
+ | | INVOKEVIRTUAL java.lang.Object.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.Object.toString())
+ | ARETURN
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ end String doit(String, java.util.List)
+end public class DynamicHelloWorld
diff --git a/weaver/testdata/ExtractedFancyHelloWorld.txt b/weaver/testdata/ExtractedFancyHelloWorld.txt
new file mode 100644
index 000000000..378da90b8
--- /dev/null
+++ b/weaver/testdata/ExtractedFancyHelloWorld.txt
@@ -0,0 +1,169 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | ALOAD_0
+ | INVOKESTATIC FancyHelloWorld.init$_extracted0 (LFancyHelloWorld;)V
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ ALOAD_0
+ ASTORE 11
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | ALOAD 11
+ | INVOKESTATIC FancyHelloWorld.main_extracted5 ([Ljava/lang/String;)V
+ | RETURN
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | INVOKESTATIC FancyHelloWorld.getName_extracted10 ()Ljava/lang/String;
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+
+ static final void init$_extracted0(FancyHelloWorld):
+ RETURN (line 7)
+ end static final void init$_extracted0(FancyHelloWorld)
+
+ static final java.io.PrintStream out_extracted1():
+ GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ ARETURN
+ end static final java.io.PrintStream out_extracted1()
+
+ static final void println_extracted2(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 11)
+ RETURN
+ end static final void println_extracted2(java.io.PrintStream, String)
+
+ static final void println_extracted3(java.io.PrintStream, Object):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V (line 13)
+ RETURN
+ end static final void println_extracted3(java.io.PrintStream, Object)
+
+ static final void println_extracted4(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 15)
+ RETURN
+ end static final void println_extracted4(java.io.PrintStream, String)
+
+ static final void main_extracted5(String[]):
+ field-get(java.io.PrintStream java.lang.System.out)
+ | INVOKESTATIC FancyHelloWorld.out_extracted1 ()Ljava/io/PrintStream;
+ field-get(java.io.PrintStream java.lang.System.out)
+ ASTORE_1 (line 9)
+ finally -> E1
+ | catch java.lang.Exception -> E0
+ | | ALOAD_1 (line 11)
+ | | LDC "bye"
+ | | ASTORE_3
+ | | ASTORE 5
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | ALOAD 5
+ | | | ALOAD_3
+ | | | INVOKESTATIC FancyHelloWorld.println_extracted2 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | GOTO L0
+ | catch java.lang.Exception -> E0
+ | E0: ASTORE 7 (line 12)
+ | ALOAD_1 (line 13)
+ | ALOAD 7
+ | ASTORE 9
+ | ASTORE 11
+ | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | ALOAD 11
+ | | ALOAD 9
+ | | INVOKESTATIC FancyHelloWorld.println_extracted3 (Ljava/io/PrintStream;Ljava/lang/Object;)V
+ | method-call(void java.io.PrintStream.println(java.lang.Object))
+ finally -> E1
+ GOTO L0
+ E1: ASTORE 13 (line 14)
+ JSR L1
+ ALOAD 13
+ ATHROW
+ L0: JSR L1
+ GOTO L2
+ L1: ASTORE 15
+ ALOAD_1 (line 15)
+ LDC "finally"
+ ASTORE 17
+ ASTORE 19
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ | ALOAD 19
+ | ALOAD 17
+ | INVOKESTATIC FancyHelloWorld.println_extracted4 (Ljava/io/PrintStream;Ljava/lang/String;)V
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ RET 15 (line 10)
+ L2: RETURN (line 17)
+ end static final void main_extracted5(String[])
+
+ static final int hashCode_extracted6(String):
+ ALOAD_0
+ INVOKEVIRTUAL java.lang.String.hashCode ()I (line 21)
+ IRETURN
+ end static final int hashCode_extracted6(String)
+
+ static final StringBuffer init$_extracted7(String):
+ NEW java.lang.StringBuffer
+ DUP
+ ALOAD_0
+ INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V (line 22)
+ ARETURN
+ end static final StringBuffer init$_extracted7(String)
+
+ static final StringBuffer append_extracted8(StringBuffer, int):
+ ALOAD_0
+ ILOAD_1
+ INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer; (line 22)
+ ARETURN
+ end static final StringBuffer append_extracted8(StringBuffer, int)
+
+ static final String toString_extracted9(StringBuffer):
+ ALOAD_0
+ INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String; (line 22)
+ ARETURN
+ end static final String toString_extracted9(StringBuffer)
+
+ static final String getName_extracted10():
+ ICONST_0 (line 20)
+ ISTORE_0
+ ILOAD_0 (line 21)
+ LDC "name"
+ ASTORE_2
+ method-call(int java.lang.String.hashCode())
+ | ALOAD_2
+ | INVOKESTATIC FancyHelloWorld.hashCode_extracted6 (Ljava/lang/String;)I
+ method-call(int java.lang.String.hashCode())
+ IADD
+ ISTORE_0
+ LDC "name" (line 22)
+ ASTORE 4
+ constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ALOAD 4
+ | INVOKESTATIC FancyHelloWorld.init$_extracted7 (Ljava/lang/String;)Ljava/lang/StringBuffer;
+ constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ ILOAD_0
+ ISTORE 6
+ ASTORE 8
+ method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | ALOAD 8
+ | ILOAD 6
+ | INVOKESTATIC FancyHelloWorld.append_extracted8 (Ljava/lang/StringBuffer;I)Ljava/lang/StringBuffer;
+ method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ ASTORE 10
+ method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ALOAD 10
+ | INVOKESTATIC FancyHelloWorld.toString_extracted9 (Ljava/lang/StringBuffer;)Ljava/lang/String;
+ method-call(java.lang.String java.lang.StringBuffer.toString())
+ ARETURN
+ end static final String getName_extracted10()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/ExtractedHelloWorld.txt b/weaver/testdata/ExtractedHelloWorld.txt
new file mode 100644
index 000000000..7ac93cbef
--- /dev/null
+++ b/weaver/testdata/ExtractedHelloWorld.txt
@@ -0,0 +1,52 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | ALOAD_0
+ | INVOKESTATIC HelloWorld.init$_extracted (LHelloWorld;)V
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ ALOAD_0
+ ASTORE_3
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | ALOAD_3
+ | INVOKESTATIC HelloWorld.main_extracted ([Ljava/lang/String;)V
+ | RETURN
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static final void init$_extracted(HelloWorld):
+ RETURN (line 5)
+ end static final void init$_extracted(HelloWorld)
+
+ static final java.io.PrintStream out_extracted():
+ GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ ARETURN
+ end static final java.io.PrintStream out_extracted()
+
+ static final void println_extracted(java.io.PrintStream, String):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 9)
+ RETURN
+ end static final void println_extracted(java.io.PrintStream, String)
+
+ static final void main_extracted(String[]):
+ field-get(java.io.PrintStream java.lang.System.out)
+ | INVOKESTATIC HelloWorld.out_extracted ()Ljava/io/PrintStream;
+ field-get(java.io.PrintStream java.lang.System.out)
+ LDC "hello world" (line 9)
+ ASTORE_1
+ ASTORE_3
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ | ALOAD_3
+ | ALOAD_1
+ | INVOKESTATIC HelloWorld.println_extracted (Ljava/io/PrintStream;Ljava/lang/String;)V
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ RETURN (line 11)
+ end static final void main_extracted(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/FieldSet.txt b/weaver/testdata/FieldSet.txt
new file mode 100644
index 000000000..c89c7e7bc
--- /dev/null
+++ b/weaver/testdata/FieldSet.txt
@@ -0,0 +1,68 @@
+public class FieldyHelloWorld extends java.lang.Object:
+ public static String str
+ static void <clinit>():
+ staticinitialization(void FieldyHelloWorld.<clinit>())
+ | LDC "Hello" (line 3)
+ | field-set(java.lang.String FieldyHelloWorld.str)
+ | | PUTSTATIC FieldyHelloWorld.str Ljava/lang/String;
+ | field-set(java.lang.String FieldyHelloWorld.str)
+ | RETURN (line 1)
+ staticinitialization(void FieldyHelloWorld.<clinit>())
+ end static void <clinit>()
+
+ public void <init>():
+ ALOAD_0 // FieldyHelloWorld this (line 1)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FieldyHelloWorld.<init>())
+ | INVOKESTATIC Aspect.ajc_before_constructor_execution ()V
+ | RETURN
+ constructor-execution(void FieldyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FieldyHelloWorld.main(java.lang.String[]))
+ | INVOKESTATIC Aspect.ajc_before_method_execution ()V
+ | field-get(java.lang.String FieldyHelloWorld.str)
+ | | INVOKESTATIC Aspect.ajc_before_field_get ()V
+ | | GETSTATIC FieldyHelloWorld.str Ljava/lang/String; (line 6)
+ | field-get(java.lang.String FieldyHelloWorld.str)
+ | method-call(java.lang.String java.lang.String.valueOf(java.lang.Object))
+ | | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | | INVOKESTATIC java.lang.String.valueOf (Ljava/lang/Object;)Ljava/lang/String;
+ | method-call(java.lang.String java.lang.String.valueOf(java.lang.Object))
+ | ASTORE_1
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESTATIC Aspect.ajc_before_constructor_call ()V
+ | | NEW java.lang.StringBuffer
+ | | DUP
+ | | ALOAD_1
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | LDC " World"
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String))
+ | | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/String;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | field-set(java.lang.String FieldyHelloWorld.str)
+ | | PUTSTATIC FieldyHelloWorld.str Ljava/lang/String;
+ | field-set(java.lang.String FieldyHelloWorld.str)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | INVOKESTATIC Aspect.ajc_before_field_get ()V
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | field-get(java.lang.String FieldyHelloWorld.str)
+ | | INVOKESTATIC Aspect.ajc_before_field_get ()V
+ | | GETSTATIC FieldyHelloWorld.str Ljava/lang/String;
+ | field-get(java.lang.String FieldyHelloWorld.str)
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKESTATIC Aspect.ajc_before_method_call ()V
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 9)
+ method-execution(void FieldyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class FieldyHelloWorld
diff --git a/weaver/testdata/IdDummyAspect.txt b/weaver/testdata/IdDummyAspect.txt
new file mode 100644
index 000000000..17ec9dac5
--- /dev/null
+++ b/weaver/testdata/IdDummyAspect.txt
@@ -0,0 +1,16 @@
+public abstract class DummyAspect extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // DummyAspect this (line 1)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void DummyAspect.<init>())
+ | RETURN
+ constructor-execution(void DummyAspect.<init>())
+ end public void <init>()
+
+ public void ajc$before$DummyAspect$57(Object) AdviceAttribute(before, traced(BindingTypePattern(java.lang.Object, 0)), 0, 87)
+:
+ advice-execution(void DummyAspect.ajc$before$DummyAspect$57(java.lang.Object))
+ | RETURN (line 5)
+ advice-execution(void DummyAspect.ajc$before$DummyAspect$57(java.lang.Object))
+ end public void ajc$before$DummyAspect$57(Object)
+end public abstract class DummyAspect
diff --git a/weaver/testdata/IdFancyHelloWorld.txt b/weaver/testdata/IdFancyHelloWorld.txt
new file mode 100644
index 000000000..86d44a554
--- /dev/null
+++ b/weaver/testdata/IdFancyHelloWorld.txt
@@ -0,0 +1,77 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | ASTORE_1
+ | finally -> E1
+ | | catch java.lang.Exception -> E0
+ | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | LDC "bye"
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | GOTO L0
+ | | catch java.lang.Exception -> E0
+ | | E0: ASTORE_2 (line 12)
+ | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | ALOAD_2 // java.lang.Exception e
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | finally -> E1
+ | GOTO L0
+ | E1: ASTORE 4 (line 14)
+ | JSR L1
+ | ALOAD 4
+ | ATHROW
+ | L0: JSR L1
+ | GOTO L2
+ | L1: ASTORE_3
+ | ALOAD_1 // java.io.PrintStream out (line 15)
+ | LDC "finally"
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RET 3 (line 10)
+ | L2: RETURN (line 17)
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | NEW java.lang.StringBuffer (line 22)
+ | DUP
+ | LDC "name"
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/IdHelloWorld.txt b/weaver/testdata/IdHelloWorld.txt
new file mode 100644
index 000000000..dfd6deff9
--- /dev/null
+++ b/weaver/testdata/IdHelloWorld.txt
@@ -0,0 +1,22 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/NoResidueDynamicHelloWorld.txt b/weaver/testdata/NoResidueDynamicHelloWorld.txt
new file mode 100644
index 000000000..9ae90cc05
--- /dev/null
+++ b/weaver/testdata/NoResidueDynamicHelloWorld.txt
@@ -0,0 +1,75 @@
+public class DynamicHelloWorld extends java.lang.Object implements java.io.Serializable:
+ public void <init>():
+ ALOAD_0 // DynamicHelloWorld this (line 8)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void DynamicHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void DynamicHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ | catch java.lang.UnsupportedOperationException -> E0
+ | | NEW DynamicHelloWorld (line 12)
+ | | DUP
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | | INVOKESPECIAL DynamicHelloWorld.<init> ()V
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | LDC "hello"
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | | GETSTATIC java.util.Collections.EMPTY_LIST Ljava/util/List;
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | | INVOKEVIRTUAL DynamicHelloWorld.doit (Ljava/lang/String;Ljava/util/List;)Ljava/lang/String;
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | POP
+ | | GOTO L0
+ | catch java.lang.UnsupportedOperationException -> E0
+ | E0: ASTORE_1 (line 13)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 14)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | NEW java.lang.StringBuffer
+ | DUP
+ | LDC "expected and caught: "
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ALOAD_1 // java.lang.UnsupportedOperationException t
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 15)
+ | L0: NEW java.lang.RuntimeException (line 17)
+ | DUP
+ | LDC "should have caught exception"
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.RuntimeException.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | ATHROW
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ String doit(String, java.util.List):
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | ALOAD_2 // java.util.List l (line 21)
+ | ALOAD_1 // java.lang.String arg0
+ | method-call(boolean java.util.List.add(java.lang.Object))
+ | | INVOKESTATIC Aspect.ajc_before_0 ()V
+ | | INVOKEINTERFACE java.util.List.add (Ljava/lang/Object;)Z
+ | method-call(boolean java.util.List.add(java.lang.Object))
+ | POP
+ | ALOAD_2 // java.util.List l (line 22)
+ | method-call(java.lang.String java.lang.Object.toString())
+ | | INVOKEVIRTUAL java.lang.Object.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.Object.toString())
+ | ARETURN
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ end String doit(String, java.util.List)
+end public class DynamicHelloWorld
diff --git a/weaver/testdata/NonStaticBeforeFancyHelloWorld.txt b/weaver/testdata/NonStaticBeforeFancyHelloWorld.txt
new file mode 100644
index 000000000..84821964a
--- /dev/null
+++ b/weaver/testdata/NonStaticBeforeFancyHelloWorld.txt
@@ -0,0 +1,79 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC Aspect.ajc$perSingletonInstance LAspect;
+ | | INVOKEVIRTUAL Aspect.ajc_before ()V
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | ASTORE_1
+ | finally -> E1
+ | | catch java.lang.Exception -> E0
+ | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | LDC "bye"
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | GOTO L0
+ | | catch java.lang.Exception -> E0
+ | | E0: ASTORE_2 (line 12)
+ | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | ALOAD_2 // java.lang.Exception e
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | finally -> E1
+ | GOTO L0
+ | E1: ASTORE 4 (line 14)
+ | JSR L1
+ | ALOAD 4
+ | ATHROW
+ | L0: JSR L1
+ | GOTO L2
+ | L1: ASTORE_3
+ | ALOAD_1 // java.io.PrintStream out (line 15)
+ | LDC "finally"
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RET 3 (line 10)
+ | L2: RETURN (line 17)
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | NEW java.lang.StringBuffer (line 22)
+ | DUP
+ | LDC "name"
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/NonStaticBeforeHelloWorld.txt b/weaver/testdata/NonStaticBeforeHelloWorld.txt
new file mode 100644
index 000000000..2786f0844
--- /dev/null
+++ b/weaver/testdata/NonStaticBeforeHelloWorld.txt
@@ -0,0 +1,24 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC Aspect.ajc$perSingletonInstance LAspect;
+ | | INVOKEVIRTUAL Aspect.ajc_before ()V
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/PatternWeaveFancyHelloWorld.txt b/weaver/testdata/PatternWeaveFancyHelloWorld.txt
new file mode 100644
index 000000000..86d44a554
--- /dev/null
+++ b/weaver/testdata/PatternWeaveFancyHelloWorld.txt
@@ -0,0 +1,77 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | ASTORE_1
+ | finally -> E1
+ | | catch java.lang.Exception -> E0
+ | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | LDC "bye"
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | GOTO L0
+ | | catch java.lang.Exception -> E0
+ | | E0: ASTORE_2 (line 12)
+ | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | ALOAD_2 // java.lang.Exception e
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | finally -> E1
+ | GOTO L0
+ | E1: ASTORE 4 (line 14)
+ | JSR L1
+ | ALOAD 4
+ | ATHROW
+ | L0: JSR L1
+ | GOTO L2
+ | L1: ASTORE_3
+ | ALOAD_1 // java.io.PrintStream out (line 15)
+ | LDC "finally"
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RET 3 (line 10)
+ | L2: RETURN (line 17)
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | NEW java.lang.StringBuffer (line 22)
+ | DUP
+ | LDC "name"
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/PatternWeaveHelloWorld.txt b/weaver/testdata/PatternWeaveHelloWorld.txt
new file mode 100644
index 000000000..dfd6deff9
--- /dev/null
+++ b/weaver/testdata/PatternWeaveHelloWorld.txt
@@ -0,0 +1,22 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/PerSingletonField.txt b/weaver/testdata/PerSingletonField.txt
new file mode 100644
index 000000000..4837c6569
--- /dev/null
+++ b/weaver/testdata/PerSingletonField.txt
@@ -0,0 +1,22 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ RETURN
+ end public void <init>()
+
+ public static void main(String[]):
+ GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ LDC "hello world" (line 9)
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ RETURN (line 11)
+ end public static void main(String[])
+
+ static void <clinit>():
+ NEW HelloWorld
+ DUP
+ INVOKESPECIAL HelloWorld.<init> ()V
+ PUTSTATIC HelloWorld.ajc$perSingletonInstance LHelloWorld;
+ RETURN
+ end static void <clinit>()
+end public class HelloWorld
diff --git a/weaver/testdata/PerThisNonStaticBeforeFancyHelloWorld.txt b/weaver/testdata/PerThisNonStaticBeforeFancyHelloWorld.txt
new file mode 100644
index 000000000..5155ab6d7
--- /dev/null
+++ b/weaver/testdata/PerThisNonStaticBeforeFancyHelloWorld.txt
@@ -0,0 +1,113 @@
+public abstract class FancyHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // FancyHelloWorld this (line 7)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void FancyHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void FancyHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | ASTORE_1
+ | finally -> E1
+ | | catch java.lang.Exception -> E0
+ | | | ALOAD_1 // java.io.PrintStream out (line 11)
+ | | | LDC "bye"
+ | | | ASTORE 5
+ | | | ASTORE 6
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | | ALOAD 6
+ | | | | INVOKESTATIC Aspect.ajc$perObjectBind (Ljava/lang/Object;)V
+ | | | | ALOAD 6
+ | | | | INVOKESTATIC Aspect.hasAspect (Ljava/lang/Object;)Z
+ | | | | IFEQ L0
+ | | | | ALOAD 6
+ | | | | INVOKESTATIC Aspect.aspectOf (Ljava/lang/Object;)LAspect;
+ | | | | INVOKEVIRTUAL Aspect.ajc_before ()V
+ | | | | L0: ALOAD 6
+ | | | | ALOAD 5
+ | | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | | | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | | GOTO L2
+ | | catch java.lang.Exception -> E0
+ | | E0: ASTORE_2 (line 12)
+ | | ALOAD_1 // java.io.PrintStream out (line 13)
+ | | ALOAD_2 // java.lang.Exception e
+ | | ASTORE 7
+ | | ASTORE 8
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | | | ALOAD 8
+ | | | INVOKESTATIC Aspect.ajc$perObjectBind (Ljava/lang/Object;)V
+ | | | ALOAD 8
+ | | | INVOKESTATIC Aspect.hasAspect (Ljava/lang/Object;)Z
+ | | | IFEQ L1
+ | | | ALOAD 8
+ | | | INVOKESTATIC Aspect.aspectOf (Ljava/lang/Object;)LAspect;
+ | | | INVOKEVIRTUAL Aspect.ajc_before ()V
+ | | | L1: ALOAD 8
+ | | | ALOAD 7
+ | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
+ | | method-call(void java.io.PrintStream.println(java.lang.Object))
+ | finally -> E1
+ | GOTO L2
+ | E1: ASTORE 4 (line 14)
+ | JSR L3
+ | ALOAD 4
+ | ATHROW
+ | L2: JSR L3
+ | GOTO L5
+ | L3: ASTORE_3
+ | ALOAD_1 // java.io.PrintStream out (line 15)
+ | LDC "finally"
+ | ASTORE 9
+ | ASTORE 10
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | ALOAD 10
+ | | INVOKESTATIC Aspect.ajc$perObjectBind (Ljava/lang/Object;)V
+ | | ALOAD 10
+ | | INVOKESTATIC Aspect.hasAspect (Ljava/lang/Object;)Z
+ | | IFEQ L4
+ | | ALOAD 10
+ | | INVOKESTATIC Aspect.aspectOf (Ljava/lang/Object;)LAspect;
+ | | INVOKEVIRTUAL Aspect.ajc_before ()V
+ | | L4: ALOAD 10
+ | | ALOAD 9
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RET 3 (line 10)
+ | L5: RETURN (line 17)
+ method-execution(void FancyHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ public static String getName():
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ | ICONST_0 (line 20)
+ | ISTORE_0
+ | ILOAD_0 // int x (line 21)
+ | LDC "name"
+ | method-call(int java.lang.String.hashCode())
+ | | INVOKEVIRTUAL java.lang.String.hashCode ()I
+ | method-call(int java.lang.String.hashCode())
+ | IADD
+ | ISTORE_0 // int x
+ | NEW java.lang.StringBuffer (line 22)
+ | DUP
+ | LDC "name"
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ILOAD_0 // int x
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (I)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | ARETURN
+ method-execution(java.lang.String FancyHelloWorld.getName())
+ end public static String getName()
+end public abstract class FancyHelloWorld
diff --git a/weaver/testdata/PerThisNonStaticBeforeHelloWorld.txt b/weaver/testdata/PerThisNonStaticBeforeHelloWorld.txt
new file mode 100644
index 000000000..7da847852
--- /dev/null
+++ b/weaver/testdata/PerThisNonStaticBeforeHelloWorld.txt
@@ -0,0 +1,34 @@
+public class HelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | ASTORE_1
+ | ASTORE_2
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | ALOAD_2
+ | | INVOKESTATIC Aspect.ajc$perObjectBind (Ljava/lang/Object;)V
+ | | ALOAD_2
+ | | INVOKESTATIC Aspect.hasAspect (Ljava/lang/Object;)Z
+ | | IFEQ L0
+ | | ALOAD_2
+ | | INVOKESTATIC Aspect.aspectOf (Ljava/lang/Object;)LAspect;
+ | | INVOKEVIRTUAL Aspect.ajc_before ()V
+ | | L0: ALOAD_2
+ | | ALOAD_1
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+end public class HelloWorld
diff --git a/weaver/testdata/Regex.jar b/weaver/testdata/Regex.jar
new file mode 100644
index 000000000..713441c52
--- /dev/null
+++ b/weaver/testdata/Regex.jar
Binary files differ
diff --git a/weaver/testdata/StateResidueMultiArgHelloWorld.txt b/weaver/testdata/StateResidueMultiArgHelloWorld.txt
new file mode 100644
index 000000000..55cc92c3e
--- /dev/null
+++ b/weaver/testdata/StateResidueMultiArgHelloWorld.txt
@@ -0,0 +1,62 @@
+public class MultiArgHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // MultiArgHelloWorld this (line 3)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void MultiArgHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void MultiArgHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void MultiArgHelloWorld.main(java.lang.String[]))
+ | LDC "Hello" (line 6)
+ | LDC "World"
+ | ASTORE_1
+ | ASTORE_2
+ | method-call(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ | | ALOAD_2
+ | | INSTANCEOF java.lang.String
+ | | IFEQ L0
+ | | ALOAD_2
+ | | CHECKCAST java.lang.String
+ | | INVOKESTATIC Aspect.ajc_before_0 (Ljava/lang/String;)V
+ | | L0: ALOAD_2
+ | | ALOAD_1
+ | | INVOKESTATIC MultiArgHelloWorld.foo (Ljava/lang/Object;Ljava/lang/Object;)V
+ | method-call(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ | RETURN (line 7)
+ method-execution(void MultiArgHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static void foo(Object, Object):
+ method-execution(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 10)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | NEW java.lang.StringBuffer
+ | DUP
+ | constructor-call(void java.lang.StringBuffer.<init>())
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> ()V
+ | constructor-call(void java.lang.StringBuffer.<init>())
+ | ALOAD_0 // java.lang.Object arg0
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | LDC " "
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/String;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String))
+ | ALOAD_1 // java.lang.Object t
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ end static void foo(Object, Object)
+end public class MultiArgHelloWorld
diff --git a/weaver/testdata/StaticEnclosingTjpBeforeHelloWorld.txt b/weaver/testdata/StaticEnclosingTjpBeforeHelloWorld.txt
new file mode 100644
index 000000000..6d9ed99f5
--- /dev/null
+++ b/weaver/testdata/StaticEnclosingTjpBeforeHelloWorld.txt
@@ -0,0 +1,61 @@
+public class HelloWorld extends java.lang.Object:
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_0
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_1
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | GETSTATIC HelloWorld.ajc$tjp_0 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ | INVOKESTATIC Aspect.ajc_before (Lorg/aspectj/lang/JoinPoint$StaticPart;)V
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | GETSTATIC HelloWorld.ajc$tjp_1 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ | INVOKESTATIC Aspect.ajc_before (Lorg/aspectj/lang/JoinPoint$StaticPart;)V
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC HelloWorld.ajc$tjp_1 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ | | INVOKESTATIC Aspect.ajc_before (Lorg/aspectj/lang/JoinPoint$StaticPart;)V
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | GETSTATIC HelloWorld.ajc$tjp_1 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ | | INVOKESTATIC Aspect.ajc_before (Lorg/aspectj/lang/JoinPoint$StaticPart;)V
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static void <clinit>():
+ NEW org.aspectj.runtime.reflect.Factory
+ DUP
+ LDC "HelloWorld.java"
+ LDC "HelloWorld"
+ INVOKESTATIC java.lang.Class.forName (Ljava/lang/String;)Ljava/lang/Class;
+ INVOKESPECIAL org.aspectj.runtime.reflect.Factory.<init> (Ljava/lang/String;Ljava/lang/Class;)V
+ ASTORE_0
+ ALOAD_0
+ LDC "constructor-execution"
+ ALOAD_0
+ LDC "1--HelloWorld----"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeConstructorSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/ConstructorSignature;
+ BIPUSH 5
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_0 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ LDC "method-execution"
+ ALOAD_0
+ LDC "9-main-HelloWorld-[Ljava/lang/String;:-args:--void-"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeMethodSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/MethodSignature;
+ BIPUSH 8
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_1 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ staticinitialization(void HelloWorld.<clinit>())
+ | RETURN
+ staticinitialization(void HelloWorld.<clinit>())
+ end static void <clinit>()
+end public class HelloWorld
diff --git a/weaver/testdata/StaticTjpBeforeHelloWorld.txt b/weaver/testdata/StaticTjpBeforeHelloWorld.txt
new file mode 100644
index 000000000..3c248872d
--- /dev/null
+++ b/weaver/testdata/StaticTjpBeforeHelloWorld.txt
@@ -0,0 +1,79 @@
+public class HelloWorld extends java.lang.Object:
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_0
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_1
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_2
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_3
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void HelloWorld.<init>())
+ | GETSTATIC HelloWorld.ajc$tjp_0 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ | INVOKESTATIC Aspect.ajc_before (Lorg/aspectj/lang/JoinPoint$StaticPart;)V
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | GETSTATIC HelloWorld.ajc$tjp_3 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ | INVOKESTATIC Aspect.ajc_before (Lorg/aspectj/lang/JoinPoint$StaticPart;)V
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC HelloWorld.ajc$tjp_1 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ | | INVOKESTATIC Aspect.ajc_before (Lorg/aspectj/lang/JoinPoint$StaticPart;)V
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | GETSTATIC HelloWorld.ajc$tjp_2 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ | | INVOKESTATIC Aspect.ajc_before (Lorg/aspectj/lang/JoinPoint$StaticPart;)V
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static void <clinit>():
+ NEW org.aspectj.runtime.reflect.Factory
+ DUP
+ LDC "HelloWorld.java"
+ LDC "HelloWorld"
+ INVOKESTATIC java.lang.Class.forName (Ljava/lang/String;)Ljava/lang/Class;
+ INVOKESPECIAL org.aspectj.runtime.reflect.Factory.<init> (Ljava/lang/String;Ljava/lang/Class;)V
+ ASTORE_0
+ ALOAD_0
+ LDC "constructor-execution"
+ ALOAD_0
+ LDC "1--HelloWorld----"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeConstructorSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/ConstructorSignature;
+ BIPUSH 5
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_0 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ LDC "field-get"
+ ALOAD_0
+ LDC "19-out-java.lang.System-java.io.PrintStream-"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeFieldSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/FieldSignature;
+ BIPUSH 8
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_1 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ LDC "method-call"
+ ALOAD_0
+ LDC "1-println-java.io.PrintStream-java.lang.String:-arg0:--void-"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeMethodSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/MethodSignature;
+ BIPUSH 9
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_2 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ LDC "method-execution"
+ ALOAD_0
+ LDC "9-main-HelloWorld-[Ljava/lang/String;:-args:--void-"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeMethodSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/MethodSignature;
+ BIPUSH 8
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_3 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ staticinitialization(void HelloWorld.<clinit>())
+ | RETURN
+ staticinitialization(void HelloWorld.<clinit>())
+ end static void <clinit>()
+end public class HelloWorld
diff --git a/weaver/testdata/StringResidue1MultiArgHelloWorld.txt b/weaver/testdata/StringResidue1MultiArgHelloWorld.txt
new file mode 100644
index 000000000..ff1add1d2
--- /dev/null
+++ b/weaver/testdata/StringResidue1MultiArgHelloWorld.txt
@@ -0,0 +1,63 @@
+public class MultiArgHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // MultiArgHelloWorld this (line 3)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void MultiArgHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void MultiArgHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void MultiArgHelloWorld.main(java.lang.String[]))
+ | LDC "Hello" (line 6)
+ | LDC "World"
+ | ASTORE_1
+ | ASTORE_2
+ | method-call(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ | | ALOAD_2
+ | | INSTANCEOF java.lang.String
+ | | IFEQ L0
+ | | ALOAD_1
+ | | INSTANCEOF java.lang.String
+ | | IFEQ L0
+ | | INVOKESTATIC Aspect.ajc_before_0 ()V
+ | | L0: ALOAD_2
+ | | ALOAD_1
+ | | INVOKESTATIC MultiArgHelloWorld.foo (Ljava/lang/Object;Ljava/lang/Object;)V
+ | method-call(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ | RETURN (line 7)
+ method-execution(void MultiArgHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static void foo(Object, Object):
+ method-execution(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 10)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | NEW java.lang.StringBuffer
+ | DUP
+ | constructor-call(void java.lang.StringBuffer.<init>())
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> ()V
+ | constructor-call(void java.lang.StringBuffer.<init>())
+ | ALOAD_0 // java.lang.Object arg0
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | LDC " "
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/String;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String))
+ | ALOAD_1 // java.lang.Object t
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ end static void foo(Object, Object)
+end public class MultiArgHelloWorld
diff --git a/weaver/testdata/StringResidue2MultiArgHelloWorld.txt b/weaver/testdata/StringResidue2MultiArgHelloWorld.txt
new file mode 100644
index 000000000..8fb78655d
--- /dev/null
+++ b/weaver/testdata/StringResidue2MultiArgHelloWorld.txt
@@ -0,0 +1,60 @@
+public class MultiArgHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // MultiArgHelloWorld this (line 3)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void MultiArgHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void MultiArgHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void MultiArgHelloWorld.main(java.lang.String[]))
+ | LDC "Hello" (line 6)
+ | LDC "World"
+ | ASTORE_1
+ | ASTORE_2
+ | method-call(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ | | ALOAD_1
+ | | INSTANCEOF java.lang.String
+ | | IFEQ L0
+ | | INVOKESTATIC Aspect.ajc_before_0 ()V
+ | | L0: ALOAD_2
+ | | ALOAD_1
+ | | INVOKESTATIC MultiArgHelloWorld.foo (Ljava/lang/Object;Ljava/lang/Object;)V
+ | method-call(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ | RETURN (line 7)
+ method-execution(void MultiArgHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static void foo(Object, Object):
+ method-execution(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 10)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | NEW java.lang.StringBuffer
+ | DUP
+ | constructor-call(void java.lang.StringBuffer.<init>())
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> ()V
+ | constructor-call(void java.lang.StringBuffer.<init>())
+ | ALOAD_0 // java.lang.Object arg0
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | LDC " "
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/String;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String))
+ | ALOAD_1 // java.lang.Object t
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ end static void foo(Object, Object)
+end public class MultiArgHelloWorld
diff --git a/weaver/testdata/StringResidue3MultiArgHelloWorld.txt b/weaver/testdata/StringResidue3MultiArgHelloWorld.txt
new file mode 100644
index 000000000..6c361581f
--- /dev/null
+++ b/weaver/testdata/StringResidue3MultiArgHelloWorld.txt
@@ -0,0 +1,60 @@
+public class MultiArgHelloWorld extends java.lang.Object:
+ public void <init>():
+ ALOAD_0 // MultiArgHelloWorld this (line 3)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void MultiArgHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void MultiArgHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void MultiArgHelloWorld.main(java.lang.String[]))
+ | LDC "Hello" (line 6)
+ | LDC "World"
+ | ASTORE_1
+ | ASTORE_2
+ | method-call(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ | | ALOAD_2
+ | | INSTANCEOF java.lang.String
+ | | IFEQ L0
+ | | INVOKESTATIC Aspect.ajc_before_0 ()V
+ | | L0: ALOAD_2
+ | | ALOAD_1
+ | | INVOKESTATIC MultiArgHelloWorld.foo (Ljava/lang/Object;Ljava/lang/Object;)V
+ | method-call(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ | RETURN (line 7)
+ method-execution(void MultiArgHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static void foo(Object, Object):
+ method-execution(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 10)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | NEW java.lang.StringBuffer
+ | DUP
+ | constructor-call(void java.lang.StringBuffer.<init>())
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> ()V
+ | constructor-call(void java.lang.StringBuffer.<init>())
+ | ALOAD_0 // java.lang.Object arg0
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | LDC " "
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/String;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.String))
+ | ALOAD_1 // java.lang.Object t
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void MultiArgHelloWorld.foo(java.lang.Object, java.lang.Object))
+ end static void foo(Object, Object)
+end public class MultiArgHelloWorld
diff --git a/weaver/testdata/TjpAround2HelloWorld.txt b/weaver/testdata/TjpAround2HelloWorld.txt
new file mode 100644
index 000000000..8f4b4dea4
--- /dev/null
+++ b/weaver/testdata/TjpAround2HelloWorld.txt
@@ -0,0 +1,503 @@
+public class HelloWorld extends java.lang.Object:
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_0
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_1
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_2
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_3
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ GETSTATIC HelloWorld.ajc$tjp_0 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ ALOAD_0
+ BIPUSH 0
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ INVOKESTATIC org.aspectj.runtime.reflect.Factory.makeJP (Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
+ ASTORE_1
+ constructor-execution(void HelloWorld.<init>())
+ | BIPUSH 2
+ | ANEWARRAY java.lang.Object
+ | ASTORE 4
+ | ALOAD 4
+ | BIPUSH 0
+ | ALOAD_0
+ | AASTORE
+ | ALOAD 4
+ | BIPUSH 1
+ | ALOAD_1
+ | AASTORE
+ | NEW HelloWorld$AjcClosure3
+ | DUP
+ | ALOAD 4
+ | INVOKESPECIAL HelloWorld$AjcClosure3.<init> ([Ljava/lang/Object;)V
+ | ALOAD_1
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;Lorg/aspectj/lang/JoinPoint;)Ljava/lang/Object;
+ | POP
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ ALOAD_0
+ ASTORE 11
+ GETSTATIC HelloWorld.ajc$tjp_3 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ACONST_NULL
+ ACONST_NULL
+ BIPUSH 1
+ ANEWARRAY java.lang.Object
+ ASTORE 13
+ ALOAD 13
+ BIPUSH 0
+ ALOAD 11
+ AASTORE
+ ALOAD 13
+ INVOKESTATIC org.aspectj.runtime.reflect.Factory.makeJP (Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
+ ASTORE 12
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | BIPUSH 2
+ | ANEWARRAY java.lang.Object
+ | ASTORE 15
+ | ALOAD 15
+ | BIPUSH 0
+ | ALOAD 11
+ | AASTORE
+ | ALOAD 15
+ | BIPUSH 1
+ | ALOAD 12
+ | AASTORE
+ | NEW HelloWorld$AjcClosure15
+ | DUP
+ | ALOAD 15
+ | INVOKESPECIAL HelloWorld$AjcClosure15.<init> ([Ljava/lang/Object;)V
+ | ALOAD 12
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;Lorg/aspectj/lang/JoinPoint;)Ljava/lang/Object;
+ | POP
+ | RETURN
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static void <clinit>():
+ NEW org.aspectj.runtime.reflect.Factory
+ DUP
+ LDC "HelloWorld.java"
+ LDC "HelloWorld"
+ INVOKESTATIC java.lang.Class.forName (Ljava/lang/String;)Ljava/lang/Class;
+ INVOKESPECIAL org.aspectj.runtime.reflect.Factory.<init> (Ljava/lang/String;Ljava/lang/Class;)V
+ ASTORE_0
+ ALOAD_0
+ LDC "constructor-execution"
+ ALOAD_0
+ LDC "1--HelloWorld----"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeConstructorSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/ConstructorSignature;
+ BIPUSH 5
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_0 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ LDC "field-get"
+ ALOAD_0
+ LDC "19-out-java.lang.System-java.io.PrintStream-"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeFieldSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/FieldSignature;
+ BIPUSH 8
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_1 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ LDC "method-call"
+ ALOAD_0
+ LDC "1-println-java.io.PrintStream-java.lang.String:-arg0:--void-"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeMethodSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/MethodSignature;
+ BIPUSH 9
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_2 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ LDC "method-execution"
+ ALOAD_0
+ LDC "9-main-HelloWorld-[Ljava/lang/String;:-args:--void-"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeMethodSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/MethodSignature;
+ BIPUSH 8
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_3 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ staticinitialization(void HelloWorld.<clinit>())
+ | RETURN
+ staticinitialization(void HelloWorld.<clinit>())
+ end static void <clinit>()
+
+ static final void init$_aroundBody0(HelloWorld, org.aspectj.lang.JoinPoint):
+ RETURN (line 5)
+ end static final void init$_aroundBody0(HelloWorld, org.aspectj.lang.JoinPoint)
+
+ static final void init$_aroundBody2(HelloWorld, org.aspectj.lang.JoinPoint):
+ BIPUSH 2
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ ALOAD_2
+ BIPUSH 1
+ ALOAD_1
+ AASTORE
+ NEW HelloWorld$AjcClosure1
+ DUP
+ ALOAD_2
+ INVOKESPECIAL HelloWorld$AjcClosure1.<init> ([Ljava/lang/Object;)V
+ ALOAD_1
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;Lorg/aspectj/lang/JoinPoint;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void init$_aroundBody2(HelloWorld, org.aspectj.lang.JoinPoint)
+
+ static final java.io.PrintStream out_aroundBody4(org.aspectj.lang.JoinPoint):
+ GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ ARETURN
+ end static final java.io.PrintStream out_aroundBody4(org.aspectj.lang.JoinPoint)
+
+ static final java.io.PrintStream out_aroundBody6(org.aspectj.lang.JoinPoint):
+ BIPUSH 1
+ ANEWARRAY java.lang.Object
+ ASTORE_1
+ ALOAD_1
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ NEW HelloWorld$AjcClosure5
+ DUP
+ ALOAD_1
+ INVOKESPECIAL HelloWorld$AjcClosure5.<init> ([Ljava/lang/Object;)V
+ ALOAD_0
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;Lorg/aspectj/lang/JoinPoint;)Ljava/lang/Object;
+ CHECKCAST java.io.PrintStream
+ ARETURN
+ end static final java.io.PrintStream out_aroundBody6(org.aspectj.lang.JoinPoint)
+
+ static final void println_aroundBody8(java.io.PrintStream, String, org.aspectj.lang.JoinPoint):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 9)
+ RETURN
+ end static final void println_aroundBody8(java.io.PrintStream, String, org.aspectj.lang.JoinPoint)
+
+ static final void println_aroundBody10(java.io.PrintStream, String, org.aspectj.lang.JoinPoint):
+ BIPUSH 3
+ ANEWARRAY java.lang.Object
+ ASTORE_3
+ ALOAD_3
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ ALOAD_3
+ BIPUSH 1
+ ALOAD_1
+ AASTORE
+ ALOAD_3
+ BIPUSH 2
+ ALOAD_2
+ AASTORE
+ NEW HelloWorld$AjcClosure9
+ DUP
+ ALOAD_3
+ INVOKESPECIAL HelloWorld$AjcClosure9.<init> ([Ljava/lang/Object;)V
+ ALOAD_2
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;Lorg/aspectj/lang/JoinPoint;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void println_aroundBody10(java.io.PrintStream, String, org.aspectj.lang.JoinPoint)
+
+ static final void main_aroundBody12(String[], org.aspectj.lang.JoinPoint):
+ GETSTATIC HelloWorld.ajc$tjp_1 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ACONST_NULL
+ ACONST_NULL
+ BIPUSH 0
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ INVOKESTATIC org.aspectj.runtime.reflect.Factory.makeJP (Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
+ ASTORE 4
+ field-get(java.io.PrintStream java.lang.System.out)
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE 6
+ | ALOAD 6
+ | BIPUSH 0
+ | ALOAD 4
+ | AASTORE
+ | NEW HelloWorld$AjcClosure7
+ | DUP
+ | ALOAD 6
+ | INVOKESPECIAL HelloWorld$AjcClosure7.<init> ([Ljava/lang/Object;)V
+ | ALOAD 4
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;Lorg/aspectj/lang/JoinPoint;)Ljava/lang/Object;
+ | CHECKCAST java.io.PrintStream
+ field-get(java.io.PrintStream java.lang.System.out)
+ LDC "hello world" (line 9)
+ ASTORE 8
+ ASTORE 10
+ GETSTATIC HelloWorld.ajc$tjp_2 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ACONST_NULL
+ ALOAD 10
+ BIPUSH 1
+ ANEWARRAY java.lang.Object
+ ASTORE 12
+ ALOAD 12
+ BIPUSH 0
+ ALOAD 8
+ AASTORE
+ ALOAD 12
+ INVOKESTATIC org.aspectj.runtime.reflect.Factory.makeJP (Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
+ ASTORE 14
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ | BIPUSH 3
+ | ANEWARRAY java.lang.Object
+ | ASTORE 16
+ | ALOAD 16
+ | BIPUSH 0
+ | ALOAD 10
+ | AASTORE
+ | ALOAD 16
+ | BIPUSH 1
+ | ALOAD 8
+ | AASTORE
+ | ALOAD 16
+ | BIPUSH 2
+ | ALOAD 14
+ | AASTORE
+ | NEW HelloWorld$AjcClosure11
+ | DUP
+ | ALOAD 16
+ | INVOKESPECIAL HelloWorld$AjcClosure11.<init> ([Ljava/lang/Object;)V
+ | ALOAD 14
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;Lorg/aspectj/lang/JoinPoint;)Ljava/lang/Object;
+ | POP
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ RETURN (line 11)
+ end static final void main_aroundBody12(String[], org.aspectj.lang.JoinPoint)
+
+ static final void main_aroundBody14(String[], org.aspectj.lang.JoinPoint):
+ BIPUSH 2
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ ALOAD_2
+ BIPUSH 1
+ ALOAD_1
+ AASTORE
+ NEW HelloWorld$AjcClosure13
+ DUP
+ ALOAD_2
+ INVOKESPECIAL HelloWorld$AjcClosure13.<init> ([Ljava/lang/Object;)V
+ ALOAD_1
+ INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;Lorg/aspectj/lang/JoinPoint;)Ljava/lang/Object;
+ POP
+ RETURN
+ end static final void main_aroundBody14(String[], org.aspectj.lang.JoinPoint)
+end public class HelloWorld
+
+public class HelloWorld$AjcClosure1 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST HelloWorld
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST org.aspectj.lang.JoinPoint
+ INVOKESTATIC HelloWorld.init$_aroundBody0 (LHelloWorld;Lorg/aspectj/lang/JoinPoint;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure1
+
+public class HelloWorld$AjcClosure3 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST HelloWorld
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST org.aspectj.lang.JoinPoint
+ INVOKESTATIC HelloWorld.init$_aroundBody2 (LHelloWorld;Lorg/aspectj/lang/JoinPoint;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure3
+
+public class HelloWorld$AjcClosure5 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST org.aspectj.lang.JoinPoint
+ INVOKESTATIC HelloWorld.out_aroundBody4 (Lorg/aspectj/lang/JoinPoint;)Ljava/io/PrintStream;
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure5
+
+public class HelloWorld$AjcClosure7 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST org.aspectj.lang.JoinPoint
+ INVOKESTATIC HelloWorld.out_aroundBody6 (Lorg/aspectj/lang/JoinPoint;)Ljava/io/PrintStream;
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure7
+
+public class HelloWorld$AjcClosure9 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ ALOAD_2
+ BIPUSH 2
+ AALOAD
+ CHECKCAST org.aspectj.lang.JoinPoint
+ INVOKESTATIC HelloWorld.println_aroundBody8 (Ljava/io/PrintStream;Ljava/lang/String;Lorg/aspectj/lang/JoinPoint;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure9
+
+public class HelloWorld$AjcClosure11 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ ALOAD_2
+ BIPUSH 2
+ AALOAD
+ CHECKCAST org.aspectj.lang.JoinPoint
+ INVOKESTATIC HelloWorld.println_aroundBody10 (Ljava/io/PrintStream;Ljava/lang/String;Lorg/aspectj/lang/JoinPoint;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure11
+
+public class HelloWorld$AjcClosure13 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST [Ljava.lang.String;
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST org.aspectj.lang.JoinPoint
+ INVOKESTATIC HelloWorld.main_aroundBody12 ([Ljava/lang/String;Lorg/aspectj/lang/JoinPoint;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure13
+
+public class HelloWorld$AjcClosure15 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST [Ljava.lang.String;
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST org.aspectj.lang.JoinPoint
+ INVOKESTATIC HelloWorld.main_aroundBody14 ([Ljava/lang/String;Lorg/aspectj/lang/JoinPoint;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure15
diff --git a/weaver/testdata/TjpAroundHelloWorld.txt b/weaver/testdata/TjpAroundHelloWorld.txt
new file mode 100644
index 000000000..d1424058e
--- /dev/null
+++ b/weaver/testdata/TjpAroundHelloWorld.txt
@@ -0,0 +1,312 @@
+public class HelloWorld extends java.lang.Object:
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_0
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_1
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_2
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_3
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ GETSTATIC HelloWorld.ajc$tjp_0 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ ALOAD_0
+ BIPUSH 0
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ INVOKESTATIC org.aspectj.runtime.reflect.Factory.makeJP (Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
+ ASTORE_1
+ constructor-execution(void HelloWorld.<init>())
+ | BIPUSH 2
+ | ANEWARRAY java.lang.Object
+ | ASTORE_3
+ | ALOAD_3
+ | BIPUSH 0
+ | ALOAD_0
+ | AASTORE
+ | ALOAD_3
+ | BIPUSH 1
+ | ALOAD_1
+ | AASTORE
+ | NEW HelloWorld$AjcClosure1
+ | DUP
+ | ALOAD_3
+ | INVOKESPECIAL HelloWorld$AjcClosure1.<init> ([Ljava/lang/Object;)V
+ | ALOAD_1
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;Lorg/aspectj/lang/JoinPoint;)Ljava/lang/Object;
+ | POP
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ ALOAD_0
+ ASTORE 9
+ GETSTATIC HelloWorld.ajc$tjp_3 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ACONST_NULL
+ ACONST_NULL
+ BIPUSH 1
+ ANEWARRAY java.lang.Object
+ ASTORE 11
+ ALOAD 11
+ BIPUSH 0
+ ALOAD 9
+ AASTORE
+ ALOAD 11
+ INVOKESTATIC org.aspectj.runtime.reflect.Factory.makeJP (Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
+ ASTORE 10
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | BIPUSH 2
+ | ANEWARRAY java.lang.Object
+ | ASTORE 12
+ | ALOAD 12
+ | BIPUSH 0
+ | ALOAD 9
+ | AASTORE
+ | ALOAD 12
+ | BIPUSH 1
+ | ALOAD 10
+ | AASTORE
+ | NEW HelloWorld$AjcClosure7
+ | DUP
+ | ALOAD 12
+ | INVOKESPECIAL HelloWorld$AjcClosure7.<init> ([Ljava/lang/Object;)V
+ | ALOAD 10
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;Lorg/aspectj/lang/JoinPoint;)Ljava/lang/Object;
+ | POP
+ | RETURN
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static void <clinit>():
+ NEW org.aspectj.runtime.reflect.Factory
+ DUP
+ LDC "HelloWorld.java"
+ LDC "HelloWorld"
+ INVOKESTATIC java.lang.Class.forName (Ljava/lang/String;)Ljava/lang/Class;
+ INVOKESPECIAL org.aspectj.runtime.reflect.Factory.<init> (Ljava/lang/String;Ljava/lang/Class;)V
+ ASTORE_0
+ ALOAD_0
+ LDC "constructor-execution"
+ ALOAD_0
+ LDC "1--HelloWorld----"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeConstructorSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/ConstructorSignature;
+ BIPUSH 5
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_0 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ LDC "field-get"
+ ALOAD_0
+ LDC "19-out-java.lang.System-java.io.PrintStream-"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeFieldSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/FieldSignature;
+ BIPUSH 8
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_1 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ LDC "method-call"
+ ALOAD_0
+ LDC "1-println-java.io.PrintStream-java.lang.String:-arg0:--void-"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeMethodSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/MethodSignature;
+ BIPUSH 9
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_2 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ LDC "method-execution"
+ ALOAD_0
+ LDC "9-main-HelloWorld-[Ljava/lang/String;:-args:--void-"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeMethodSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/MethodSignature;
+ BIPUSH 8
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_3 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ staticinitialization(void HelloWorld.<clinit>())
+ | RETURN
+ staticinitialization(void HelloWorld.<clinit>())
+ end static void <clinit>()
+
+ static final void init$_aroundBody0(HelloWorld, org.aspectj.lang.JoinPoint):
+ RETURN (line 5)
+ end static final void init$_aroundBody0(HelloWorld, org.aspectj.lang.JoinPoint)
+
+ static final java.io.PrintStream out_aroundBody2(org.aspectj.lang.JoinPoint):
+ GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ ARETURN
+ end static final java.io.PrintStream out_aroundBody2(org.aspectj.lang.JoinPoint)
+
+ static final void println_aroundBody4(java.io.PrintStream, String, org.aspectj.lang.JoinPoint):
+ ALOAD_0
+ ALOAD_1
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V (line 9)
+ RETURN
+ end static final void println_aroundBody4(java.io.PrintStream, String, org.aspectj.lang.JoinPoint)
+
+ static final void main_aroundBody6(String[], org.aspectj.lang.JoinPoint):
+ GETSTATIC HelloWorld.ajc$tjp_1 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ACONST_NULL
+ ACONST_NULL
+ BIPUSH 0
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ INVOKESTATIC org.aspectj.runtime.reflect.Factory.makeJP (Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
+ ASTORE 4
+ field-get(java.io.PrintStream java.lang.System.out)
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE 6
+ | ALOAD 6
+ | BIPUSH 0
+ | ALOAD 4
+ | AASTORE
+ | NEW HelloWorld$AjcClosure3
+ | DUP
+ | ALOAD 6
+ | INVOKESPECIAL HelloWorld$AjcClosure3.<init> ([Ljava/lang/Object;)V
+ | ALOAD 4
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;Lorg/aspectj/lang/JoinPoint;)Ljava/lang/Object;
+ | CHECKCAST java.io.PrintStream
+ field-get(java.io.PrintStream java.lang.System.out)
+ LDC "hello world" (line 9)
+ ASTORE 8
+ ASTORE 10
+ GETSTATIC HelloWorld.ajc$tjp_2 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ACONST_NULL
+ ALOAD 10
+ BIPUSH 1
+ ANEWARRAY java.lang.Object
+ ASTORE 12
+ ALOAD 12
+ BIPUSH 0
+ ALOAD 8
+ AASTORE
+ ALOAD 12
+ INVOKESTATIC org.aspectj.runtime.reflect.Factory.makeJP (Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
+ ASTORE 14
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ | BIPUSH 3
+ | ANEWARRAY java.lang.Object
+ | ASTORE 16
+ | ALOAD 16
+ | BIPUSH 0
+ | ALOAD 10
+ | AASTORE
+ | ALOAD 16
+ | BIPUSH 1
+ | ALOAD 8
+ | AASTORE
+ | ALOAD 16
+ | BIPUSH 2
+ | ALOAD 14
+ | AASTORE
+ | NEW HelloWorld$AjcClosure5
+ | DUP
+ | ALOAD 16
+ | INVOKESPECIAL HelloWorld$AjcClosure5.<init> ([Ljava/lang/Object;)V
+ | ALOAD 14
+ | INVOKESTATIC Aspect.ajc_around (Lorg/aspectj/runtime/internal/AroundClosure;Lorg/aspectj/lang/JoinPoint;)Ljava/lang/Object;
+ | POP
+ method-call(void java.io.PrintStream.println(java.lang.String))
+ RETURN (line 11)
+ end static final void main_aroundBody6(String[], org.aspectj.lang.JoinPoint)
+end public class HelloWorld
+
+public class HelloWorld$AjcClosure1 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST HelloWorld
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST org.aspectj.lang.JoinPoint
+ INVOKESTATIC HelloWorld.init$_aroundBody0 (LHelloWorld;Lorg/aspectj/lang/JoinPoint;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure1
+
+public class HelloWorld$AjcClosure3 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST org.aspectj.lang.JoinPoint
+ INVOKESTATIC HelloWorld.out_aroundBody2 (Lorg/aspectj/lang/JoinPoint;)Ljava/io/PrintStream;
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure3
+
+public class HelloWorld$AjcClosure5 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST java.io.PrintStream
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ ALOAD_2
+ BIPUSH 2
+ AALOAD
+ CHECKCAST org.aspectj.lang.JoinPoint
+ INVOKESTATIC HelloWorld.println_aroundBody4 (Ljava/io/PrintStream;Ljava/lang/String;Lorg/aspectj/lang/JoinPoint;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure5
+
+public class HelloWorld$AjcClosure7 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST [Ljava.lang.String;
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST org.aspectj.lang.JoinPoint
+ INVOKESTATIC HelloWorld.main_aroundBody6 ([Ljava/lang/String;Lorg/aspectj/lang/JoinPoint;)V
+ ACONST_NULL
+ ARETURN
+ end public Object run(Object[])
+end public class HelloWorld$AjcClosure7
diff --git a/weaver/testdata/TjpBeforeHelloWorld.txt b/weaver/testdata/TjpBeforeHelloWorld.txt
new file mode 100644
index 000000000..b63dde298
--- /dev/null
+++ b/weaver/testdata/TjpBeforeHelloWorld.txt
@@ -0,0 +1,129 @@
+public class HelloWorld extends java.lang.Object:
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_0
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_1
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_2
+ public static final org.aspectj.lang.JoinPoint$StaticPart ajc$tjp_3
+ public void <init>():
+ ALOAD_0 // HelloWorld this (line 5)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ GETSTATIC HelloWorld.ajc$tjp_0 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ ALOAD_0
+ BIPUSH 0
+ ANEWARRAY java.lang.Object
+ ASTORE_2
+ ALOAD_2
+ INVOKESTATIC org.aspectj.runtime.reflect.Factory.makeJP (Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
+ ASTORE_1
+ constructor-execution(void HelloWorld.<init>())
+ | ALOAD_1
+ | INVOKESTATIC Aspect.ajc_before (Lorg/aspectj/lang/JoinPoint;)V
+ | RETURN
+ constructor-execution(void HelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ ALOAD_0
+ ASTORE 9
+ GETSTATIC HelloWorld.ajc$tjp_3 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ACONST_NULL
+ ACONST_NULL
+ BIPUSH 1
+ ANEWARRAY java.lang.Object
+ ASTORE 8
+ ALOAD 8
+ BIPUSH 0
+ ALOAD 9
+ AASTORE
+ ALOAD 8
+ INVOKESTATIC org.aspectj.runtime.reflect.Factory.makeJP (Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
+ ASTORE 7
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ | ALOAD 7
+ | INVOKESTATIC Aspect.ajc_before (Lorg/aspectj/lang/JoinPoint;)V
+ | GETSTATIC HelloWorld.ajc$tjp_1 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ | ACONST_NULL
+ | ACONST_NULL
+ | BIPUSH 0
+ | ANEWARRAY java.lang.Object
+ | ASTORE_2
+ | ALOAD_2
+ | INVOKESTATIC org.aspectj.runtime.reflect.Factory.makeJP (Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
+ | ASTORE_1
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | ALOAD_1
+ | | INVOKESTATIC Aspect.ajc_before (Lorg/aspectj/lang/JoinPoint;)V
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 8)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | LDC "hello world" (line 9)
+ | ASTORE 4
+ | ASTORE 5
+ | GETSTATIC HelloWorld.ajc$tjp_2 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ | ACONST_NULL
+ | ALOAD 5
+ | BIPUSH 1
+ | ANEWARRAY java.lang.Object
+ | ASTORE 6
+ | ALOAD 6
+ | BIPUSH 0
+ | ALOAD 4
+ | AASTORE
+ | ALOAD 6
+ | INVOKESTATIC org.aspectj.runtime.reflect.Factory.makeJP (Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint;
+ | ASTORE_3
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | ALOAD_3
+ | | INVOKESTATIC Aspect.ajc_before (Lorg/aspectj/lang/JoinPoint;)V
+ | | ALOAD 5
+ | | ALOAD 4
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 11)
+ method-execution(void HelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ static void <clinit>():
+ NEW org.aspectj.runtime.reflect.Factory
+ DUP
+ LDC "HelloWorld.java"
+ LDC "HelloWorld"
+ INVOKESTATIC java.lang.Class.forName (Ljava/lang/String;)Ljava/lang/Class;
+ INVOKESPECIAL org.aspectj.runtime.reflect.Factory.<init> (Ljava/lang/String;Ljava/lang/Class;)V
+ ASTORE_0
+ ALOAD_0
+ LDC "constructor-execution"
+ ALOAD_0
+ LDC "1--HelloWorld----"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeConstructorSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/ConstructorSignature;
+ BIPUSH 5
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_0 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ LDC "field-get"
+ ALOAD_0
+ LDC "19-out-java.lang.System-java.io.PrintStream-"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeFieldSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/FieldSignature;
+ BIPUSH 8
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_1 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ LDC "method-call"
+ ALOAD_0
+ LDC "1-println-java.io.PrintStream-java.lang.String:-arg0:--void-"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeMethodSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/MethodSignature;
+ BIPUSH 9
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_2 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ ALOAD_0
+ LDC "method-execution"
+ ALOAD_0
+ LDC "9-main-HelloWorld-[Ljava/lang/String;:-args:--void-"
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeMethodSig (Ljava/lang/String;)Lorg/aspectj/lang/reflect/MethodSignature;
+ BIPUSH 8
+ INVOKEVIRTUAL org.aspectj.runtime.reflect.Factory.makeSJP (Ljava/lang/String;Lorg/aspectj/lang/Signature;I)Lorg/aspectj/lang/JoinPoint$StaticPart;
+ PUTSTATIC HelloWorld.ajc$tjp_3 Lorg/aspectj/lang/JoinPoint$StaticPart;
+ staticinitialization(void HelloWorld.<clinit>())
+ | RETURN
+ staticinitialization(void HelloWorld.<clinit>())
+ end static void <clinit>()
+end public class HelloWorld
diff --git a/weaver/testdata/TraceJarHello.txt b/weaver/testdata/TraceJarHello.txt
new file mode 100644
index 000000000..0741a7ac1
--- /dev/null
+++ b/weaver/testdata/TraceJarHello.txt
@@ -0,0 +1,199 @@
+public class DynamicHelloWorld extends java.lang.Object implements java.io.Serializable:
+ public void <init>():
+ ALOAD_0 // DynamicHelloWorld this (line 8)
+ INVOKESPECIAL java.lang.Object.<init> ()V
+ constructor-execution(void DynamicHelloWorld.<init>())
+ | RETURN
+ constructor-execution(void DynamicHelloWorld.<init>())
+ end public void <init>()
+
+ public static void main(String[]):
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ | catch java.lang.UnsupportedOperationException -> E0
+ | | NEW DynamicHelloWorld (line 12)
+ | | DUP
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | | INVOKESPECIAL DynamicHelloWorld.<init> ()V
+ | | constructor-call(void DynamicHelloWorld.<init>())
+ | | LDC "hello"
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | | GETSTATIC java.util.Collections.EMPTY_LIST Ljava/util/List;
+ | | field-get(java.util.List java.util.Collections.EMPTY_LIST)
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | | INVOKEVIRTUAL DynamicHelloWorld.doit (Ljava/lang/String;Ljava/util/List;)Ljava/lang/String;
+ | | method-call(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | | POP
+ | | GOTO L0
+ | catch java.lang.UnsupportedOperationException -> E0
+ | E0: ASTORE_1 (line 13)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 14)
+ | field-get(java.io.PrintStream java.lang.System.out)
+ | NEW java.lang.StringBuffer
+ | DUP
+ | LDC "expected and caught: "
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))
+ | ALOAD_1 // java.lang.UnsupportedOperationException t
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | method-call(java.lang.StringBuffer java.lang.StringBuffer.append(java.lang.Object))
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | method-call(java.lang.String java.lang.StringBuffer.toString())
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | method-call(void java.io.PrintStream.println(java.lang.String))
+ | RETURN (line 15)
+ | L0: NEW java.lang.RuntimeException (line 17)
+ | DUP
+ | LDC "should have caught exception"
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | | INVOKESPECIAL java.lang.RuntimeException.<init> (Ljava/lang/String;)V
+ | constructor-call(void java.lang.RuntimeException.<init>(java.lang.String))
+ | ATHROW
+ method-execution(void DynamicHelloWorld.main(java.lang.String[]))
+ end public static void main(String[])
+
+ String doit(String, java.util.List):
+ ALOAD_1
+ ASTORE_3
+ ALOAD_2
+ ASTORE 4
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ | GETSTATIC MyTrace.ajc$perSingletonInstance LMyTrace;
+ | ALOAD_0
+ | INVOKEVIRTUAL Trace.ajc$before$Trace$51 (Ljava/lang/Object;)V
+ | GETSTATIC MyTrace.ajc$perSingletonInstance LMyTrace;
+ | BIPUSH 3
+ | ANEWARRAY java.lang.Object
+ | ASTORE 6
+ | ALOAD 6
+ | BIPUSH 0
+ | ALOAD_0
+ | AASTORE
+ | ALOAD 6
+ | BIPUSH 1
+ | ALOAD_3
+ | AASTORE
+ | ALOAD 6
+ | BIPUSH 2
+ | ALOAD 4
+ | AASTORE
+ | NEW DynamicHelloWorld$AjcClosure3
+ | DUP
+ | ALOAD 6
+ | INVOKESPECIAL DynamicHelloWorld$AjcClosure3.<init> ([Ljava/lang/Object;)V
+ | INVOKEVIRTUAL Trace.ajc$around$Trace$cc (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ | CHECKCAST java.lang.String
+ | GOTO L0
+ | L0: DUP
+ | ASTORE 7
+ | GETSTATIC MyTrace.ajc$perSingletonInstance LMyTrace;
+ | ALOAD_0
+ | ALOAD 7
+ | INVOKEVIRTUAL MyTrace.ajc$afterReturning$MyTrace$6e (Ljava/lang/Object;Ljava/lang/Object;)V
+ | ARETURN
+ method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
+ end String doit(String, java.util.List)
+
+ static final String doit_aroundBody0(DynamicHelloWorld, String, java.util.List):
+ ALOAD_2 (line 21)
+ ALOAD_1
+ method-call(boolean java.util.List.add(java.lang.Object))
+ | INVOKEINTERFACE java.util.List.add (Ljava/lang/Object;)Z
+ method-call(boolean java.util.List.add(java.lang.Object))
+ POP
+ ALOAD_2 (line 22)
+ method-call(java.lang.String java.lang.Object.toString())
+ | INVOKEVIRTUAL java.lang.Object.toString ()Ljava/lang/String;
+ method-call(java.lang.String java.lang.Object.toString())
+ ARETURN
+ end static final String doit_aroundBody0(DynamicHelloWorld, String, java.util.List)
+
+ static final String doit_aroundBody2(DynamicHelloWorld, String, java.util.List):
+ GETSTATIC MyTrace.ajc$perSingletonInstance LMyTrace;
+ ALOAD_0
+ BIPUSH 3
+ ANEWARRAY java.lang.Object
+ ASTORE_3
+ ALOAD_3
+ BIPUSH 0
+ ALOAD_0
+ AASTORE
+ ALOAD_3
+ BIPUSH 1
+ ALOAD_1
+ AASTORE
+ ALOAD_3
+ BIPUSH 2
+ ALOAD_2
+ AASTORE
+ NEW DynamicHelloWorld$AjcClosure1
+ DUP
+ ALOAD_3
+ INVOKESPECIAL DynamicHelloWorld$AjcClosure1.<init> ([Ljava/lang/Object;)V
+ INVOKEVIRTUAL Trace.ajc$around$Trace$1bc (Ljava/lang/Object;Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
+ CHECKCAST java.lang.String
+ ARETURN
+ end static final String doit_aroundBody2(DynamicHelloWorld, String, java.util.List)
+end public class DynamicHelloWorld
+
+public class DynamicHelloWorld$AjcClosure1 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_1
+ BIPUSH 0
+ AALOAD
+ CHECKCAST DynamicHelloWorld
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ ALOAD_2
+ BIPUSH 2
+ AALOAD
+ CHECKCAST java.util.List
+ INVOKESTATIC DynamicHelloWorld.doit_aroundBody0 (LDynamicHelloWorld;Ljava/lang/String;Ljava/util/List;)Ljava/lang/String;
+ ARETURN
+ end public Object run(Object[])
+end public class DynamicHelloWorld$AjcClosure1
+
+public class DynamicHelloWorld$AjcClosure3 extends org.aspectj.runtime.internal.AroundClosure:
+ public void <init>(Object[]):
+ ALOAD_0
+ ALOAD_1
+ INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
+ RETURN
+ end public void <init>(Object[])
+
+ public Object run(Object[]):
+ ALOAD_0
+ GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
+ ASTORE_2
+ ALOAD_2
+ BIPUSH 0
+ AALOAD
+ CHECKCAST DynamicHelloWorld
+ ALOAD_2
+ BIPUSH 1
+ AALOAD
+ CHECKCAST java.lang.String
+ ALOAD_2
+ BIPUSH 2
+ AALOAD
+ CHECKCAST java.util.List
+ INVOKESTATIC DynamicHelloWorld.doit_aroundBody2 (LDynamicHelloWorld;Ljava/lang/String;Ljava/util/List;)Ljava/lang/String;
+ ARETURN
+ end public Object run(Object[])
+end public class DynamicHelloWorld$AjcClosure3
diff --git a/weaver/testdata/aspectjtools.jar b/weaver/testdata/aspectjtools.jar
new file mode 100644
index 000000000..b75dfa0ee
--- /dev/null
+++ b/weaver/testdata/aspectjtools.jar
Binary files differ
diff --git a/weaver/testdata/dummyAspect.jar b/weaver/testdata/dummyAspect.jar
new file mode 100644
index 000000000..d43326ab1
--- /dev/null
+++ b/weaver/testdata/dummyAspect.jar
Binary files differ
diff --git a/weaver/testdata/megatrace.jar b/weaver/testdata/megatrace.jar
new file mode 100644
index 000000000..cd9a39fde
--- /dev/null
+++ b/weaver/testdata/megatrace.jar
Binary files differ
diff --git a/weaver/testdata/megatraceNoweave.jar b/weaver/testdata/megatraceNoweave.jar
new file mode 100644
index 000000000..ec73b528a
--- /dev/null
+++ b/weaver/testdata/megatraceNoweave.jar
Binary files differ
diff --git a/weaver/testdata/tracing.jar b/weaver/testdata/tracing.jar
new file mode 100644
index 000000000..b43613e79
--- /dev/null
+++ b/weaver/testdata/tracing.jar
Binary files differ
diff --git a/weaver/testsrc/Aspect.java b/weaver/testsrc/Aspect.java
new file mode 100644
index 000000000..bdb8108f4
--- /dev/null
+++ b/weaver/testsrc/Aspect.java
@@ -0,0 +1,347 @@
+/* This file is part of the compiler and core tools for the AspectJ(tm)
+ * programming language; see http://aspectj.org
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is AspectJ.
+ *
+ * The Initial Developer of the Original Code is Palo Alto Research Center,
+ * Incorporated (PARC). Portions created by PARC are are
+ * Copyright (C) 2002 Palo Alto Research Center, Incorporated.
+ * All Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+import java.util.*;
+
+import org.aspectj.runtime.internal.*;
+import org.aspectj.runtime.internal.AroundClosure;
+import org.aspectj.lang.JoinPoint;
+
+public class Aspect {
+
+ public static void ajc_before_0() {
+ System.out.println("before_0");
+ }
+ public static void ajc_before_0(String s) {
+ System.out.println("before_0: " + s);
+ }
+ public static boolean ajc_around_0(ArrayList s, AroundClosure c) throws Throwable {
+ System.out.println("doing around, got " + s);
+ Object ret = c.run(new Object[] {s}); // proceed(s)
+ return ((Boolean) ret).booleanValue();
+ }
+
+ public static void ajc_before_0(java.util.ArrayList list) {
+ System.out.println("before_0: " + list);
+ }
+
+ public static void ajc_before_method_execution() {
+
+ }
+ public static void ajc_before_method_execution(Object o) {
+ System.out.println("before_method_execution: " + o);
+ }
+
+ public static void ajc_after_method_execution() {
+ System.out.println("after_method_execution");
+ }
+ public static void ajc_after_method_execution(Object o) {
+ System.out.println("after_method_execution: " + o);
+ }
+
+ public static void ajc_afterReturning_method_execution() {
+ System.out.println("ajc_afterReturning_method_execution");
+ }
+ public static void ajc_afterReturning_method_execution(Object o) {
+ System.out.println("afterReturning_method_execution: " + o);
+ }
+
+ public static void ajc_afterThrowing_method_execution() {
+ System.out.println("ajc_afterThrowing_method_execution");
+ }
+ public static void ajc_afterThrowing_method_execution(Object o) {
+ System.out.println("afterThrowing_method_execution: " + o);
+ }
+
+
+
+
+
+ public static Object ajc_around(AroundClosure closure) throws Throwable {
+ Object ret = closure.run(new Object[] {});
+ return ret;
+ }
+
+ public static Object ajc_around(AroundClosure closure, JoinPoint tjp) throws Throwable {
+ System.out.println("thisJoinPoint: " + tjp);
+ Object ret = closure.run(new Object[] {});
+ return ret;
+ }
+
+ // ---
+
+
+ public static void ajc_before_method_call() {
+ System.out.println("before_method_call");
+ }
+ public static void ajc_before_method_call(Object o) {
+ System.out.println("before_method_call: " + o);
+ }
+
+ public static void ajc_after_method_call() {
+ System.out.println("after_method_call");
+ }
+ public static void ajc_after_method_call(Object o) {
+ System.out.println("after_method_call: " + o);
+ }
+
+ public static void ajc_afterReturning_method_call() {
+ System.out.println("ajc_afterReturning_method_call");
+ }
+ public static void ajc_afterReturning_method_call(Object o) {
+ System.out.println("afterReturning_method_call: " + o);
+ }
+
+ public static void ajc_afterThrowing_method_call() {
+ System.out.println("ajc_afterThrowing_method_call");
+ }
+ public static void ajc_afterThrowing_method_call(Object o) {
+ System.out.println("afterThrowing_method_call: " + o);
+ }
+
+ public static Object ajc_around_method_call(AroundClosure closure) throws Throwable {
+ Object ret = null;
+ for (int i=0; i<3; i++) {
+ System.out.println("enter: " + i);
+ ret = closure.run(new Object[] {});
+ }
+ return ret;
+ }
+
+ // ----
+
+ public static void ajc_before_constructor_call() {
+ System.out.println("before_constructor_call");
+ }
+ public static void ajc_before_constructor_call(Object o) {
+ System.out.println("before_constructor_call: " + o);
+ }
+
+ public static void ajc_after_constructor_call() {
+ System.out.println("after_constructor_call");
+ }
+ public static void ajc_after_constructor_call(Object o) {
+ System.out.println("after_constructor_call: " + o);
+ }
+
+ public static void ajc_afterReturning_constructor_call() {
+ System.out.println("ajc_afterReturning_constructor_call");
+ }
+ public static void ajc_afterReturning_constructor_call(Object o) {
+ System.out.println("afterReturning_constructor_call: " + o);
+ }
+
+ public static void ajc_afterThrowing_constructor_call() {
+ System.out.println("ajc_afterThrowing_constructor_call");
+ }
+ public static void ajc_afterThrowing_constructor_call(Object o) {
+ System.out.println("afterThrowing_constructor_call: " + o);
+ }
+
+ public static Object ajc_around_constructor_call(AroundClosure closure) throws Throwable {
+ Object ret = null;
+ for (int i=0; i<3; i++) {
+ System.out.println("enter: " + i);
+ ret = closure.run(new Object[] {});
+ }
+ return ret;
+ }
+ // ----
+
+ public static void ajc_before_constructor_execution() {
+ System.out.println("before_constructor_execution");
+ }
+ public static void ajc_before_constructor_execution(Object o) {
+ System.out.println("before_constructor_execution: " + o);
+ }
+
+ public static void ajc_after_constructor_execution() {
+ System.out.println("after_constructor_execution");
+ }
+ public static void ajc_after_constructor_execution(Object o) {
+ System.out.println("after_constructor_execution: " + o);
+ }
+
+ public static void ajc_afterReturning_constructor_execution() {
+ System.out.println("ajc_afterReturning_constructor_execution");
+ }
+ public static void ajc_afterReturning_constructor_execution(Object o) {
+ System.out.println("afterReturning_constructor_execution: " + o);
+ }
+
+ public static void ajc_afterThrowing_constructor_execution() {
+ System.out.println("ajc_afterThrowing_constructor_execution");
+ }
+ public static void ajc_afterThrowing_constructor_execution(Object o) {
+ System.out.println("afterThrowing_constructor_execution: " + o);
+ }
+
+ public static Object ajc_around_constructor_execution(AroundClosure closure) throws Throwable {
+ Object ret = null;
+ for (int i=0; i<3; i++) {
+ System.out.println("enter: " + i);
+ ret = closure.run(new Object[] {});
+ }
+ return ret;
+ }
+
+
+ // ---
+
+
+ public static void ajc_before_field_get() {
+ System.out.println("before_field_get");
+ }
+ public static void ajc_before_field_get(Object o) {
+ System.out.println("before_field_get: " + o);
+ }
+
+ public static void ajc_after_field_get() {
+ System.out.println("after_field_get");
+ }
+ public static void ajc_after_field_get(Object o) {
+ System.out.println("after_field_get: " + o);
+ }
+
+ public static void ajc_afterReturning_field_get() {
+ System.out.println("afterReturning_field_get");
+ }
+ public static void ajc_afterReturning_field_get(Object o) {
+ System.out.println("afterReturning_field_get: " + o);
+ }
+
+ public static void ajc_afterThrowing_field_get() {
+ System.out.println("afterThrowing_field_get");
+ }
+ public static void ajc_afterThrowing_field_get(Object o) {
+ System.out.println("afterThrowing_field_get: " + o);
+ }
+ public static void ajc_afterThrowing_field_get(Throwable t) {
+ System.out.println("afterThrowing_field_get: " + t);
+ }
+
+ public static Object ajc_around_field_get(AroundClosure closure) throws Throwable {
+ Object ret = closure.run(new Object[] {});
+ return ret;
+ }
+
+
+ // ---
+
+
+ public static void ajc_before_field_set() {
+ System.out.println("before_field_set");
+ }
+ public static void ajc_before_field_set(Object o) {
+ System.out.println("before_field_set: " + o);
+ }
+
+ public static void ajc_after_field_set() {
+ System.out.println("after_field_set");
+ }
+ public static void ajc_after_field_set(Object o) {
+ System.out.println("after_field_set: " + o);
+ }
+
+ public static void ajc_afterReturning_field_set() {
+ System.out.println("afterReturning_field_set");
+ }
+ public static void ajc_afterReturning_field_set(Object o) {
+ System.out.println("afterReturning_field_set: " + o);
+ }
+
+ public static void ajc_afterThrowing_field_set() {
+ System.out.println("afterThrowing_field_set");
+ }
+ public static void ajc_afterThrowing_field_set(Object o) {
+ System.out.println("afterThrowing_field_set: " + o);
+ }
+ public static void ajc_afterThrowing_field_set(Throwable t) {
+ System.out.println("afterThrowing_field_set: " + t);
+ }
+
+ public static Object ajc_around_field_set(AroundClosure closure) throws Throwable {
+ Object ret = closure.run(new Object[] {});
+ return ret;
+ }
+
+ // don't call this method for callee-side call join points
+ public static void ajc_before(JoinPoint.StaticPart tjp) {
+ System.out.println("before: " + tjp);
+ if (tjp.getSourceLocation() == null) {
+ throw new RuntimeException("didn't want null");
+ }
+ System.out.println(" loc: " + tjp.getSourceLocation());
+ }
+
+ public static void ajc_before(JoinPoint tjp) {
+ System.out.println("before: " + tjp + " this = " + tjp.getThis() +
+ " target = " + tjp.getTarget() +
+ " args = " + Arrays.asList(tjp.getArgs()));
+ }
+
+ // per object stuff
+
+ private static Map objects = new HashMap();
+
+ public static void ajc$perObjectBind(Object o) {
+ if (objects.containsKey(o)) return;
+ objects.put(o, new Aspect());
+ }
+
+ public static boolean hasAspect(Object o) {
+ return objects.containsKey(o);
+ }
+
+ public static Aspect aspectOf(Object o) {
+ return (Aspect) objects.get(o);
+ }
+
+
+ // per cflow stuff
+
+ public static void ajc$perCflowPush() {
+ ajc$perCflowStack.pushInstance(new Aspect());
+ }
+
+ public static boolean hasAspect() {
+ return ajc$perCflowStack.isValid();
+ }
+
+ public static Aspect aspectOf() {
+ return (Aspect) ajc$perCflowStack.peekInstance();
+ }
+
+ public static CFlowStack ajc$perCflowStack = new CFlowStack();
+
+ // non-static methods
+
+ public static Aspect ajc$perSingletonInstance = new Aspect();
+ public void ajc_before() {
+ System.out.println("before in: " + this);
+ }
+
+ public static CFlowStack ajc$cflowStack$0 = new CFlowStack();
+
+
+}
diff --git a/weaver/testsrc/BcweaverModuleTests.java b/weaver/testsrc/BcweaverModuleTests.java
new file mode 100644
index 000000000..4c4617338
--- /dev/null
+++ b/weaver/testsrc/BcweaverModuleTests.java
@@ -0,0 +1,30 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+// default package
+
+import junit.framework.*;
+import junit.framework.Test;
+
+public class BcweaverModuleTests extends TestCase {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(BcweaverModuleTests.class.getName());
+ suite.addTest(org.aspectj.weaver.bcel.BcelTests.suite());
+ suite.addTest(org.aspectj.weaver.BcweaverTests.suite());
+ suite.addTest(org.aspectj.weaver.patterns.PatternsTests.suite());
+ return suite;
+ }
+
+ public BcweaverModuleTests(String name) { super(name); }
+
+}
diff --git a/weaver/testsrc/DynamicHelloWorld.java b/weaver/testsrc/DynamicHelloWorld.java
new file mode 100644
index 000000000..f3818050e
--- /dev/null
+++ b/weaver/testsrc/DynamicHelloWorld.java
@@ -0,0 +1,24 @@
+import java.io.*;
+import java.util.*;
+
+/**
+ * @version 1.0
+ * @author
+ */
+public class DynamicHelloWorld implements Serializable {
+
+ public static void main(String[] args) {
+ try {
+ new DynamicHelloWorld().doit("hello", Collections.EMPTY_LIST);
+ } catch (UnsupportedOperationException t) {
+ System.out.println("expected and caught: " + t);
+ return;
+ }
+ throw new RuntimeException("should have caught exception");
+ }
+
+ String doit(String s, List l) {
+ l.add(s); // this will throw an exception
+ return l.toString();
+ }
+}
diff --git a/weaver/testsrc/FancyHelloWorld.java b/weaver/testsrc/FancyHelloWorld.java
new file mode 100644
index 000000000..96bd4a067
--- /dev/null
+++ b/weaver/testsrc/FancyHelloWorld.java
@@ -0,0 +1,24 @@
+import java.io.PrintStream;
+
+/**
+ * @version 1.0
+ * @author
+ */
+public abstract class FancyHelloWorld {
+ public static void main(String[] args) {
+ PrintStream out = System.out;
+ try {
+ out.println("bye");
+ } catch (Exception e) {
+ out.println(e);
+ } finally {
+ out.println("finally");
+ }
+ }
+
+ public static String getName() {
+ int x = 0;
+ x += "name".hashCode();
+ return "name" + x;
+ }
+}
diff --git a/weaver/testsrc/FieldyHelloWorld.java b/weaver/testsrc/FieldyHelloWorld.java
new file mode 100644
index 000000000..b5502abf8
--- /dev/null
+++ b/weaver/testsrc/FieldyHelloWorld.java
@@ -0,0 +1,10 @@
+public class FieldyHelloWorld {
+
+ public static String str = "Hello";
+
+ public static void main(String[] args) {
+ str += " World";
+
+ System.out.println(str);
+ }
+}
diff --git a/weaver/testsrc/HelloWorld.java b/weaver/testsrc/HelloWorld.java
new file mode 100644
index 000000000..b296ba704
--- /dev/null
+++ b/weaver/testsrc/HelloWorld.java
@@ -0,0 +1,12 @@
+/**
+ * @version 1.0
+ * @author
+ */
+public class HelloWorld {
+
+ public static void main(String[] args) {
+ System.out
+ .println("hello world");
+ //System.out.println("hello world");
+ }
+}
diff --git a/weaver/testsrc/MultiArgHelloWorld.java b/weaver/testsrc/MultiArgHelloWorld.java
new file mode 100644
index 000000000..9fccf0ec6
--- /dev/null
+++ b/weaver/testsrc/MultiArgHelloWorld.java
@@ -0,0 +1,12 @@
+
+
+public class MultiArgHelloWorld {
+
+ public static void main(String[] args) {
+ foo("Hello", "World");
+ }
+
+ static void foo(Object s, Object t) {
+ System.out.println(s + " " + t);
+ }
+}
diff --git a/weaver/testsrc/Test.java b/weaver/testsrc/Test.java
new file mode 100644
index 000000000..97f37d943
--- /dev/null
+++ b/weaver/testsrc/Test.java
@@ -0,0 +1,11 @@
+public class Test {
+ public static void main(String[] args) {
+ foo()
+ .
+ foo();
+ }
+ public static Test foo() {
+ new Exception().printStackTrace();
+ return new Test();
+ }
+}
diff --git a/weaver/testsrc/TestSwitchy.java b/weaver/testsrc/TestSwitchy.java
new file mode 100644
index 000000000..1f65a12d8
--- /dev/null
+++ b/weaver/testsrc/TestSwitchy.java
@@ -0,0 +1,31 @@
+/**
+ * @author hilsdale
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public abstract class TestSwitchy {
+
+
+ public int i = 3;
+
+ public static final int j = 4;
+
+
+ public static void main(String[] args) {
+ switch (args.length) {
+ case 0: System.err.println("hi");
+ case 1: System.err.println("bye"); break;
+ case 2: System.err.println("two");
+ default: System.err.println("ning");
+ }
+ System.err.println("done");
+ }
+
+
+ abstract int goo();
+
+ void nimbo() {}
+}
diff --git a/weaver/testsrc/fluffy/Aspect.java b/weaver/testsrc/fluffy/Aspect.java
new file mode 100644
index 000000000..7cb35bfa4
--- /dev/null
+++ b/weaver/testsrc/fluffy/Aspect.java
@@ -0,0 +1,31 @@
+package fluffy;
+import java.util.*;
+
+import org.aspectj.runtime.internal.AroundClosure;
+
+public class Aspect {
+
+ public static void ignoreMe() {}
+
+ public static void before_method_call() {
+ System.out.println("before");
+ }
+
+ public static void afterReturning_method_call() {
+ System.out.println("afterReturning");
+ }
+
+ public static void afterThrowing_method_execution(Throwable t) {
+ System.out.println("afterThrowing " + t);
+ t.printStackTrace();
+ }
+
+ public static Object aroundFun(AroundClosure c) {
+ System.out.println("around");
+ try {
+ return c.run(new Object[0]);
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+}
diff --git a/weaver/testsrc/fluffy/Base.java b/weaver/testsrc/fluffy/Base.java
new file mode 100644
index 000000000..9aa148d68
--- /dev/null
+++ b/weaver/testsrc/fluffy/Base.java
@@ -0,0 +1,15 @@
+package fluffy;
+
+public class Base {
+
+ public static void onlyBase() {}
+ public static void both() {}
+
+ public int onlyBase;
+ public int both;
+
+ public Base() {}
+ public Base(int i) {}
+
+ public void m() throws CloneNotSupportedException {}
+}
diff --git a/weaver/testsrc/fluffy/Derived.java b/weaver/testsrc/fluffy/Derived.java
new file mode 100644
index 000000000..6c38db40e
--- /dev/null
+++ b/weaver/testsrc/fluffy/Derived.java
@@ -0,0 +1,17 @@
+package fluffy;
+
+import java.io.IOException;
+
+public class Derived extends Base {
+
+ public static void onlyDerived() throws IOException, CloneNotSupportedException {}
+ public static void both() {}
+
+ public int onlyDerived;
+ public int both;
+
+ public Derived() {}
+
+ public void m() {}
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/AbstractWorldTestCase.java b/weaver/testsrc/org/aspectj/weaver/AbstractWorldTestCase.java
new file mode 100644
index 000000000..4ae04c77f
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/AbstractWorldTestCase.java
@@ -0,0 +1,179 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import junit.framework.TestCase;
+
+import org.aspectj.testing.util.TestUtil;
+
+/** This isn't a test case, it's extended by test cases, and includes tests that
+ * should be true in all worlds.
+ */
+
+public abstract class AbstractWorldTestCase extends TestCase {
+
+ public AbstractWorldTestCase(String name) {
+ super(name);
+ }
+
+ protected abstract World getWorld();
+
+ private final TypeX[] primitiveTypeXs =
+ TypeX.forSignatures(
+ new String[] {"B", "S", "C", "I", "J", "F", "D", "V"});
+
+ public void testPrimitiveTypes() {
+ ResolvedTypeX[] primitives = getWorld().resolve(primitiveTypeXs);
+ for(int i = 0, len = primitives.length; i < len; i++) {
+ ResolvedTypeX ty = primitives[i];
+ modifiersTest(ty, Modifier.PUBLIC | Modifier.FINAL);
+ fieldsTest(ty, ResolvedMember.NONE);
+ methodsTest(ty, ResolvedMember.NONE);
+ interfacesTest(ty, ResolvedTypeX.NONE);
+ superclassTest(ty, null);
+ pointcutsTest(ty, ResolvedMember.NONE);
+ isInterfaceTest(ty, false);
+ isClassTest(ty, false);
+ isAspectTest(ty, false);
+ for (int j = 0; j < len; j++) {
+ ResolvedTypeX ty1 = primitives[j];
+ if (ty.equals(ty1)) {
+ isCoerceableFromTest(ty, ty1, true);
+ } else if (ty == ResolvedTypeX.BOOLEAN || ty1 == ResolvedTypeX.BOOLEAN ||
+ ty == ResolvedTypeX.VOID || ty1 == ResolvedTypeX.VOID) {
+ isCoerceableFromTest(ty, ty1, false);
+ } else {
+ isCoerceableFromTest(ty, ty1, true);
+ }
+ }
+ isCoerceableFromTest(ty, TypeX.OBJECT, false);
+
+ primAssignTest("B", new String[] {});
+ primAssignTest("S", new String[] {"B"});
+ primAssignTest("C", new String[] {"B"});
+ primAssignTest("I", new String[] {"B", "S", "C"});
+ primAssignTest("J", new String[] {"B", "S", "C", "I"});
+ primAssignTest("F", new String[] {"B", "S", "C", "I", "J"});
+ primAssignTest("D", new String[] {"B", "S", "C", "I", "J", "F"});
+ primAssignTest("Z", new String[] {});
+ primAssignTest("V", new String[] {});
+
+ }
+ }
+ private void primAssignTest(String sig, String[] lowers) {
+ ResolvedTypeX[] primitives = getWorld().resolve(primitiveTypeXs);
+ ResolvedTypeX ty = getWorld().resolve(TypeX.forSignature(sig));
+ ResolvedTypeX[] lowerTyArray =
+ getWorld().resolve(TypeX.forSignatures(lowers));
+ List lowerTys = new ArrayList(Arrays.asList(lowerTyArray));
+ lowerTys.add(ty);
+ Set allLowerTys = new HashSet(lowerTys);
+ Set allUpperTys = new HashSet(Arrays.asList(primitives));
+ allUpperTys.removeAll(allLowerTys);
+
+ for (Iterator i = allLowerTys.iterator(); i.hasNext(); ) {
+ ResolvedTypeX other = (ResolvedTypeX) i.next();
+ isAssignableFromTest(ty, other, true);
+ }
+ for (Iterator i = allUpperTys.iterator(); i.hasNext(); ) {
+ ResolvedTypeX other = (ResolvedTypeX) i.next();
+ isAssignableFromTest(ty, other, false);
+ }
+ }
+
+ public void testPrimitiveArrays() {
+ ResolvedTypeX[] primitives = getWorld().resolve(primitiveTypeXs);
+ for(int i = 0, len = primitives.length; i < len; i++) {
+ ResolvedTypeX ty = primitives[i];
+ ResolvedTypeX aty = getWorld().resolve(TypeX.forSignature("[" + ty.getSignature()));
+ modifiersTest(aty, Modifier.PUBLIC | Modifier.FINAL);
+ fieldsTest(aty, ResolvedMember.NONE);
+ methodsTest(aty, ResolvedMember.NONE);
+ interfacesTest(aty, new ResolvedTypeX[] {
+ getWorld().resolve(TypeX.CLONEABLE),
+ getWorld().resolve(TypeX.SERIALIZABLE) });
+ superclassTest(aty, TypeX.OBJECT);
+
+ pointcutsTest(aty, ResolvedMember.NONE);
+ isInterfaceTest(aty, false);
+ isClassTest(aty, false);
+ isAspectTest(aty, false);
+ for (int j = 0; j < len; j++) {
+ ResolvedTypeX ty1 = primitives[j];
+ isCoerceableFromTest(aty, ty1, false);
+ ResolvedTypeX aty1 = getWorld().resolve(TypeX.forSignature("[" + ty1.getSignature()));
+ if (ty.equals(ty1)) {
+ isCoerceableFromTest(aty, aty1, true);
+ isAssignableFromTest(aty, aty1, true);
+ } else {
+ isCoerceableFromTest(aty, aty1, false);
+ isAssignableFromTest(aty, aty1, false);
+ }
+ }
+ }
+ }
+
+ // ---- tests for parts of ResolvedTypeX objects
+
+ protected void modifiersTest(ResolvedTypeX ty, int mods) {
+ assertEquals(ty + " modifiers:", Modifier.toString(mods), Modifier.toString(ty.getModifiers()));
+ }
+ protected void fieldsTest(ResolvedTypeX ty, Member[] x) {
+ TestUtil.assertSetEquals(ty + " fields:", x, ty.getDeclaredJavaFields());
+ }
+ protected void methodsTest(ResolvedTypeX ty, Member[] x) {
+ TestUtil.assertSetEquals(ty + " methods:", x, ty.getDeclaredJavaMethods());
+ }
+ protected void mungersTest(ResolvedTypeX ty, ShadowMunger[] x) {
+ TestUtil.assertSetEquals(ty + " mungers:", x, ty.getDeclaredShadowMungersArray());
+ }
+ protected void interfacesTest(ResolvedTypeX ty, ResolvedTypeX[] x) {
+ TestUtil.assertArrayEquals(ty + " interfaces:", x, ty.getDeclaredInterfaces());
+ }
+ protected void superclassTest(ResolvedTypeX ty, TypeX x) {
+ assertEquals(ty + " superclass:", x, ty.getSuperclass());
+ }
+ protected void pointcutsTest(ResolvedTypeX ty, Member[] x) {
+ TestUtil.assertSetEquals(ty + " pointcuts:", x, ty.getDeclaredPointcuts());
+ }
+ protected void isInterfaceTest(ResolvedTypeX ty, boolean x) {
+ assertEquals(ty + " is interface:", x, ty.isInterface());
+ }
+ protected void isAspectTest(ResolvedTypeX ty, boolean x) {
+ assertEquals(ty + " is aspect:", x, ty.isAspect());
+ }
+ protected void isClassTest(ResolvedTypeX ty, boolean x) {
+ assertEquals(ty + " is class:", x, ty.isClass());
+ }
+ protected void isCoerceableFromTest(TypeX ty0, TypeX ty1, boolean x) {
+ assertEquals(ty0 + " is coerceable from " + ty1, x, ty0.isCoerceableFrom(ty1, getWorld()));
+ assertEquals(ty1 + " is coerceable from " + ty0, x, ty1.isCoerceableFrom(ty0, getWorld()));
+ }
+ protected void isAssignableFromTest(TypeX ty0, TypeX ty1, boolean x) {
+ assertEquals(ty0 + " is assignable from " + ty1, x, ty0.isAssignableFrom(ty1, getWorld()));
+ }
+
+ // ---- tests for parts of ResolvedMethod objects
+
+ protected void modifiersTest(ResolvedMember m, int mods) {
+ assertEquals(m + " modifiers:", Modifier.toString(mods), Modifier.toString(m.getModifiers()));
+ }
+ protected void exceptionsTest(ResolvedMember m, TypeX[] exns) {
+ TestUtil.assertSetEquals(m + " exceptions:", exns, m.getExceptions());
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/BcweaverTests.java b/weaver/testsrc/org/aspectj/weaver/BcweaverTests.java
new file mode 100644
index 000000000..5f2419dd0
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/BcweaverTests.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import junit.framework.*;
+
+public class BcweaverTests extends TestCase {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(BcweaverTests.class.getName());
+ // abstract
+ //suite.addTestSuite(AbstractWorldTestCase.class);
+ //$JUnit-BEGIN$
+ suite.addTestSuite(MemberTestCase.class);
+ suite.addTestSuite(TypeXTestCase.class);
+ //$JUnit-END$
+ return suite;
+ }
+
+ public BcweaverTests(String name) { super(name); }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/MemberTestCase.java b/weaver/testsrc/org/aspectj/weaver/MemberTestCase.java
new file mode 100644
index 000000000..d3e2919b3
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/MemberTestCase.java
@@ -0,0 +1,175 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import junit.framework.TestCase;
+
+import org.aspectj.testing.util.TestUtil;
+
+/**
+ * This is a test case for all the portions of Member that don't require a world.
+ */
+public class MemberTestCase extends TestCase {
+
+ public MemberTestCase(String name) {
+ super(name);
+ }
+
+ public void testMethodConstruction() {
+ Member s = Member.methodFromString("void Foo.goo(int)");
+ Member t = Member.method(TypeX.forName("Foo"), 0, "goo", "(I)V");
+ Member u = Member.methodFromString("void Foo1.goo(int)");
+ Member v = Member.methodFromString("int Foo.goo(int)");
+
+ TestUtil.assertCommutativeEquals(s, s, true);
+ TestUtil.assertCommutativeEquals(t, t, true);
+ TestUtil.assertCommutativeEquals(u, u, true);
+ TestUtil.assertCommutativeEquals(v, v, true);
+ TestUtil.assertCommutativeEquals(s, t, true);
+ TestUtil.assertCommutativeEquals(s, u, false);
+ TestUtil.assertCommutativeEquals(s, v, false);
+ TestUtil.assertCommutativeEquals(t, u, false);
+ TestUtil.assertCommutativeEquals(t, v, false);
+ TestUtil.assertCommutativeEquals(u, v, false);
+
+ s = Member.fieldFromString("int Foo.goo");
+ t = Member.field("Foo", 0, "goo", "I");
+ u = Member.fieldFromString("int Foo.goo1");
+ v = Member.fieldFromString("long Foo.goo");
+
+ TestUtil.assertCommutativeEquals(s, s, true);
+ TestUtil.assertCommutativeEquals(t, t, true);
+ TestUtil.assertCommutativeEquals(u, u, true);
+ TestUtil.assertCommutativeEquals(v, v, true);
+ TestUtil.assertCommutativeEquals(s, t, true);
+ TestUtil.assertCommutativeEquals(s, u, false);
+ TestUtil.assertCommutativeEquals(s, v, false);
+ TestUtil.assertCommutativeEquals(t, u, false);
+ TestUtil.assertCommutativeEquals(t, v, false);
+ TestUtil.assertCommutativeEquals(u, v, false);
+ }
+
+
+ public void testMethodContents() {
+ Member m = Member.methodFromString("void Foo.goo(int)");
+ kindTest(m, Member.METHOD);
+ declaringTypeTest(m, "Foo");
+ nameTest(m, "goo");
+ parameterTypesTest(m, new TypeX[] { ResolvedTypeX.INT });
+ returnTypeTest(m, ResolvedTypeX.VOID);
+ isInterfaceTest(m, false);
+ isPrivateTest(m, false);
+ isConstructorTest(m, false);
+ isStaticTest(m, false);
+
+ m = Member.methodFromString("interface java.lang.Object java.util.Iterator.next()");
+ kindTest(m, Member.METHOD);
+ declaringTypeTest(m, "java.util.Iterator");
+ nameTest(m, "next");
+ parameterTypesTest(m, TypeX.NONE);
+ returnTypeTest(m, TypeX.OBJECT);
+ isInterfaceTest(m, true);
+ isPrivateTest(m, false);
+ isConstructorTest(m, false);
+ isStaticTest(m, false);
+
+ m = Member.methodFromString("void Foo.<init>(int, java.lang.Object)");
+ kindTest(m, Member.CONSTRUCTOR);
+ declaringTypeTest(m, "Foo");
+ nameTest(m, "<init>");
+ parameterTypesTest(m, new TypeX[] { ResolvedTypeX.INT, TypeX.OBJECT } );
+ returnTypeTest(m, ResolvedTypeX.VOID);
+ isInterfaceTest(m, false);
+ isPrivateTest(m, false);
+ isConstructorTest(m, true);
+ isStaticTest(m, false);
+
+ m = Member.methodFromString("private double Foo.sqrt(double)");
+ kindTest(m, Member.METHOD);
+ declaringTypeTest(m, "Foo");
+ nameTest(m, "sqrt");
+ parameterTypesTest(m, new TypeX[] { ResolvedTypeX.DOUBLE } );
+ returnTypeTest(m, ResolvedTypeX.DOUBLE);
+ isInterfaceTest(m, false);
+ isPrivateTest(m, true);
+ isConstructorTest(m, false);
+ isStaticTest(m, false);
+
+ m = Member.methodFromString("static int java.lang.Math.max(int, int)");
+ kindTest(m, Member.METHOD);
+ declaringTypeTest(m, "java.lang.Math");
+ nameTest(m, "max");
+ parameterTypesTest(m, new TypeX[] { ResolvedTypeX.INT, ResolvedTypeX.INT } );
+ returnTypeTest(m, ResolvedTypeX.INT);
+ isInterfaceTest(m, false);
+ isPrivateTest(m, false);
+ isConstructorTest(m, false);
+ isStaticTest(m, true);
+ }
+
+ public void testFieldContents() {
+ Member m = Member.fieldFromString("int Foo.goo");
+ kindTest(m, Member.FIELD);
+ declaringTypeTest(m, "Foo");
+ nameTest(m, "goo");
+ parameterTypesTest(m, TypeX.NONE);
+ returnTypeTest(m, ResolvedTypeX.INT);
+ isInterfaceTest(m, false);
+ isPrivateTest(m, false);
+ isConstructorTest(m, false);
+ isStaticTest(m, false);
+
+ m = Member.fieldFromString("static java.util.Iterator goo.Bar.i");
+ kindTest(m, Member.FIELD);
+ declaringTypeTest(m, "goo.Bar");
+ nameTest(m, "i");
+ parameterTypesTest(m, TypeX.NONE);
+ returnTypeTest(m, TypeX.forName("java.util.Iterator"));
+ isInterfaceTest(m, false);
+ isPrivateTest(m, false);
+ isConstructorTest(m, false);
+ isStaticTest(m, true);
+ }
+
+ private void isStaticTest(Member m, boolean b) {
+ assertEquals(m + " is static", b, m.isStatic());
+ }
+ private void isConstructorTest(Member m, boolean b) {
+ assertEquals(m + " is constructor", b, m.getKind() == Member.CONSTRUCTOR);
+ }
+ private void isPrivateTest(Member m, boolean b) {
+ assertEquals(m + " is private", b, m.isPrivate());
+ }
+ private void isInterfaceTest(Member m, boolean b) {
+ assertEquals(m + " is interface", b, m.isInterface());
+ }
+ private void returnTypeTest(Member m, TypeX returnType) {
+ assertEquals(m + " return type", returnType, m.getReturnType());
+ }
+ private void parameterTypesTest(Member m, TypeX[] paramTypes) {
+ TestUtil.assertArrayEquals(m + " parameters", paramTypes, m.getParameterTypes());
+ }
+ private void nameTest(Member m, String name) {
+ assertEquals(m + " name", name, m.getName());
+ }
+ private void declaringTypeTest(Member m, String declaringName) {
+ assertEquals(m + " declared in", TypeX.forName(declaringName), m.getDeclaringType());
+ }
+ private void kindTest(Member m, Member.Kind kind) {
+ assertEquals(m + " kind", kind, m.getKind());
+ }
+
+
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/TestShadow.java b/weaver/testsrc/org/aspectj/weaver/TestShadow.java
new file mode 100644
index 000000000..ae22c8000
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/TestShadow.java
@@ -0,0 +1,79 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import org.aspectj.weaver.ast.Var;
+import org.aspectj.bridge.SourceLocation;
+
+public class TestShadow extends Shadow {
+
+ private final World world;
+ private final TypeX thisType;
+
+ public TestShadow(Kind kind, Member signature, TypeX thisType, World world) {
+ super(kind, signature);
+ this.world = world;
+ this.thisType = thisType;
+ }
+
+ public World getIWorld() {
+ return world;
+ }
+
+ public boolean hasThis() { return true; }
+
+ public TypeX getThisType() {
+ return thisType;
+ }
+
+ /** this is subtly wrong. ha ha */
+ public TypeX getEnclosingType() {
+ return thisType;
+ }
+
+ public Var getThisVar() {
+ // we should thorw if we don't have a this
+ return new Var(getThisType().resolve(world));
+ }
+
+ public Var getTargetVar() {
+ if (! hasTarget()) throw new RuntimeException("bad");
+ return new Var(getTargetType().resolve(world));
+ }
+
+ public Var getArgVar(int i) {
+ return new Var(getArgType(i).resolve(world));
+ }
+
+ public Var getThisEnclosingJoinPointStaticPartVar() {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public Var getThisJoinPointStaticPartVar() {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public Var getThisJoinPointVar() {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public SourceLocation getSourceLocation() {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public Member getEnclosingCodeSignature() {
+ throw new RuntimeException("unimplemented");
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/TypeXTestCase.java b/weaver/testsrc/org/aspectj/weaver/TypeXTestCase.java
new file mode 100644
index 000000000..87b0317f8
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/TypeXTestCase.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import junit.framework.TestCase;
+
+import org.aspectj.testing.util.TestUtil;
+
+/**
+ * This is a test case for all the portions of TypeX that don't require a world.
+ */
+public class TypeXTestCase extends TestCase {
+
+ public TypeXTestCase(String name) {
+ super(name);
+ }
+
+ public void testUnresolvedTypes() {
+ // basic equality
+ String[] testNames =
+ new String[] {"int", "long", "int[]", "boolean[][]",
+ "java.lang.String", "java.lang.String[]", "void" };
+ String[] testSigs =
+ new String[] {"I", "J", "[I", "[[Z",
+ "Ljava/lang/String;", "[Ljava/lang/String;", "V" };
+
+ String[] componentNames =
+ new String[] {null, null, "int", "boolean[]",
+ null, "java.lang.String", null };
+
+ int[] sizes = new int[] {1, 2, 1, 1, 1, 1, 0};
+
+ boolean[] isPrimitive =
+ new boolean[] { true, true, false, false, false, false, true };
+
+ nameSignatureTest(testNames, testSigs);
+ arrayTest(TypeX.forNames(testNames), componentNames);
+ arrayTest(TypeX.forSignatures(testSigs), componentNames);
+
+ sizeTest(TypeX.forNames(testNames), sizes);
+ sizeTest(TypeX.forSignatures(testSigs), sizes);
+
+ isPrimitiveTest(TypeX.forSignatures(testSigs), isPrimitive);
+ }
+
+ public void testNameAndSigWithInners() {
+ TypeX t = TypeX.forName("java.util.Map$Entry");
+ assertEquals(t.getName(), "java.util.Map$Entry");
+ assertEquals(t.getSignature(), "Ljava/util/Map$Entry;");
+ assertEquals(t.getDeclaringType(), TypeX.forName("java.util.Map"));
+ assertNull(TypeX.forName("java.util.Map").getDeclaringType());
+ }
+
+ private void isPrimitiveTest(TypeX[] types, boolean[] isPrimitives) {
+ for (int i = 0, len = types.length; i < len; i++) {
+ TypeX type = types[i];
+ boolean b = isPrimitives[i];
+ assertEquals(type + " is primitive: ", b, type.isPrimitive());
+ }
+ }
+
+ private void sizeTest(TypeX[] types, int[] sizes) {
+ for (int i = 0, len = types.length; i < len; i++) {
+ TypeX type = types[i];
+ int size = sizes[i];
+ assertEquals("size of " + type + ": ", size, type.getSize());
+ }
+ }
+
+ private void arrayTest(TypeX[] types, String[] components) {
+ for (int i = 0, len = types.length; i < len; i++) {
+ TypeX type = types[i];
+ String component = components[i];
+ assertEquals(type + " is array: ", component != null, type.isArray());
+ if (component != null)
+ assertEquals(type + " componentType: ", component,
+ type.getComponentType().getName());
+ }
+ }
+
+ private void nameSignatureTest(String[] ns, String[] ss) {
+ for (int i = 0, len = ns.length; i < len; i++) {
+ String n = ns[i];
+ String s = ss[i];
+ TypeX tn = TypeX.forName(n);
+ TypeX ts = TypeX.forSignature(s);
+
+ assertEquals("forName(n).getName()", n,
+ tn.getName());
+ assertEquals("forSignature(s).getSignature()", s,
+ ts.getSignature());
+ assertEquals("forName(n).getSignature()", s,
+ tn.getSignature());
+ assertEquals("forSignature(n).getName()", n,
+ ts.getName());
+
+ TestUtil.assertCommutativeEquals(tn, tn, true);
+ TestUtil.assertCommutativeEquals(ts, ts, true);
+ TestUtil.assertCommutativeEquals(tn, ts, true);
+
+ for (int j = 0; j < len; j++) {
+ if (i == j) continue;
+ TypeX tn1 = TypeX.forName(ns[j]);
+ TypeX ts1 = TypeX.forSignature(ss[j]);
+ TestUtil.assertCommutativeEquals(tn, tn1, false);
+ TestUtil.assertCommutativeEquals(ts, tn1, false);
+ TestUtil.assertCommutativeEquals(tn, ts1, false);
+ TestUtil.assertCommutativeEquals(ts, ts1, false);
+ }
+ }
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/AfterReturningWeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/AfterReturningWeaveTestCase.java
new file mode 100644
index 000000000..a66fc0d40
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/AfterReturningWeaveTestCase.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.IOException;
+
+import org.aspectj.weaver.ShadowMunger;
+
+public class AfterReturningWeaveTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public AfterReturningWeaveTestCase(String name) {
+ super(name);
+ }
+
+ public void testAfterReturning() throws IOException {
+ weaveTest(
+ getStandardTargets(),
+ "AfterReturning",
+ makeAdviceAll("afterReturning"));
+ }
+
+ public void testAfterReturningParam() throws IOException {
+ weaveTest(
+ getStandardTargets(),
+ "AfterReturningParam",
+ makeAdviceField("afterReturning", "java.lang.Object"));
+ }
+ public void testAfterReturningCheckcastParam() throws IOException {
+ weaveTest(
+ getStandardTargets(),
+ "AfterReturningCheckcastParam",
+ makeAdviceField("afterReturning", "java.rmi.server.LogStream"));
+ }
+
+ public void testAfterReturningConversionParam() throws IOException {
+ String mungerString =
+ "afterReturning(): call(int *.*(..)) -> "
+ + "static void Aspect.ajc_afterReturning_field_get(java.lang.Object)";
+ ShadowMunger cm = makeConcreteAdvice(mungerString, 1);
+
+ weaveTest("FancyHelloWorld", "AfterReturningConversionParam", cm);
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/AfterThrowingWeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/AfterThrowingWeaveTestCase.java
new file mode 100644
index 000000000..0202fdb69
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/AfterThrowingWeaveTestCase.java
@@ -0,0 +1,43 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.IOException;
+
+import org.aspectj.weaver.*;
+
+public class AfterThrowingWeaveTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public AfterThrowingWeaveTestCase(String name) {
+ super(name);
+ }
+
+ public void testAfterThrowing() throws IOException {
+ weaveTest(getStandardTargets(), "AfterThrowing", makeAdviceAll("afterThrowing"));
+ }
+ public void testAfterThrowingParam() throws IOException {
+ BcelWorld world = new BcelWorld();
+
+ ShadowMunger myMunger =
+ world.shadowMunger("afterThrowing(): get(* *.out) -> static void Aspect.ajc_afterThrowing_field_get(java.lang.Throwable)",
+ Advice.ExtraArgument);
+ ShadowMunger cm = myMunger.concretize(ResolvedTypeX.MISSING, world, null);
+
+ weaveTest(getStandardTargets(), "AfterThrowingParam", cm);
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/AfterWeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/AfterWeaveTestCase.java
new file mode 100644
index 000000000..ef91d979f
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/AfterWeaveTestCase.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.util.*;
+import java.io.*;
+
+import junit.framework.TestResult;
+
+public class AfterWeaveTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public AfterWeaveTestCase(String name) {
+ super(name);
+ }
+
+
+ public void testAfter() throws IOException {
+ weaveTest(getStandardTargets(), "After", makeAdviceAll("after"));
+ }
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/ArgsWeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/ArgsWeaveTestCase.java
new file mode 100644
index 000000000..e0761bf0d
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/ArgsWeaveTestCase.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.util.*;
+import java.io.*;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.weaver.*;
+
+/**.
+ */
+public class ArgsWeaveTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public ArgsWeaveTestCase(String name) {
+ super(name);
+ }
+
+
+ public void testAfterReturningArgs() throws IOException {
+ weaveTest("HelloWorld", "ArgsAfterReturningHelloWorld", makeArgsMunger("afterReturning"));
+ }
+
+
+ public void testFancyAfterReturningArgs() throws IOException {
+ weaveTest("FancyHelloWorld", "ArgsAfterReturningFancyHelloWorld", makeArgsMunger("afterReturning"));
+ }
+
+ public void testThrowing() throws IOException {
+ weaveTest("HelloWorld", "ArgsAfterThrowingHelloWorld", makeArgsMunger("afterThrowing"));
+ }
+
+ public void testLots() throws IOException {
+ List l = new ArrayList();
+
+
+ BcelAdvice p1 =
+ makeArgsMunger("before");
+
+ BcelAdvice p2 =
+ makeArgsMunger("afterThrowing");
+
+ BcelAdvice p3 =
+ makeArgsMunger("afterReturning");
+
+ l.add(p1);
+ l.add(p2);
+ l.add(p3);
+
+
+ weaveTest("HelloWorld", "ArgsBeforeAfterHelloWorld", addLexicalOrder(l));
+ }
+
+ private InstructionList getArgsAdviceTag(BcelShadow shadow, String where) {
+ String methodName =
+ "ajc_" + where + "_" + shadow.getKind().toLegalJavaIdentifier();
+ InstructionFactory fact = shadow.getFactory();
+ InstructionList il = new InstructionList();
+
+
+ il.append(
+ BcelRenderer.renderExpr(
+ fact,
+ new BcelWorld(),
+ shadow.getArgVar(0),
+ Type.OBJECT));
+
+ il.append(
+ fact.createInvoke(
+ "Aspect",
+ methodName,
+ Type.VOID,
+ new Type[] { Type.OBJECT },
+ Constants.INVOKESTATIC));
+
+ return il;
+ }
+
+ private BcelAdvice makeArgsMunger(final String kindx) {
+ return new BcelAdvice(AdviceKind.stringToKind(kindx), makePointcutNoZeroArg(),
+ Member.method(TypeX.forName("Aspect"), 0, "foo", "()V"), 0, -1, -1, null,
+ world.resolve(TypeX.forName("Aspect"))) {
+ public void specializeOn(Shadow shadow) {
+ super.specializeOn(shadow);
+ shadow.getArgVar(0);
+ }
+ public InstructionList getAdviceInstructions(BcelShadow shadow, BcelVar extraVar, InstructionHandle fk) {
+ return getArgsAdviceTag(shadow, kindx);
+ }
+ };
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/AroundArgsWeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/AroundArgsWeaveTestCase.java
new file mode 100644
index 000000000..47b80d7ef
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/AroundArgsWeaveTestCase.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.IOException;
+
+import org.aspectj.weaver.ShadowMunger;
+
+public class AroundArgsWeaveTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public AroundArgsWeaveTestCase(String name) {
+ super(name);
+ }
+
+ public void testWeave() throws IOException
+ {
+ String label = "AroundArgs";
+ ShadowMunger p =
+ makeConcreteAdvice(
+ "around(list) : "
+ + "(call(public * add(..)) && target(list)) -> "
+ + "static boolean Aspect.ajc_around0"
+ + "(java.util.ArrayList, org.aspectj.runtime.internal.AroundClosure)");
+ weaveTest(new String[] {"DynamicHelloWorld"}, label, p);
+
+ }
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/AroundWeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/AroundWeaveTestCase.java
new file mode 100644
index 000000000..28d0e1a7a
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/AroundWeaveTestCase.java
@@ -0,0 +1,93 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import org.aspectj.weaver.*;
+
+public class AroundWeaveTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public AroundWeaveTestCase(String name) {
+ super(name);
+ }
+
+ public void testAround() throws IOException {
+ aroundTest("Around", true);
+ }
+
+ public void testAroundAll() throws IOException {
+ aroundTest("AroundAll", false);
+ }
+
+ public void testAroundAndOthers() throws IOException {
+ aroundTestAndOthers("AroundAndOthers", true);
+ }
+
+ public void testAroundAllAndOthers() throws IOException {
+ aroundTestAndOthers("AroundAllAndOthers", false);
+ }
+
+
+ private BcelAdvice makeAroundMunger(final boolean matchOnlyPrintln) {
+ BcelWorld world = new BcelWorld();
+ final Member sig =
+ Member.method(
+ TypeX.forName("Aspect"),
+ Modifier.STATIC,
+ "ajc_around",
+ "(Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;");
+
+ return new BcelAdvice(
+ AdviceKind.stringToKind("around"),
+ matchOnlyPrintln ? makePointcutPrintln() : makePointcutAll(),
+ sig, 0, -1, -1, null, TypeX.forName("Aspect").resolve(world))
+ {
+ public void specializeOn(Shadow s) {
+ super.specializeOn(s);
+ ((BcelShadow) s).initializeForAroundClosure();
+ }
+ };
+ }
+
+ private void aroundTest(String outName, final boolean matchOnlyPrintln) throws IOException {
+ weaveTest(getStandardTargets(), outName, makeAroundMunger(matchOnlyPrintln));
+ }
+
+ private void aroundTestAndOthers(String outName, final boolean matchOnlyPrintln)
+ throws IOException
+ {
+
+ List l = new ArrayList();
+
+ // the afterReturning was taken out to avoid circular advice dependency
+
+ l.addAll(makeAdviceAll("before", matchOnlyPrintln));
+ //l.addAll(makeAdviceAll("afterReturning", matchOnlyPrintln));
+
+ l.add(makeAroundMunger(matchOnlyPrintln));
+
+ l.addAll(makeAdviceAll("before", matchOnlyPrintln));
+ //l.addAll(makeAdviceAll("afterReturning", matchOnlyPrintln));
+
+ l.add(makeAroundMunger(matchOnlyPrintln));
+ weaveTest(getStandardTargets(), outName, addLexicalOrder(l));
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/BcelTests.java b/weaver/testsrc/org/aspectj/weaver/bcel/BcelTests.java
new file mode 100644
index 000000000..88b252b6a
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/BcelTests.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import junit.framework.*;
+
+public class BcelTests extends TestCase {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(BcelTests.class.getName());
+ // abstract
+ //suite.addTestSuite(WeaveTestCase.class);
+ //$JUnit-BEGIN$
+ suite.addTestSuite(AfterReturningWeaveTestCase.class);
+ suite.addTestSuite(AfterThrowingWeaveTestCase.class);
+ suite.addTestSuite(AfterWeaveTestCase.class);
+ suite.addTestSuite(ArgsWeaveTestCase.class);
+ suite.addTestSuite(AroundArgsWeaveTestCase.class);
+ suite.addTestSuite(AroundWeaveTestCase.class);
+ suite.addTestSuite(BeforeWeaveTestCase.class);
+ suite.addTestSuite(CheckerTestCase.class);
+ suite.addTestSuite(FieldSetTestCase.class);
+ suite.addTestSuite(HierarchyDependsTestCase.class);
+ suite.addTestSuite(IdWeaveTestCase.class);
+ suite.addTestSuite(MoveInstructionsWeaveTestCase.class);
+ suite.addTestSuite(NonstaticWeaveTestCase.class);
+ suite.addTestSuite(PatternWeaveTestCase.class);
+ suite.addTestSuite(PointcutResidueTestCase.class);
+ suite.addTestSuite(TraceJarWeaveTestCase.class);
+ suite.addTestSuite(TjpWeaveTestCase.class);
+ suite.addTestSuite(UtilityTestCase.class);
+ suite.addTestSuite(WeaveOrderTestCase.class);
+ suite.addTestSuite(WorldTestCase.class);
+ suite.addTestSuite(ZipTestCase.class);
+ //$JUnit-END$
+ return suite;
+ }
+
+ public BcelTests(String name) { super(name); }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/BeforeWeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/BeforeWeaveTestCase.java
new file mode 100644
index 000000000..04a285096
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/BeforeWeaveTestCase.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.IOException;
+
+public class BeforeWeaveTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public BeforeWeaveTestCase(String name) {
+ super(name);
+ }
+
+
+ public void testBefore() throws IOException {
+ weaveTest(getStandardTargets(), "Before", makeAdviceAll("before"));
+ }
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/CheckerTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/CheckerTestCase.java
new file mode 100644
index 000000000..f0a2747e8
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/CheckerTestCase.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.IOException;
+
+import org.aspectj.weaver.Checker;
+import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
+import org.aspectj.bridge.*;
+import org.aspectj.bridge.MessageHandler;
+
+public class CheckerTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public CheckerTestCase(String name) {
+ super(name);
+ }
+
+
+ public void testStaticTjp() throws IOException {
+ Checker checker = new Checker(
+ new DeclareErrorOrWarning(true, makePointcutPrintln(), "hey, we found a println"));
+
+ MessageHandler handler = new MessageHandler();
+ world.setMessageHandler(handler);
+
+ weaveTest("HelloWorld", "IdHelloWorld", checker);
+ assertEquals(1, handler.numMessages(IMessage.ERROR, false));
+
+ handler = new MessageHandler();
+ world.setMessageHandler(handler);
+ weaveTest("FancyHelloWorld", "IdFancyHelloWorld", checker);
+ assertEquals(3, handler.numMessages(IMessage.ERROR, false));
+ }
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/FieldSetTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/FieldSetTestCase.java
new file mode 100644
index 000000000..15d1fa680
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/FieldSetTestCase.java
@@ -0,0 +1,35 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.IOException;
+import java.util.Collections;
+
+public class FieldSetTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public FieldSetTestCase(String name) {
+ super(name);
+ }
+
+ public void testBefore() throws IOException {
+ weaveTest(
+ "FieldyHelloWorld",
+ "FieldSet",
+ makeAdviceAll("before")
+ );
+ }
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/HierarchyDependsTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/HierarchyDependsTestCase.java
new file mode 100644
index 000000000..939a62748
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/HierarchyDependsTestCase.java
@@ -0,0 +1,67 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import junit.framework.TestCase;
+
+import org.apache.bcel.classfile.JavaClass;
+import org.aspectj.weaver.TypeX;
+import org.aspectj.weaver.patterns.*;
+
+
+public class HierarchyDependsTestCase extends TestCase {
+
+ /**
+ * Constructor for ParserTestCase.
+ * @param arg0
+ */
+ public HierarchyDependsTestCase(String arg0) {
+ super(arg0);
+ }
+
+
+ public void testHierarchyDepends() {
+ BcelWorld world = new BcelWorld();
+ TypePatternQuestions questions = new TypePatternQuestions();
+ BcelObjectType runnableType = (BcelObjectType)world.resolve("java.lang.Runnable");
+ BcelObjectType numberType = (BcelObjectType)world.resolve("java.lang.Number");
+ BcelObjectType integerType = (BcelObjectType)world.resolve("java.lang.Integer");
+ BcelObjectType stringType = (BcelObjectType)world.resolve("java.lang.String");
+
+
+ TypePattern numberPattern = new ExactTypePattern(numberType, false);
+ questions.askQuestion(numberPattern, integerType, TypePattern.STATIC);
+ questions.askQuestion(numberPattern, integerType, TypePattern.DYNAMIC);
+ assertNull(questions.anyChanges());
+
+ JavaClass saveClass = integerType.getJavaClass();
+ integerType.replaceJavaClass(stringType.getJavaClass());
+ assertNotNull(questions.anyChanges());
+
+ integerType.replaceJavaClass(saveClass);
+ assertNull(questions.anyChanges());
+
+ TypePattern runnablePattern = new ExactTypePattern(runnableType, false);
+ questions.askQuestion(runnablePattern, stringType, TypePattern.DYNAMIC);
+ assertNull(questions.toString(), questions.anyChanges());
+
+ saveClass = stringType.getJavaClass();
+ stringType.replaceJavaClass(numberType.getJavaClass());
+ assertNotNull(questions.toString(), questions.anyChanges());
+
+ stringType.replaceJavaClass(saveClass);
+ assertNull(questions.toString(), questions.anyChanges());
+ }
+}
+
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/IdWeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/IdWeaveTestCase.java
new file mode 100644
index 000000000..031bf1c8d
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/IdWeaveTestCase.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.IOException;
+import java.util.*;
+
+import org.apache.bcel.util.ClassPath;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.patterns.Pointcut;
+
+public class IdWeaveTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public IdWeaveTestCase(String name) {
+ super(name);
+ }
+
+ public void testFancyId() throws IOException {
+ final List l = new ArrayList();
+ Pointcut pointcut2 = makePointcutAll();
+ BcelAdvice p =
+ new BcelAdvice(null, pointcut2, null, 0, -1, -1, null, null) {
+ public boolean match(Shadow shadow, World world) {
+ if (super.match(shadow, world)) {
+ l.add(shadow);
+ }
+ return false;
+ }
+ };
+ weaveTest(new String[] {"FancyHelloWorld"}, "Id", p);
+
+ checkShadowSet(l, new String[] {
+ "method-call(void java.io.PrintStream.println(java.lang.Object))",
+ "method-call(void java.io.PrintStream.println(java.lang.String))",
+ "method-call(java.lang.StringBuffer java.lang.StringBuffer.append(int))",
+ "method-call(java.lang.String java.lang.StringBuffer.toString())",
+ "method-execution(java.lang.String FancyHelloWorld.getName())",
+ "field-get(java.io.PrintStream java.lang.System.out)",
+ "method-call(void java.io.PrintStream.println(java.lang.String))",
+ "method-execution(void FancyHelloWorld.main(java.lang.String[]))",
+ "method-call(int java.lang.String.hashCode())",
+ "constructor-execution(void FancyHelloWorld.<init>())",
+ "constructor-call(void java.lang.StringBuffer.<init>(java.lang.String))"
+ });
+ }
+
+ public void testId() throws IOException {
+ final List l = new ArrayList();
+ BcelAdvice p = new BcelAdvice(null, makePointcutAll(), null, 0, -1, -1, null, null) {
+ public void implementOn(Shadow shadow) {
+ l.add(shadow);
+ }
+ };
+ weaveTest(new String[] {"HelloWorld"}, "Id", p);
+
+ checkShadowSet(l, new String[] {
+ "method-execution(void HelloWorld.main(java.lang.String[]))",
+ "method-call(void java.io.PrintStream.println(java.lang.String))",
+ "field-get(java.io.PrintStream java.lang.System.out)",
+ "constructor-execution(void HelloWorld.<init>())",
+ });
+ }
+
+ // this test requires that Trace has been unzipped and placed in the correct place
+ public void testTraceId() throws IOException {
+ String saveClassDir = classDir;
+ try {
+ classDir = "testdata/dummyAspect.jar";
+
+
+
+ final List l = new ArrayList();
+ BcelAdvice p = new BcelAdvice(null, makePointcutAll(), null, 0, -1, -1, null, null) {
+ public void implementOn(Shadow shadow) {
+ l.add(shadow);
+ }
+ };
+ boolean tempRunTests = runTests;
+ runTests = false;
+ weaveTest(new String[] {"DummyAspect"}, "Id", p);
+ runTests = tempRunTests;
+
+ checkShadowSet(l, new String[] {
+ "constructor-execution(void DummyAspect.<init>())",
+ // XXX waiting on parser stuff
+ //"advice-execution(void DummyAspect.ajc_before_1(java.lang.Object))",
+ });
+ } finally {
+ classDir = saveClassDir;
+ }
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/MegaZipTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/MegaZipTestCase.java
new file mode 100644
index 000000000..72ad0d0a4
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/MegaZipTestCase.java
@@ -0,0 +1,111 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import org.aspectj.weaver.*;
+
+public class MegaZipTestCase extends WeaveTestCase {
+
+ public MegaZipTestCase(String arg0) {
+ super(arg0);
+ }
+
+
+ private BcelAdvice makeAroundMunger(final boolean matchOnlyPrintln) {
+ BcelWorld world = new BcelWorld();
+ final Member sig =
+ Member.method(
+ TypeX.forName("fluffy.Aspect"),
+ Modifier.STATIC,
+ "aroundFun",
+ "(Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;");
+
+ return new BcelAdvice(
+ AdviceKind.stringToKind("around"),
+ matchOnlyPrintln ? makePointcutPrintln() : makePointcutAll(),
+ sig, 0, -1, -1, null, null)
+ {
+ public void specializeOn(Shadow s) {
+ super.specializeOn(s);
+ ((BcelShadow) s).initializeForAroundClosure();
+ }
+ };
+ }
+
+ public List getShadowMungers() {
+ List ret = new ArrayList();
+ ret.add(
+ makeConcreteAdvice(
+ "before"
+ + "(): call(* *.println(..)) -> static void fluffy.Aspect.before_method_call()"));
+ ret.add(
+ makeConcreteAdvice(
+ "afterReturning"
+ + "(): call(* *.println(..)) -> static void fluffy.Aspect.afterReturning_method_call()"));
+
+ ret.add(
+ makeConcreteAdvice(
+ "before"
+ + "(): execution(* *.*(..)) -> static void fluffy.Aspect.ignoreMe()"));
+
+ ret.add(
+ makeConcreteAdvice(
+ "afterReturning"
+ + "(): execution(* *.*(..)) -> static void fluffy.Aspect.ignoreMe()"));
+
+ ret.add(
+ makeConcreteAdvice(
+ "afterThrowing"
+ + "(): execution(* *.*(..)) -> static void fluffy.Aspect.afterThrowing_method_execution(java.lang.Throwable)",
+ 1));
+ ret.add(
+ makeConcreteAdvice(
+ "after"
+ + "(): execution(* *.*(..)) -> static void fluffy.Aspect.ignoreMe()"));
+
+
+ ret.add(makeAroundMunger(true));
+ return ret;
+ }
+
+
+ public void zipTest(String fileName) throws IOException {
+ long startTime = System.currentTimeMillis();
+ File inFile = new File("testdata", fileName);
+ File outFile = new File("out", fileName);
+ outFile.delete();
+
+ world = new BcelWorld("c:/apps/java-1.3.1_04/lib/tools.jar");
+ BcelWeaver weaver1 = new BcelWeaver(world);
+
+
+ ZipFileWeaver weaver = new ZipFileWeaver(inFile);
+
+ weaver1.setShadowMungers(getShadowMungers());
+
+ weaver.weave(weaver1, outFile);
+ assertTrue(outFile.lastModified() > startTime);
+ }
+
+ // this is something we test every now and again.
+ public void testBig() throws IOException {
+ System.out.println("could take 80 seconds...");
+ zipTest("aspectjtools.jar");
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/MoveInstructionsWeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/MoveInstructionsWeaveTestCase.java
new file mode 100644
index 000000000..3c964c4ae
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/MoveInstructionsWeaveTestCase.java
@@ -0,0 +1,73 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.util.*;
+import java.io.*;
+
+import junit.framework.TestResult;
+
+import org.apache.bcel.generic.*;
+import org.apache.bcel.generic.InstructionList;
+import org.aspectj.weaver.*;
+
+public class MoveInstructionsWeaveTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public MoveInstructionsWeaveTestCase(String name) {
+ super(name);
+ }
+ public void testHello() throws IOException {
+ BcelAdvice p = new BcelAdvice(null, makePointcutAll(), null, 0, -1, -1, null, null) {
+ public void specializeOn(Shadow s) {
+ super.specializeOn(s);
+ ((BcelShadow) s).initializeForAroundClosure();
+ }
+ public void implementOn(Shadow s) {
+ BcelShadow shadow = (BcelShadow) s;
+ LazyMethodGen newMethod = shadow.extractMethod(shadow.getSignature().getExtractableName() + "_extracted");
+ shadow.getRange().append(shadow.makeCallToCallback(newMethod));
+
+ if (! shadow.isFallsThrough()) {
+ shadow.getRange().append(shadow.getFactory().createReturn(newMethod.getReturnType()));
+ }
+ }
+ };
+
+ weaveTest("HelloWorld", "ExtractedHelloWorld", p);
+ }
+
+ static int counter = 0;
+ public void testFancyHello() throws IOException {
+ BcelAdvice p = new BcelAdvice(null, makePointcutAll(), null, 0, -1, -1, null, null) {
+ public void specializeOn(Shadow s) {
+ super.specializeOn(s);
+ ((BcelShadow) s).initializeForAroundClosure();
+ }
+ public void implementOn(Shadow s) {
+ BcelShadow shadow = (BcelShadow) s;
+ LazyMethodGen newMethod = shadow.extractMethod(shadow.getSignature().getExtractableName() + "_extracted" + counter++);
+ shadow.getRange().append(shadow.makeCallToCallback(newMethod));
+
+ if (! shadow.isFallsThrough()) {
+ shadow.getRange().append(shadow.getFactory().createReturn(newMethod.getReturnType()));
+ }
+ }
+ };
+
+ weaveTest("FancyHelloWorld", "ExtractedFancyHelloWorld", p);
+ }
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/NonstaticWeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/NonstaticWeaveTestCase.java
new file mode 100644
index 000000000..75247d3f2
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/NonstaticWeaveTestCase.java
@@ -0,0 +1,86 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.List;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ShadowMunger;
+import org.aspectj.weaver.patterns.*;
+
+public class NonstaticWeaveTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public NonstaticWeaveTestCase(String name) {
+ super(name);
+ }
+
+
+ public void testBefore() throws IOException {
+ String s = "before(): get(* *.*) -> void Aspect.ajc_before()";
+ PerClause per = new PerSingleton();
+ per = per.concretize(world.resolve("Aspect"));
+
+ ShadowMunger myMunger = this.makeConcreteAdvice(s, 0, per);
+
+ weaveTest(getStandardTargets(), "NonStaticBefore", myMunger);
+ }
+
+ public void testBeforeCflow() throws IOException {
+ String s = "before(): get(* *.*) -> void Aspect.ajc_before()";
+ PerClause per = new PatternParser("percflow(execution(void main(..)))").maybeParsePerClause();
+ per.resolve(new TestScope(new String[0], new String[0], world));
+
+ ResolvedTypeX onAspect = world.resolve("Aspect");
+ CrosscuttingMembers xcut = new CrosscuttingMembers(onAspect);
+ onAspect.crosscuttingMembers = xcut;
+
+ per = per.concretize(onAspect);
+
+ ShadowMunger myMunger = this.makeConcreteAdvice(s, 0, per);
+
+ xcut.addConcreteShadowMunger(myMunger);
+
+
+ weaveTest(getStandardTargets(), "CflowNonStaticBefore", xcut.getShadowMungers());
+ }
+
+ public void testBeforePerThis() throws IOException {
+ String s = "before(): call(* println(..)) -> void Aspect.ajc_before()";
+ PerClause per = new PatternParser("pertarget(call(* println(..)))").maybeParsePerClause();
+ per.resolve(new TestScope(new String[0], new String[0], world));
+
+ ResolvedTypeX onAspect = world.resolve("Aspect");
+ CrosscuttingMembers xcut = new CrosscuttingMembers(onAspect);
+ onAspect.crosscuttingMembers = xcut;
+ per = per.concretize(onAspect);
+
+ ShadowMunger myMunger = this.makeConcreteAdvice(s, 0, per);
+ xcut.addConcreteShadowMunger(myMunger);
+
+// List mungers = new ArrayList();
+// mungers.add(myMunger);
+// mungers.addAll(onAspect.getExtraConcreteShadowMungers());
+
+
+ weaveTest(getStandardTargets(), "PerThisNonStaticBefore", xcut.getShadowMungers());
+ }
+
+
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/PatternWeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/PatternWeaveTestCase.java
new file mode 100644
index 000000000..22c0a2011
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/PatternWeaveTestCase.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.*;
+import java.util.*;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.patterns.*;
+
+public class PatternWeaveTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public PatternWeaveTestCase(String name) {
+ super(name);
+ }
+
+ String[] none = new String[0];
+
+
+ public void testPublic() throws IOException {
+ String[] publicHello = new String[] {
+ "method-execution(void HelloWorld.main(java.lang.String[]))",
+ };
+ String[] publicFancyHello = new String[] {
+ "method-execution(void FancyHelloWorld.main(java.lang.String[]))",
+ "method-execution(java.lang.String FancyHelloWorld.getName())",
+ };
+ checkPointcut("execution(public * *(..))", publicHello, publicFancyHello);
+ }
+
+ public void testPrintln() throws IOException {
+ String[] callPrintlnHello = new String[] {
+ "method-call(void java.io.PrintStream.println(java.lang.String))",
+ };
+ String[] callPrintlnFancyHello = new String[] {
+ "method-call(void java.io.PrintStream.println(java.lang.String))",
+ "method-call(void java.io.PrintStream.println(java.lang.String))",
+ "method-call(void java.io.PrintStream.println(java.lang.Object))",
+ };
+ checkPointcut("call(* println(*))", callPrintlnHello, callPrintlnFancyHello);
+ }
+
+ public void testMumble() throws IOException {
+ checkPointcut("call(* mumble(*))", none, none);
+ }
+
+ public void testFooBar() throws IOException {
+ checkPointcut("call(FooBar *(..))", none, none);
+ }
+
+ public void testGetOut() throws IOException {
+ String[] getOutHello = new String[] {
+ "field-get(java.io.PrintStream java.lang.System.out)",
+ };
+
+ checkPointcut("get(* java.lang.System.out)", getOutHello, getOutHello);
+ }
+
+ private Pointcut makePointcut(String s) {
+ return new PatternParser(s).parsePointcut();
+ }
+
+ private void checkPointcut(String pointcutSource, String[] expectedHelloShadows,
+ String[] expectedFancyShadows) throws IOException
+ {
+ Pointcut sp = Pointcut.fromString(pointcutSource);
+ Pointcut rp = sp.resolve(new SimpleScope(world, FormalBinding.NONE));
+ Pointcut cp = rp.concretize(ResolvedTypeX.MISSING, 0);
+
+ final List l = new ArrayList();
+ BcelAdvice p = new BcelAdvice(null, cp, null, 0, -1, -1, null, null) {
+ public void implementOn(Shadow shadow) {
+ l.add(shadow);
+ }
+ };
+ weaveTest(new String[] {"HelloWorld"}, "PatternWeave", p);
+
+ checkShadowSet(l, expectedHelloShadows);
+
+
+ l.clear();
+ weaveTest(new String[] {"FancyHelloWorld"}, "PatternWeave", p);
+
+ checkShadowSet(l, expectedFancyShadows);
+
+ checkSerialize(rp);
+ }
+
+ public void checkSerialize(Pointcut p) throws IOException {
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ DataInputStream in = new DataInputStream(bi);
+ Pointcut newP = Pointcut.read(in, null);
+
+ assertEquals("write/read", p, newP);
+ }
+
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/PointcutResidueTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/PointcutResidueTestCase.java
new file mode 100644
index 000000000..7dafd2f9b
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/PointcutResidueTestCase.java
@@ -0,0 +1,236 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.patterns.*;
+import org.aspectj.weaver.patterns.SimpleScope;
+
+public class PointcutResidueTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+ public PointcutResidueTestCase(String name) {
+ super(name);
+ }
+
+ String[] none = new String[0];
+
+
+ // -----
+
+
+
+
+
+ // ----
+
+
+
+ public void testArgResidue1() throws IOException {
+ checkMultiArgWeave(
+ "StringResidue1",
+ "call(* *(java.lang.Object, java.lang.Object)) && args(java.lang.String, java.lang.String)");
+ }
+
+ public void testArgResidue2() throws IOException {
+ checkMultiArgWeave(
+ "StringResidue2",
+ "call(* *(java.lang.Object, java.lang.Object)) && args(.., java.lang.String)");
+ }
+ public void testArgResidue3() throws IOException {
+ checkMultiArgWeave(
+ "StringResidue3",
+ "call(* *(java.lang.Object, java.lang.Object)) && args(java.lang.String, ..)");
+ }
+
+ // BETAX this is a beta feature.
+// public void testArgResidue4() throws IOException {
+// checkMultiArgWeave(
+// "StringResidue4",
+// "call(* *(java.lang.Object, java.lang.Object)) && args(.., java.lang.String, ..)");
+// }
+
+ public void testMultiArgState() throws IOException {
+ checkWeave(
+ "StateResidue",
+ "MultiArgHelloWorld",
+ "call(* *(java.lang.Object, java.lang.Object)) && args(s, ..)",
+ new String[] { "java.lang.String" },
+ new String[] { "s" });
+ checkWeave(
+ "StateResidue",
+ "MultiArgHelloWorld",
+ "call(* *(java.lang.Object, java.lang.Object)) && args(s, *)",
+ new String[] { "java.lang.String" },
+ new String[] { "s" });
+ }
+
+
+
+ public void testAdd() throws IOException {
+ checkDynamicWeave("AddResidue", "call(public * add(..)) && target(java.util.ArrayList)");
+ checkDynamicWeave("AddResidue", "call(public * add(..)) && (target(java.util.ArrayList) || target(java.lang.String))");
+ checkDynamicWeave("AddResidue", "call(public * add(..)) && this(java.io.Serializable) && target(java.util.ArrayList) && !this(java.lang.Integer)");
+ }
+
+ public void testNot() throws IOException {
+ checkDynamicWeave("AddNotResidue", "call(public * add(..)) && !target(java.util.ArrayList)");
+ checkDynamicWeave("AddNotResidue", "call(public * add(..)) && !(target(java.util.ArrayList) || target(java.lang.String)) ");
+ checkDynamicWeave("AddNotResidue", "call(public * add(..)) && target(java.lang.Object) && !target(java.util.ArrayList)");
+ }
+
+ public void testState() throws IOException {
+ checkWeave(
+ "AddStateResidue",
+ "DynamicHelloWorld",
+ "call(public * add(..)) && target(list)",
+ new String[] { "java.util.ArrayList" },
+ new String[] { "list" });
+ checkWeave(
+ "AddStateResidue",
+ "DynamicHelloWorld",
+ "target(foo) && !target(java.lang.Integer) && call(public * add(..))",
+ new String[] { "java.util.ArrayList" },
+ new String[] { "foo" });
+ checkDynamicWeave(
+ "AddResidue",
+ "call(public * add(..)) && (target(java.util.ArrayList) || target(java.lang.String))");
+ checkDynamicWeave(
+ "AddResidue",
+ "call(public * add(..)) && this(java.io.Serializable) && target(java.util.ArrayList) && !this(java.lang.Integer)");
+ }
+
+ public void testNoResidueArgs() throws IOException {
+ checkDynamicWeave("NoResidue", "call(public * add(..)) && args(java.lang.Object)");
+ checkDynamicWeave("NoResidue", "call(public * add(..)) && args(*)");
+ checkDynamicWeave("NoResidue", "call(public * add(..))");
+ }
+
+ // ---- cflow tests
+
+ public void testCflowState() throws IOException {
+ checkWeave(
+ "CflowStateResidue",
+ "DynamicHelloWorld",
+ "cflow(call(public * add(..)) && target(list)) && execution(public void main(..))",
+ new String[] { "java.util.ArrayList" },
+ new String[] { "list" });
+// checkWeave(
+// "CflowStateResidue",
+// "DynamicHelloWorld",
+// "cflow(call(public * add(..)) && target(list)) && this(obj) && execution(public void doit(..))",
+// new String[] { "java.lang.Object", "java.util.ArrayList" },
+// new String[] { "obj", "list" });
+// checkWeave(
+// "AddStateResidue",
+// "DynamicHelloWorld",
+// "target(foo) && !target(java.lang.Integer) && call(public * add(..))",
+// new String[] { "java.util.ArrayList" },
+// new String[] { "foo" });
+// checkDynamicWeave(
+// "AddResidue",
+// "call(public * add(..)) && (target(java.util.ArrayList) || target(java.lang.String))");
+// checkDynamicWeave(
+// "AddResidue",
+// "call(public * add(..)) && this(java.io.Serializable) && target(java.util.ArrayList) && !this(java.lang.Integer)");
+ }
+
+
+
+
+
+ // ----
+
+ private void checkDynamicWeave(String label, String pointcutSource) throws IOException {
+ checkWeave(label, "DynamicHelloWorld", pointcutSource, new String[0], new String[0]);
+ }
+
+ private void checkMultiArgWeave(String label, String pointcutSource) throws IOException {
+ checkWeave(label, "MultiArgHelloWorld", pointcutSource, new String[0], new String[0]);
+ }
+
+ private void checkWeave(
+ String label,
+ String filename,
+ String pointcutSource,
+ String[] formalTypes,
+ String[] formalNames)
+ throws IOException
+ {
+ final Pointcut sp = Pointcut.fromString(pointcutSource);
+ final Pointcut rp =
+ sp.resolve(
+ new SimpleScope(
+ world,
+ SimpleScope.makeFormalBindings(TypeX.forNames(formalTypes),
+ formalNames)
+ ));
+
+ ShadowMunger pp =
+ world.concreteAdvice(
+ AdviceKind.Before,
+ rp,
+ Member.method(
+ TypeX.forName("Aspect"),
+ Modifier.STATIC,
+ "ajc_before_0",
+ Member.typesToSignature(
+ ResolvedTypeX.VOID,
+ TypeX.forNames(formalTypes))),
+ 0, -1, -1, null);
+
+ ResolvedTypeX inAspect = world.resolve("Aspect");
+ CrosscuttingMembers xcut = new CrosscuttingMembers(inAspect);
+ inAspect.crosscuttingMembers = xcut;
+
+ ShadowMunger cp = pp.concretize(inAspect, world, null);
+
+ xcut.addConcreteShadowMunger(cp);
+
+ //System.out.println("extras: " + inAspect.getExtraConcreteShadowMungers());
+// List advice = new ArrayList();
+// advice.add(cp);
+// advice.addAll(inAspect.getExtraConcreteShadowMungers());
+ weaveTest(new String[] { filename }, label, xcut.getShadowMungers());
+
+ checkSerialize(rp);
+ }
+
+ public void weaveTest(String name, String outName, ShadowMunger planner) throws IOException {
+ List l = new ArrayList(1);
+ l.add(planner);
+ weaveTest(name, outName, l);
+ }
+
+
+ public void checkSerialize(Pointcut p) throws IOException {
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ DataInputStream in = new DataInputStream(bi);
+ Pointcut newP = Pointcut.read(in, null);
+
+ assertEquals("write/read", p, newP);
+ }
+
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/TjpWeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/TjpWeaveTestCase.java
new file mode 100644
index 000000000..32aede4d7
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/TjpWeaveTestCase.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.util.*;
+import java.io.*;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.weaver.*;
+
+public class TjpWeaveTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public TjpWeaveTestCase(String name) {
+ super(name);
+ }
+
+
+ public void testStaticTjp() throws IOException {
+ BcelAdvice munger = new BcelAdvice(
+ AdviceKind.stringToKind("before"),
+ makePointcutAll(),
+ Member.methodFromString("static void Aspect.ajc_before(org.aspectj.lang.JoinPoint$StaticPart)"),
+ Advice.ThisJoinPointStaticPart, -1, -1, null, null);
+
+ weaveTest("HelloWorld", "StaticTjpBeforeHelloWorld", munger);
+ }
+
+
+ public void testEnclosingStaticTjp() throws IOException {
+ BcelAdvice munger = new BcelAdvice(
+ AdviceKind.stringToKind("before"),
+ makePointcutAll(),
+ Member.methodFromString("static void Aspect.ajc_before(org.aspectj.lang.JoinPoint$StaticPart)"),
+ Advice.ThisEnclosingJoinPointStaticPart, -1, -1, null, null);
+
+ weaveTest("HelloWorld", "StaticEnclosingTjpBeforeHelloWorld", munger);
+ }
+
+
+ public void testTjp() throws IOException {
+ BcelAdvice munger = new BcelAdvice(
+ AdviceKind.stringToKind("before"),
+ makePointcutAll(),
+ Member.methodFromString("static void Aspect.ajc_before(org.aspectj.lang.JoinPoint)"),
+ Advice.ThisJoinPoint, -1, -1, null, null);
+
+ weaveTest("HelloWorld", "TjpBeforeHelloWorld", munger);
+ }
+
+ public void testAroundTjp() throws IOException {
+ BcelAdvice munger = new BcelAdvice(
+ AdviceKind.stringToKind("around"),
+ makePointcutAll(),
+ Member.methodFromString("static java.lang.Object Aspect.ajc_around(org.aspectj.runtime.internal.AroundClosure, org.aspectj.lang.JoinPoint)"),
+ Advice.ThisJoinPoint | Advice.ExtraArgument, -1, -1, null, null);
+
+ weaveTest("HelloWorld", "TjpAroundHelloWorld", munger);
+ }
+
+ public void testAround2Tjp() throws IOException {
+ BcelAdvice munger1 = new BcelAdvice(
+ AdviceKind.stringToKind("around"),
+ makePointcutAll(),
+ Member.methodFromString("static java.lang.Object Aspect.ajc_around(org.aspectj.runtime.internal.AroundClosure, org.aspectj.lang.JoinPoint)"),
+ Advice.ThisJoinPoint | Advice.ExtraArgument, -1, -1, null,
+ world.resolve(TypeX.forName("Aspect")));
+
+ BcelAdvice munger2 = new BcelAdvice(
+ AdviceKind.stringToKind("around"),
+ makePointcutAll(),
+ Member.methodFromString("static java.lang.Object Aspect.ajc_around(org.aspectj.runtime.internal.AroundClosure, org.aspectj.lang.JoinPoint)"),
+ Advice.ThisJoinPoint | Advice.ExtraArgument, -1, -1, null,
+ world.resolve(TypeX.forName("Aspect")));
+
+ weaveTest("HelloWorld", "TjpAround2HelloWorld", Arrays.asList(new BcelAdvice[] {munger1, munger2}));
+ }
+
+
+
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/TraceJarWeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/TraceJarWeaveTestCase.java
new file mode 100644
index 000000000..ed06ecd1e
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/TraceJarWeaveTestCase.java
@@ -0,0 +1,40 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.IOException;
+
+public class TraceJarWeaveTestCase extends WeaveTestCase {
+ {
+ regenerate = true;
+ }
+
+ public TraceJarWeaveTestCase(String name) {
+ super(name);
+ }
+
+
+ public void testTraceJar() throws IOException {
+ world = new BcelWorld(getTraceJar());
+ BcelWeaver weaver = new BcelWeaver(world);
+ weaver.addLibraryAspect("MyTrace");
+
+ UnwovenClassFile classFile = makeUnwovenClassFile(classDir, "DynamicHelloWorld", outDir);
+
+ weaver.addClassFile(classFile);
+ weaver.prepareForWeave();
+
+ weaveTestInner(weaver, classFile, "DynamicHelloWorld", "TraceJarHello");
+ }
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/UtilityTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/UtilityTestCase.java
new file mode 100644
index 000000000..a18856711
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/UtilityTestCase.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+import java.io.*;
+
+import junit.framework.TestCase;
+
+import org.apache.bcel.util.ClassPath;
+
+public class UtilityTestCase extends TestCase {
+
+ public UtilityTestCase(String name) {
+ super(name);
+ }
+
+ public void disassembleTest(String name) throws IOException {
+ BcelWorld world = new BcelWorld("../bcweaver/bin");
+
+ LazyClassGen clazz = new LazyClassGen((BcelObjectType) world.resolve(name));
+ clazz.print();
+ System.out.println();
+ }
+
+
+ public void testHelloWorld() throws IOException {
+ disassembleTest("Test");
+ }
+ public void testFancyHelloWorld() throws IOException {
+ disassembleTest("FancyHelloWorld");
+ }
+// public void testSwitchy() throws IOException {
+// disassembleTest("TestSwitchy");
+// }
+
+ public static void main(String[] args) throws IOException {
+ BcelWorld world = new BcelWorld();
+ LazyClassGen clazz = new LazyClassGen((BcelObjectType)world.resolve(args[0]));
+ clazz.print();
+ }
+}
+
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/WeaveOrderTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/WeaveOrderTestCase.java
new file mode 100644
index 000000000..a2a4c9787
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/WeaveOrderTestCase.java
@@ -0,0 +1,155 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.util.*;
+import java.io.*;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.patterns.*;
+import org.aspectj.weaver.patterns.DeclareDominates;
+import org.aspectj.weaver.*;
+
+/**.
+ */
+public class WeaveOrderTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+
+ public WeaveOrderTestCase(String name) {
+ super(name);
+ }
+
+
+ public void testLexicalOrder() {
+ Advice a1 =
+ makeConcreteAdvice(AdviceKind.Before, TypeX.OBJECT, TypeX.OBJECT, 1);
+ Advice a2 =
+ makeConcreteAdvice(AdviceKind.Before, TypeX.OBJECT, TypeX.THROWABLE, 2);
+
+ assertEquals(-1, a2.compareTo(a1));
+ assertEquals(+1, a1.compareTo(a2));
+ }
+
+ public void testLexicalOrderWithAfter() {
+ Advice a1 =
+ makeConcreteAdvice(AdviceKind.Before, TypeX.OBJECT, TypeX.OBJECT, 1);
+ Advice a2 =
+ makeConcreteAdvice(AdviceKind.After, TypeX.OBJECT, TypeX.THROWABLE, 2);
+
+ assertEquals(+1, a2.compareTo(a1));
+ assertEquals(-1, a1.compareTo(a2));
+
+ a1 =
+ makeConcreteAdvice(AdviceKind.After, TypeX.OBJECT, TypeX.OBJECT, 1);
+ a2 =
+ makeConcreteAdvice(AdviceKind.After, TypeX.OBJECT, TypeX.THROWABLE, 2);
+
+ assertEquals(+1, a2.compareTo(a1));
+ assertEquals(-1, a1.compareTo(a2));
+ }
+
+ public void testSubtypes() {
+ Advice a1 =
+ makeConcreteAdvice(AdviceKind.Before, TypeX.OBJECT, TypeX.OBJECT, 1);
+ Advice a2 =
+ makeConcreteAdvice(AdviceKind.Before, TypeX.THROWABLE, TypeX.OBJECT, 1);
+ Advice a3 =
+ makeConcreteAdvice(AdviceKind.Before, TypeX.forName("java.lang.String"), TypeX.OBJECT, 1);
+
+ assertEquals(+1, a2.compareTo(a1));
+ assertEquals(-1, a1.compareTo(a2));
+
+ assertEquals(+1, a3.compareTo(a1));
+ assertEquals(-1, a1.compareTo(a3));
+
+ assertEquals(0, a3.compareTo(a2));
+ assertEquals(0, a2.compareTo(a3));
+ }
+
+
+ public void testDominates() {
+ Declare dom =
+ new PatternParser("declare dominates: java.lang.String, java.lang.Throwable").parseDeclare();
+ //??? concretize dom
+ ResolvedTypeX aType = world.resolve("Aspect");
+ CrosscuttingMembers xcut = new CrosscuttingMembers(aType);
+ aType.crosscuttingMembers = xcut;
+ xcut.addDeclare(dom);
+ world.getCrosscuttingMembersSet().addFixedCrosscuttingMembers(aType);
+
+ Advice a1 =
+ makeConcreteAdvice(AdviceKind.Before, TypeX.OBJECT, TypeX.OBJECT, 1);
+ Advice a2 =
+ makeConcreteAdvice(AdviceKind.Before, TypeX.OBJECT, TypeX.THROWABLE, 2);
+ Advice a3 =
+ makeConcreteAdvice(AdviceKind.Before, TypeX.OBJECT, TypeX.forName("java.lang.String"), 2);
+
+ assertEquals(-1, a2.compareTo(a1));
+ assertEquals(+1, a1.compareTo(a2));
+
+ assertEquals(-1, a3.compareTo(a1));
+ assertEquals(+1, a1.compareTo(a3));
+
+
+ assertEquals(+1, a3.compareTo(a2));
+ assertEquals(-1, a2.compareTo(a3));
+ }
+
+ public void testDominatesHarder() {
+ Declare dom =
+ new PatternParser("declare dominates: *, java.lang.String, java.lang.Throwable").parseDeclare();
+ //??? concretize dom
+ ResolvedTypeX aType = world.resolve("Aspect");
+ CrosscuttingMembers xcut = new CrosscuttingMembers(aType);
+ aType.crosscuttingMembers = xcut;
+ xcut.addDeclare(dom);
+ world.getCrosscuttingMembersSet().addFixedCrosscuttingMembers(aType);
+
+ Advice a1 =
+ makeConcreteAdvice(AdviceKind.Before, TypeX.OBJECT, TypeX.OBJECT, 2);
+ Advice a2 =
+ makeConcreteAdvice(AdviceKind.Before, TypeX.OBJECT, TypeX.THROWABLE, 1);
+ Advice a3 =
+ makeConcreteAdvice(AdviceKind.Before, TypeX.OBJECT, TypeX.forName("java.lang.String"), 1);
+
+ assertEquals(-1, a2.compareTo(a1));
+ assertEquals(+1, a1.compareTo(a2));
+
+ assertEquals(-1, a3.compareTo(a1));
+ assertEquals(+1, a1.compareTo(a3));
+
+
+ assertEquals(+1, a3.compareTo(a2));
+ assertEquals(-1, a2.compareTo(a3));
+ }
+
+
+
+
+ private Advice makeConcreteAdvice(AdviceKind kind, TypeX declaringAspect,
+ TypeX concreteAspect, int lexicalPosition)
+ {
+ Advice a1 = new BcelAdvice(kind, makeResolvedPointcut("this(*)"),
+ Member.method(declaringAspect, 0, "foo", "()V"),
+ 0, lexicalPosition, lexicalPosition, null, null);
+ a1 = (Advice)a1.concretize(concreteAspect.resolve(world), world, null);
+ return a1;
+ }
+
+
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/WeaveTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/WeaveTestCase.java
new file mode 100644
index 000000000..62c078e61
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/WeaveTestCase.java
@@ -0,0 +1,324 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import java.util.zip.ZipFile;
+
+import junit.framework.*;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.generic.*;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.patterns.*;
+import org.aspectj.testing.util.TestUtil;
+import org.aspectj.util.FileUtil;
+
+public abstract class WeaveTestCase extends TestCase {
+
+ public boolean regenerate = false;
+ public boolean runTests = true;
+
+ public BcelWorld world = new BcelWorld();
+
+ public WeaveTestCase(String name) {
+ super(name);
+ }
+
+ public static InstructionList getAdviceTag(BcelShadow shadow, String where) {
+ String methodName =
+ "ajc_" + where + "_" + shadow.getKind().toLegalJavaIdentifier();
+
+ InstructionFactory fact = shadow.getFactory();
+ InvokeInstruction il =
+ fact.createInvoke("Aspect", methodName, Type.VOID, new Type[] {
+ }, Constants.INVOKESTATIC);
+ return new InstructionList(il);
+ }
+
+ public void weaveTest(String name, String outName, ShadowMunger planner) throws IOException {
+ List l = new ArrayList(1);
+ l.add(planner);
+ weaveTest(name, outName, l);
+ }
+
+ static String classDir = "../bcweaver/bin";
+ static String outDir = "out";
+
+
+ public void weaveTest(String name, String outName, List planners) throws IOException {
+ BcelWeaver weaver = new BcelWeaver(world);
+
+ UnwovenClassFile classFile = makeUnwovenClassFile(classDir, name, outDir);
+
+ weaver.addClassFile(classFile);
+ weaver.setShadowMungers(planners);
+ weaveTestInner(weaver, classFile, name, outName);
+ }
+
+
+ protected void weaveTestInner(
+ BcelWeaver weaver,
+ UnwovenClassFile classFile,
+ String name,
+ String outName)
+ throws IOException
+ {
+ //int preErrors = currentResult.errorCount();
+ BcelObjectType classType =
+ (BcelObjectType) world.resolve(classFile.getClassName());
+ LazyClassGen gen = weaver.weave(classFile, classType);
+ if (gen == null) {
+ // we didn't do any weaving, but let's make a gen anyway
+ gen = new LazyClassGen(classType);
+ }
+ try {
+ checkClass(gen, outDir, outName + ".txt");
+ if (runTests) {
+ System.out.println(
+ "*******RUNNING: " + outName + " " + name + " *******");
+ TestUtil.runMain(makeClassPath(outDir), name);
+ }
+ } catch (Error e) {
+ gen.print(System.err);
+ throw e;
+ } catch (RuntimeException e) {
+ gen.print(System.err);
+ throw e;
+ }
+ }
+
+ public String makeClassPath(String outDir) {
+ return outDir
+ + File.pathSeparator
+ + getTraceJar()
+ + File.pathSeparator
+ + System.getProperty("java.class.path");
+ }
+
+
+ /** '/' in the name indicates the location of the class
+ */
+ public static UnwovenClassFile makeUnwovenClassFile(
+ String classDir,
+ String name,
+ String outDir) throws IOException {
+ File outFile = new File(outDir, name+".class");
+ if (classDir.endsWith(".jar")) {
+ String fname = name+".class";
+ UnwovenClassFile ret =
+ new UnwovenClassFile(outFile.getAbsolutePath(),
+ FileUtil.readAsByteArray(FileUtil.getStreamFromZip(classDir, fname)));
+ return ret;
+ } else {
+ File inFile = new File(classDir, name+".class");
+ return new UnwovenClassFile(outFile.getAbsolutePath(), FileUtil.readAsByteArray(inFile));
+ }
+ }
+
+ public void checkClass(LazyClassGen gen, String outDir, String expectedFile) throws IOException {
+ if (regenerate) genClass(gen, outDir, expectedFile);
+ else realCheckClass(gen, outDir, expectedFile);
+ }
+
+ void genClass(LazyClassGen gen, String outDir, String expectedFile) throws IOException {
+ //ClassGen b = getJavaClass(outDir, className);
+ FileOutputStream out = new FileOutputStream(new File("testdata", expectedFile));
+ PrintStream ps = new PrintStream(out);
+ gen.print(ps);
+ ps.flush();
+
+ }
+
+ void realCheckClass(LazyClassGen gen, String outDir, String expectedFile) throws IOException {
+ TestUtil.assertMultiLineStringEquals("classes",
+ FileUtil.readAsString(new File("testdata", expectedFile)),
+ gen.toLongString());
+ }
+
+
+ // ----
+ public ShadowMunger makeConcreteAdvice(String mungerString) {
+ return makeConcreteAdvice(mungerString, 0, null);
+ }
+
+ public ShadowMunger makeConcreteAdvice(String mungerString, int extraArgFlag) {
+ return makeConcreteAdvice(mungerString, extraArgFlag, null);
+ }
+
+ protected ShadowMunger makeConcreteAdvice(String mungerString, int extraArgFlag, PerClause perClause) {
+ Advice myMunger =
+ world.shadowMunger(mungerString, extraArgFlag);
+
+// PerSingleton s = new PerSingleton();
+// s.concretize(world.resolve("Aspect"));
+ //System.err.println(((KindedPointcut)myMunger.getPointcut().getPointcut()).getKind());
+ Advice cm = (Advice) myMunger.concretize(myMunger.getDeclaringAspect().resolve(world),
+ world, perClause);
+ return cm;
+ }
+
+ public ShadowMunger makeAdviceField(String kind, String extraArgType) {
+ return makeConcreteAdvice(
+ kind
+ + "(): get(* *.*) -> static void Aspect.ajc_"
+ + kind
+ + "_field_get("
+ + extraArgType
+ + ")",
+ 1);
+ }
+
+ public List makeAdviceAll(String kind, boolean matchOnlyPrintln) {
+ List ret = new ArrayList();
+ if (matchOnlyPrintln) {
+ ret.add(
+ makeConcreteAdvice(
+ kind
+ + "(): call(* *.println(..)) -> static void Aspect.ajc_"
+ + kind
+ + "_method_execution()"));
+ } else {
+ ret.add(
+ makeConcreteAdvice(
+ kind
+ + "(): call(* *.*(..)) -> static void Aspect.ajc_"
+ + kind
+ + "_method_call()"));
+ ret.add(
+ makeConcreteAdvice(
+ kind
+ + "(): call(*.new(..)) -> static void Aspect.ajc_"
+ + kind
+ + "_constructor_call()"));
+ ret.add(
+ makeConcreteAdvice(
+ kind
+ + "(): execution(* *.*(..)) -> static void Aspect.ajc_"
+ + kind
+ + "_method_execution()"));
+ ret.add(
+ makeConcreteAdvice(
+ kind
+ + "(): execution(*.new(..)) -> static void Aspect.ajc_"
+ + kind
+ + "_constructor_execution()"));
+// ret.add(
+// makeConcreteMunger(
+// kind
+// + "(): staticinitialization(*) -> static void Aspect.ajc_"
+// + kind
+// + "_staticinitialization()"));
+ ret.add(
+ makeConcreteAdvice(
+ kind + "(): get(* *.*) -> static void Aspect.ajc_" + kind + "_field_get()"));
+// ret.add(
+// makeConcreteMunger(
+// kind + "(): set(* *.*) -> static void Aspect.ajc_" + kind + "_field_set()"));
+ // XXX no test for advice execution, staticInitialization or (god help us) preInitialization
+ }
+ return ret;
+ }
+
+ public List makeAdviceAll(final String kind) {
+ return makeAdviceAll(kind, false);
+ }
+
+ public Pointcut makePointcutAll() {
+ return makeConcretePointcut("get(* *.*) || call(* *.*(..)) || execution(* *.*(..)) || call(*.new(..)) || execution(*.new(..))");
+ }
+ public Pointcut makePointcutNoZeroArg() {
+ return makeConcretePointcut("call(* *.*(*, ..)) || execution(* *.*(*, ..)) || call(*.new(*, ..)) || execution(*.new(*, ..))");
+ }
+
+ public Pointcut makePointcutPrintln() {
+ return makeConcretePointcut("call(* *.println(..))");
+ }
+
+
+ public Pointcut makeConcretePointcut(String s) {
+ return makeResolvedPointcut(s).concretize(null, 0);
+ }
+
+ public Pointcut makeResolvedPointcut(String s) {
+ Pointcut pointcut0 = Pointcut.fromString(s);
+ return pointcut0.resolve(new SimpleScope(world, FormalBinding.NONE));
+ }
+
+
+ // ----
+
+ public String[] getStandardTargets() {
+ return new String[] {"HelloWorld", "FancyHelloWorld"};
+ }
+
+ public String getTraceJar() {
+ return "testdata/tracing.jar";
+ }
+
+ // ----
+
+ protected void weaveTest(
+ String[] inClassNames,
+ String outKind,
+ ShadowMunger patternMunger) throws IOException {
+ for (int i = 0; i < inClassNames.length; i++) {
+ String inFileName = inClassNames[i];
+ weaveTest(inFileName, outKind + inFileName, patternMunger);
+ }
+ }
+ protected void weaveTest(
+ String[] inClassNames,
+ String outKind,
+ List patternMungers) throws IOException {
+ for (int i = 0; i < inClassNames.length; i++) {
+ String inFileName = inClassNames[i];
+ weaveTest(inFileName, outKind + inFileName, patternMungers);
+ }
+ }
+
+ protected List addLexicalOrder(List l) {
+ int i = 10;
+ for (Iterator iter = l.iterator(); iter.hasNext();) {
+ Advice element = (Advice) iter.next();
+ element.setLexicalPosition(i+=10);
+ }
+ return l;
+ }
+
+ //XXX cut-and-paster from IdWeaveTestCase
+ public void checkShadowSet(List l, String[] ss) {
+ outer:
+ for (int i = 0, len = ss.length; i < len; i++) {
+ inner:
+ for (Iterator j = l.iterator(); j.hasNext(); ) {
+ BcelShadow shadow = (BcelShadow) j.next();
+ String shadowString = shadow.toString();
+ if (shadowString.equals(ss[i])) {
+ j.remove();
+ continue outer;
+ }
+ }
+ assertTrue("didn't find " + ss[i] + " in " + l, false);
+ }
+ assertTrue("too many things in " + l, l.size() == 0);
+ }
+
+
+
+
+
+}
+
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/WorldTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/WorldTestCase.java
new file mode 100644
index 000000000..47202bb66
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/WorldTestCase.java
@@ -0,0 +1,148 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.lang.reflect.Modifier;
+
+import org.apache.bcel.util.ClassPath;
+import org.aspectj.weaver.*;
+
+/**
+ * This is a test case for the nameType parts of worlds.
+ */
+public class WorldTestCase extends AbstractWorldTestCase {
+
+ public WorldTestCase(String name) {
+ super(name);
+ }
+
+ private final BcelWorld world = new BcelWorld("testdata/tracing.jar");
+
+ protected World getWorld() {
+ return world;
+ }
+
+ // XXX fix the various XXXs before expecting this test to work
+ public void xtestTraceJar() {
+ ResolvedTypeX trace = world.resolve(TypeX.forName("Trace"));
+
+ fieldsTest(trace, Member.NONE);
+ Member constr = Member.methodFromString("void Trace.<init>()");
+ //XXX need attribute fix -
+ //methodsTest(trace, new Member[] { constr });
+
+ interfacesTest(trace, ResolvedTypeX.NONE);
+ superclassTest(trace, TypeX.OBJECT);
+ isInterfaceTest(trace, false);
+ isClassTest(trace, false);
+ isAspectTest(trace, true);
+
+ pointcutsTest(trace,
+ new Member[] {
+ Member.pointcut(trace, "traced", "(Ljava/lang/Object;)V"),
+ });
+
+ modifiersTest(trace.findPointcut("traced"),
+ Modifier.PUBLIC | Modifier.ABSTRACT);
+
+ mungersTest(trace,
+ new ShadowMunger[] {
+ world.shadowMunger("before(foo): traced(foo) -> void Trace.ajc_before_4(java.lang.Object))",
+ 0),
+ world.shadowMunger("afterReturning(foo): traced(foo) -> void Trace.ajc_afterreturning_3(java.lang.Object, java.lang.Object))",
+ Advice.ExtraArgument),
+ world.shadowMunger("around(): execution(* doit(..)) -> java.lang.Object Trace.ajc_around_2(org.aspectj.runtime.internal.AroundClosure))",
+ Advice.ExtraArgument),
+ world.shadowMunger("around(foo): traced(foo) -> java.lang.Object Trace.ajc_around_1(java.lang.Object, org.aspectj.runtime.internal.AroundClosure))",
+ Advice.ExtraArgument),
+ });
+
+ ResolvedTypeX myTrace = world.resolve(TypeX.forName("MyTrace"));
+
+ interfacesTest(myTrace, ResolvedTypeX.NONE);
+ superclassTest(myTrace, trace);
+ isInterfaceTest(myTrace, false);
+ isClassTest(myTrace, false);
+ isAspectTest(myTrace, true);
+
+ //XXX need attribute fix -
+ //fieldsTest(myTrace, Member.NONE);
+
+
+ pointcutsTest(trace,
+ new Member[] {
+ Member.pointcut(trace, "traced", "(Ljava/lang/Object;)V"),
+ });
+
+ modifiersTest(myTrace.findPointcut("traced"),
+ Modifier.PUBLIC);
+
+ // this tests for declared mungers
+ mungersTest(myTrace, ShadowMunger.NONE);
+
+ }
+
+ public void testIterator() {
+ int abstractPublic = Modifier.ABSTRACT | Modifier.PUBLIC;
+ ResolvedTypeX iter = world.resolve(TypeX.forName("java.util.Iterator"));
+
+ modifiersTest(iter, abstractPublic | Modifier.INTERFACE);
+ fieldsTest(iter, ResolvedMember.NONE);
+ methodsTest(iter,
+ new Member[] {
+ Member.method(iter, 0, "hasNext", "()Z"),
+ Member.method(iter, 0, "remove", "()V"),
+ Member.method(iter, 0, "next", "()Ljava/lang/Object;"),
+ });
+ ResolvedMember remove = iter.lookupMethod(Member.method(iter, 0, "remove", "()V"));
+ assertNotNull("iterator doesn't have remove" , remove);
+ modifiersTest(remove, abstractPublic | Modifier.INTERFACE);
+ exceptionsTest(remove, TypeX.NONE);
+
+ ResolvedMember clone = iter.lookupMethod(Member.method(TypeX.OBJECT, 0, "clone", "()Ljava/lang/Object;"));
+ assertNotNull("iterator doesn't have clone" , clone);
+ modifiersTest(clone, Modifier.PROTECTED | Modifier.NATIVE);
+ exceptionsTest(clone, TypeX.forNames(new String[] {"java.lang.CloneNotSupportedException"}));
+
+ interfacesTest(iter, ResolvedTypeX.NONE);
+ superclassTest(iter, TypeX.OBJECT);
+ pointcutsTest(iter, ResolvedMember.NONE);
+ mungersTest(iter, ShadowMunger.NONE);
+ isInterfaceTest(iter, true);
+ isClassTest(iter, false);
+ isAspectTest(iter, false);
+ }
+
+ public void testObjectCoersion() {
+ assertCouldBeCoercibleFrom("java.lang.Object", "java.lang.String");
+ assertCouldBeCoercibleFrom("java.lang.Integer", "java.lang.Object");
+ assertCouldBeCoercibleFrom("java.io.Serializable", "java.lang.Runnable");
+ assertCouldBeCoercibleFrom("java.util.Stack", "java.lang.Runnable");
+ assertCouldNotBeCoercibleFrom("java.lang.Runnable", "java.lang.Integer");
+ assertCouldNotBeCoercibleFrom("java.lang.Integer", "java.lang.String");
+ assertCouldNotBeCoercibleFrom("java.lang.Integer", "java.lang.Runnable");
+ }
+
+ // ----
+
+ private void assertCouldBeCoercibleFrom(String a, String b) {
+ isCoerceableFromTest(world.resolve(a), world.resolve(b), true);
+ }
+
+ private void assertCouldNotBeCoercibleFrom(String a, String b) {
+ isCoerceableFromTest(world.resolve(a), world.resolve(b), false);
+ }
+
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/ZipTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/ZipTestCase.java
new file mode 100644
index 000000000..27e68fc93
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/ZipTestCase.java
@@ -0,0 +1,90 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.bcel;
+
+import java.io.*;
+import java.util.Collection;
+
+import junit.framework.TestCase;
+
+public class ZipTestCase extends TestCase {
+
+ /**
+ * Constructor for ZipTestCase.
+ * @param arg0
+ */
+ public ZipTestCase(String arg0) {
+ super(arg0);
+ }
+
+
+ public void zipTest(String fileName, String aspectjar) throws IOException {
+ zipTest(fileName, aspectjar, false);
+ }
+
+ public void zipTest(String fileName, String aspectjar, boolean isInJar) throws IOException {
+ File inFile = new File(fileName);
+ File outFile = new File("out", inFile.getName());
+
+
+ BcelWorld world = new BcelWorld();
+ //BcelWeaver weaver1 = new BcelWeaver(world);
+ BcelWeaver weaver = new BcelWeaver(world);
+
+ long startTime = System.currentTimeMillis();
+ weaver.addJarFile(inFile, new File("."));
+ if (aspectjar != null) {
+ if (isInJar) {
+ weaver.addJarFile(new File(aspectjar), new File("."));
+ } else {
+ weaver.addLibraryJarFile(new File(aspectjar));
+ }
+ }
+
+
+ Collection woven = weaver.weave(outFile);
+ long stopTime = System.currentTimeMillis();
+
+
+ System.out.println("handled " + woven.size() + " entries, in " +
+ (stopTime-startTime)/1000. + " seconds");
+ assertTrue(outFile.lastModified() > startTime);
+ }
+
+ public void testSmall() throws IOException {
+ zipTest("testdata/Regex.jar", null);
+ }
+
+ public void testSmallWithAspects() throws IOException {
+ System.out.println("could take 4 seconds...");
+ zipTest("testdata/Regex.jar", "testdata/megatrace.jar");
+ }
+
+ public void testSmallWithAspectsNoWeave() throws IOException {
+ System.out.println("could take 4 seconds...");
+ zipTest("testdata/Regex.jar", "testdata/megatraceNoweave.jar", true);
+ }
+
+ // this is something we test every now and again.
+ public void testBig() throws IOException {
+ System.out.println("could take 4 seconds...");
+ zipTest("../lib/bcel/bcel.jar", null);
+ }
+
+ public void xtestBigWithAspects() throws IOException {
+ System.out.println("could take 40 seconds...");
+ zipTest("../lib/bcel/bcel.jar", "testdata/megatrace.jar");
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/AndOrNotTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/AndOrNotTestCase.java
new file mode 100644
index 000000000..e1dac9ba7
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/AndOrNotTestCase.java
@@ -0,0 +1,121 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.lang.reflect.*;
+
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.util.FuzzyBoolean;
+
+import junit.framework.TestCase;
+import org.aspectj.weaver.*;
+
+/**
+ * @author hugunin
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class AndOrNotTestCase extends TestCase {
+ /**
+ * Constructor for PatternTestCase.
+ * @param name
+ */
+ public AndOrNotTestCase(String name) {
+ super(name);
+ }
+
+ World world;
+
+
+ public void testMatch() throws IOException {
+ world = new BcelWorld();
+
+ Pointcut foo = makePointcut("this(Foo)");
+ Pointcut bar = makePointcut("this(Bar)");
+ Pointcut c = makePointcut("this(C)");
+
+ checkEquals("this(Foo) && this(Bar)", new AndPointcut(foo, bar));
+ checkEquals("this(Foo) && this(Bar) && this(C)", new AndPointcut(foo, new AndPointcut(bar, c)));
+
+
+ checkEquals("this(Foo) || this(Bar)", new OrPointcut(foo, bar));
+ checkEquals("this(Foo) || this(Bar) || this(C)", new OrPointcut(foo, new OrPointcut(bar, c)));
+
+ checkEquals("this(Foo) && this(Bar) || this(C)", new OrPointcut(new AndPointcut(foo, bar), c));
+ checkEquals("this(Foo) || this(Bar) && this(C)", new OrPointcut(foo, new AndPointcut(bar, c)));
+ checkEquals("(this(Foo) || this(Bar)) && this(C)", new AndPointcut(new OrPointcut(foo, bar), c));
+ checkEquals("this(Foo) || (this(Bar) && this(C))", new OrPointcut(foo, new AndPointcut(bar, c)));
+
+ checkEquals("!this(Foo)", new NotPointcut(foo));
+ checkEquals("!this(Foo) && this(Bar)", new AndPointcut(new NotPointcut(foo), bar));
+ checkEquals("!(this(Foo) && this(Bar)) || this(C)", new OrPointcut(new NotPointcut(new AndPointcut(foo, bar)), c));
+ checkEquals("!!this(Foo)", new NotPointcut(new NotPointcut(foo)));
+
+ }
+
+ private Pointcut makePointcut(String pattern) {
+ return new PatternParser(pattern).parsePointcut();
+ }
+
+ private void checkEquals(String pattern, Pointcut p) throws IOException {
+ assertEquals(pattern, p, makePointcut(pattern));
+ checkSerialization(pattern);
+ }
+
+
+// private void checkMatch(Pointcut p, Signature[] matches, boolean shouldMatch) {
+// for (int i=0; i<matches.length; i++) {
+// boolean result = p.matches(matches[i]);
+// String msg = "matches " + p + " to " + matches[i] + " expected ";
+// if (shouldMatch) {
+// assertTrue(msg + shouldMatch, result);
+// } else {
+// assertTrue(msg + shouldMatch, !result);
+// }
+// }
+// }
+//
+// public void testSerialization() throws IOException {
+// String[] patterns = new String[] {
+// "public * *(..)", "void *.foo(A, B)", "A b()"
+// };
+//
+// for (int i=0, len=patterns.length; i < len; i++) {
+// checkSerialization(patterns[i]);
+// }
+// }
+
+ /**
+ * Method checkSerialization.
+ * @param string
+ */
+ private void checkSerialization(String string) throws IOException {
+ Pointcut p = makePointcut(string);
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ DataInputStream in = new DataInputStream(bi);
+ Pointcut newP = Pointcut.read(in, null);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/BindingTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/BindingTestCase.java
new file mode 100644
index 000000000..d1d2b3923
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/BindingTestCase.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.util.*;
+
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.weaver.bcel.BcelShadow;
+
+import junit.framework.TestCase;
+
+import org.aspectj.bridge.AbortException;
+import org.aspectj.weaver.*;
+
+/**
+ * @author hugunin
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class BindingTestCase extends TestCase {
+
+ /**
+ * Constructor for ParserTestCase.
+ * @param arg0
+ */
+ public BindingTestCase(String arg0) {
+ super(arg0);
+ }
+
+ World world = new BcelWorld();
+
+
+ public void testResolveBindings() {
+ BindingTypePattern at = new BindingTypePattern(world.resolve("java.lang.Object"), 0);
+ BindingTypePattern bt = new BindingTypePattern(world.resolve("java.lang.Object"), 1);
+
+ BindingTypePattern[] all = new BindingTypePattern[] {at, bt};
+ BindingTypePattern[] none = new BindingTypePattern[] {null, null};
+ BindingTypePattern[] a = new BindingTypePattern[] {at, null};
+ BindingTypePattern[] b = new BindingTypePattern[] {null, bt};
+
+ checkBindings("this(b)",b);
+ checkBindings("this(Foo)", none);
+ checkBindings("this(*)", none);
+ checkBindings("this(a)", a);
+
+ checkBindings("args(.., a,..,b)", all);
+ checkBindings("args(a,..,b, ..)", all);
+
+ checkBindings("args(a,..,b)", all);
+ checkBindings("args(b)", b);
+
+ checkBindings("args()", none);
+
+ checkBindings("this(a) && this(b)", all);
+
+ checkBindingFailure("this(a) && this(a)", "multiple");
+ //checkBindingFailure("this(a) && this(b)");
+
+ checkBindingFailure("this(a) || this(b)", "inconsistent");
+ checkBindingFailure("this(A) || this(b)", "inconsistent");
+ checkBindingFailure("this(a) || this(B)", "inconsistent");
+ checkBindings("this(a) || this(a)", a);
+
+ checkBindings("!this(Foo)", none);
+ checkBindings("!this(Foo) && this(a)", a);
+ checkBindingFailure("!this(a)", "negation");
+ //checkBindingFailure("this(a)");
+
+
+ checkBindings("cflow(this(a))", a);
+ checkBindings("cflow(this(a)) && this(b)", all);
+
+ checkBindingFailure("cflow(this(a)) || this(b)", "inconsistent");
+ checkBindingFailure("cflow(this(a)) && this(a)", "multiple");
+
+ checkBindingFailure("!cflow(this(a))", "negation");
+
+ // todo
+ // this should fail since a isn't visible to if
+ //checkBindingFailure("cflow(if(a != null)) && this(a)");
+ //checkBinding("cflow(if(a != null) && this(a))", a);
+
+ }
+
+
+ /**
+ * Method checkBindingFailure. (assumes an env where "a" and "b" are formals).
+ * @param string
+ */
+ private void checkBindingFailure(String pattern, String prefix) {
+ PatternParser parser = new PatternParser(pattern);
+ Pointcut p = parser.parsePointcut();
+ Bindings actualBindings = new Bindings(2);
+ try {
+ p.resolveBindings(makeSimpleScope(), actualBindings);
+ } catch (AbortException re) {
+ assertEquals(prefix, re.getIMessage().getMessage().substring(0, prefix.length()));
+ //System.out.println("expected exception: " + re);
+ return;
+ }
+ assertTrue("should have failed", false);
+ }
+
+
+ /**
+ * Method checkBindings.
+ * @param string
+ * @param i
+ */
+ private void checkBindings(String pattern, BindingTypePattern[] expectedBindings) {
+ PatternParser parser = new PatternParser(pattern);
+ Pointcut p = parser.parsePointcut();
+ Bindings actualBindings = new Bindings(expectedBindings.length);
+
+ TestScope simpleScope = makeSimpleScope();
+ p.resolveBindings(simpleScope, actualBindings);
+ //System.out.println(actualBindings);
+
+ new Bindings(expectedBindings).checkEquals(actualBindings, simpleScope);
+ }
+
+
+ public TestScope makeSimpleScope() {
+ return new TestScope(new String[] {"int", "java.lang.String"}, new String[] {"a", "b"}, world);
+ }
+}
+
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/ConcretizationTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/ConcretizationTestCase.java
new file mode 100644
index 000000000..1f71719ce
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/ConcretizationTestCase.java
@@ -0,0 +1,161 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import org.aspectj.testing.util.TestUtil;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.weaver.bcel.WeaveTestCase;
+
+public class ConcretizationTestCase extends WeaveTestCase {
+ {
+ regenerate = false;
+ }
+ public ConcretizationTestCase(String name) {
+ super(name);
+ }
+
+ String[] none = new String[0];
+
+
+ public void testCflowResidual() throws IOException {
+
+ BcelAdvice a = (BcelAdvice) makeConcreteTestAdviceEntryPart();
+
+ TestShadow shadow = new TestShadow(Shadow.MethodCall,
+ Member.methodFromString("int Aspect.i(int x)"),
+ TypeX.OBJECT,
+ world);
+
+ ExposedState state = new ExposedState(1);
+
+ a.specializeOn(shadow);
+
+ //System.err.println(shadow);
+ //System.err.println(a);
+
+ //System.err.println(a.exposedState);
+
+
+ }
+
+
+
+ public Advice makeConcreteTestAdviceEntryPart() throws IOException {
+ // XXX copied from below, refactor later
+
+
+ // returns the advice for the entry part of cflow(foo(a))
+ Pointcut in =
+ createResolvedPointcut(
+ "cflow(foo(a)) && (args(b) && !cflow(foo(int)))",
+ new String[] { "b", "a" },
+ new String[] { "float", "int" });
+
+ ResolvedPointcutDefinition ref =
+ new ResolvedPointcutDefinition(
+ TypeX.forName("Aspect"),
+ 0,
+ "foo",
+ new TypeX[] { ResolvedTypeX.INT },
+ createResolvedPointcut(
+ "args(refA)",
+ new String[] { "refA" },
+ new String[] { "int" }));
+ BcelObjectType target = (BcelObjectType) world.resolve("Aspect");
+
+ // now munge this to get the pointcut in it
+
+ target.addPointcutDefinition(ref);
+ CrosscuttingMembers xcut = new CrosscuttingMembers(target);
+ target.crosscuttingMembers = xcut;
+
+ Advice adviceMember =
+ new BcelAdvice(
+ AdviceKind.Before,
+ in,
+ Member.method(TypeX.forName("FOO"), 0, "garadf", "(FI)V"),
+ 0,
+ 0, 0, null,
+ null);
+ // The pointcut to concretize
+
+ // this returns the actual advice, but we don't care about it now.
+ in.concretize(target, 2, adviceMember);
+
+ List c = (List)xcut.getCflowEntries(); //target.getExtraConcreteShadowMungers();
+
+ return (Advice) c.get(0);
+ }
+
+ public void XtestCflow() throws IOException {
+ Pointcut in = createResolvedPointcut("cflow(foo(a)) && (args(b) && !cflow(foo(int)))",
+ new String[] {"b", "a"}, new String[] {"float", "int"} );
+
+ ResolvedPointcutDefinition ref =
+ new ResolvedPointcutDefinition(TypeX.forName("Aspect"),
+ 0, "foo", new TypeX[] { ResolvedTypeX.INT },
+ createResolvedPointcut("args(refA)",
+ new String[] {"refA"}, new String[] {"int"}));
+
+ List expectedSlots = new ArrayList();
+ expectedSlots.add(new ConcreteCflowPointcut.Slot(1, ResolvedTypeX.INT, 0));
+
+ checkConcr(in, ref, expectedSlots);
+ }
+
+ public void checkConcr(
+ Pointcut in,
+ ResolvedPointcutDefinition referredTo,
+ List expectedSlots) throws IOException {
+
+ BcelObjectType target = (BcelObjectType)world.resolve("Aspect");
+
+ // now munge this to get the pointcut in it
+
+ target.addPointcutDefinition(referredTo);
+
+
+ Advice adviceMember = new BcelAdvice(AdviceKind.Before, in,
+ Member.method(TypeX.forName("FOO"), 0, "garadf", "(FI)V"), 0, 0, 0, null, null);
+
+ // The pointcut to concretize
+ AndPointcut ap = (AndPointcut)in.concretize(target, 2, adviceMember);
+
+
+ ConcreteCflowPointcut conc = (ConcreteCflowPointcut)ap.left;
+
+ List slots = conc.slots;
+ TestUtil.assertSetEquals(expectedSlots, slots);
+
+ }
+
+
+ public Pointcut createResolvedPointcut(
+ String pointcutSource, String[] formalNames, String[] formalTypes) {
+ final Pointcut sp = Pointcut.fromString(pointcutSource);
+ final Pointcut rp =
+ sp.resolve(
+ new SimpleScope(
+ world,
+ SimpleScope.makeFormalBindings(TypeX.forNames(formalTypes),
+ formalNames)
+ ));
+ return rp;
+ }
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/DeclareErrorOrWarningTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/DeclareErrorOrWarningTestCase.java
new file mode 100644
index 000000000..7c125b48c
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/DeclareErrorOrWarningTestCase.java
@@ -0,0 +1,61 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import junit.framework.TestCase;
+
+public class DeclareErrorOrWarningTestCase extends TestCase {
+
+ public DeclareErrorOrWarningTestCase(String name) {
+ super(name);
+ }
+
+
+ public void testParse() throws IOException {
+ DeclareErrorOrWarning d =
+ parse("declare error: call(void foo()): \"that is bad\";");
+ assertTrue(d.isError());
+ assertEquals(d.getPointcut(),
+ new PatternParser("call(void foo())").parsePointcut());
+ assertEquals("that is bad", d.getMessage());
+ checkSerialization(d);
+
+ d = parse("declare warning: bar() && baz(): \"boo!\";");
+ assertTrue(!d.isError());
+ assertEquals(d.getPointcut(),
+ new PatternParser("bar() && baz()").parsePointcut());
+ assertEquals("boo!", d.getMessage());
+ checkSerialization(d);
+
+ }
+
+ private DeclareErrorOrWarning parse(String string) {
+ return (DeclareErrorOrWarning)new PatternParser(string).parseDeclare();
+ }
+
+ private void checkSerialization(Declare declare) throws IOException {
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ declare.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ DataInputStream in = new DataInputStream(bi);
+ Declare newDeclare = Declare.read(in, null);
+
+ assertEquals("write/read", declare, newDeclare);
+ }
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/ModifiersPatternTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/ModifiersPatternTestCase.java
new file mode 100644
index 000000000..38bc0fdad
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/ModifiersPatternTestCase.java
@@ -0,0 +1,140 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.lang.reflect.*;
+
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.util.FuzzyBoolean;
+
+import junit.framework.TestCase;
+import org.aspectj.weaver.*;
+
+public class ModifiersPatternTestCase extends TestCase {
+ /**
+ * Constructor for PatternTestCase.
+ * @param name
+ */
+ public ModifiersPatternTestCase(String name) {
+ super(name);
+ }
+
+ World world;
+
+ public void testMatch() {
+ world = new BcelWorld();
+
+ int[] publicMatches = new int[] {
+ Modifier.PUBLIC,
+ Modifier.PUBLIC | Modifier.STATIC,
+ Modifier.PUBLIC | Modifier.STATIC | Modifier.STRICT | Modifier.FINAL,
+ };
+
+ int[] publicFailures = new int[] {
+ Modifier.PRIVATE,
+ 0,
+ Modifier.STATIC | Modifier.STRICT | Modifier.FINAL,
+ };
+
+ int[] publicStaticMatches = new int[] {
+ Modifier.PUBLIC | Modifier.STATIC,
+ Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL | Modifier.STRICT,
+ };
+
+ int[] publicStaticFailures = new int[] {
+ 0,
+ Modifier.PUBLIC,
+ Modifier.STATIC,
+ };
+
+ int[] trickMatches = new int[] {
+ Modifier.PRIVATE,
+ Modifier.PRIVATE | Modifier.ABSTRACT,
+ Modifier.PRIVATE | Modifier.FINAL,
+ };
+
+ int[] trickFailures = new int[] {
+ Modifier.PUBLIC,
+ Modifier.PRIVATE | Modifier.STATIC,
+ Modifier.PRIVATE | Modifier.STRICT,
+ };
+
+
+ int[] none = new int[0];
+
+ checkMatch("", publicMatches, none);
+ checkMatch("", publicFailures, none);
+ checkMatch("!public", publicFailures, publicMatches);
+ checkMatch("public", publicMatches, publicFailures);
+ checkMatch("public static", none, publicFailures);
+ checkMatch("public static", publicStaticMatches, publicStaticFailures);
+
+ checkMatch("private !static !strictfp", trickMatches, trickFailures);
+ checkMatch("private !static !strictfp", none, publicMatches);
+ checkMatch("private !static !strictfp", none, publicStaticMatches);
+ }
+
+ private ModifiersPattern makeModifiersPattern(String pattern) {
+ return new PatternParser(pattern).parseModifiersPattern();
+ }
+
+ private void checkMatch(String pattern, int[] shouldMatch, int[] shouldFail) {
+ ModifiersPattern p = makeModifiersPattern(pattern);
+ checkMatch(p, shouldMatch, true);
+ checkMatch(p, shouldFail, false);
+ }
+
+ private void checkMatch(ModifiersPattern p, int[] matches, boolean shouldMatch) {
+ for (int i=0; i<matches.length; i++) {
+ boolean result = p.matches(matches[i]);
+ String msg = "matches " + p + " to " + Modifier.toString(matches[i]) + " expected ";
+ if (shouldMatch) {
+ assertTrue(msg + shouldMatch, result);
+ } else {
+ assertTrue(msg + shouldMatch, !result);
+ }
+ }
+ }
+
+ public void testSerialization() throws IOException {
+ String[] patterns = new String[] {
+ "", "!public", "public", "public static",
+ "private !static !strictfp",
+ };
+
+ for (int i=0, len=patterns.length; i < len; i++) {
+ checkSerialization(patterns[i]);
+ }
+ }
+
+ /**
+ * Method checkSerialization.
+ * @param string
+ */
+ private void checkSerialization(String string) throws IOException {
+ ModifiersPattern p = makeModifiersPattern(string);
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ DataInputStream in = new DataInputStream(bi);
+ ModifiersPattern newP = ModifiersPattern.read(in);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/NamePatternParserTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/NamePatternParserTestCase.java
new file mode 100644
index 000000000..22e180250
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/NamePatternParserTestCase.java
@@ -0,0 +1,65 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.weaver.patterns.*;
+
+import junit.framework.TestCase;
+
+/**
+ * @author hugunin
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class NamePatternParserTestCase extends TestCase {
+ /**
+ * Constructor for PatternTestCase.
+ * @param name
+ */
+ public NamePatternParserTestCase(String name) {
+ super(name);
+ }
+
+ public void testMatch() {
+ checkMatch(NamePatternTestCase.matchAll);
+ checkMatch(NamePatternTestCase.match1);
+ checkMatch(NamePatternTestCase.match2);
+
+
+ NamePattern p = new PatternParser("abc *").parseNamePattern();
+ assertEquals(new NamePattern("abc"), p);
+ }
+
+ /**
+ * Method checkMatch.
+ * @param string
+ * @param matchAll
+ * @param b
+ */
+ private void checkMatch(String[] patterns) {
+ for (int i=0, len=patterns.length; i < len; i++) {
+ String pattern = patterns[i];
+ ITokenSource tokenSource = BasicTokenSource.makeTokenSource(pattern);
+ NamePattern p1 = new PatternParser(tokenSource).parseNamePattern();
+ NamePattern p2 = new NamePattern(pattern);
+ assertEquals("pattern: " + pattern, p2, p1);
+ assertEquals("eof", IToken.EOF, tokenSource.next());
+ }
+ }
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/NamePatternTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/NamePatternTestCase.java
new file mode 100644
index 000000000..3382dd4e7
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/NamePatternTestCase.java
@@ -0,0 +1,118 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import org.aspectj.weaver.patterns.*;
+
+import junit.framework.TestCase;
+
+/**
+ * @author hugunin
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class NamePatternTestCase extends TestCase {
+ static String[] matchAll = new String[] {
+ "*****",
+ "*"
+ };
+
+
+ static String[] match1 = new String[] {
+ "abcde", "abc*", "abcd*", "abcde*",
+ "*e", "*cde", "*abcde",
+ "a*e", "ab*e", "abc*de",
+ "*a*b*c*d*e*", "a*c*e", "a***bcde",
+ "*d*",
+ };
+
+ static String[] match2 = new String[] {
+ "abababab",
+ "aba*", "abab*", "abababab*",
+ "*b", "*ab", "*ababab", "*abababab",
+ "a*b", "ab*b", "abab*abab",
+ "*a*b*a*b*a*b*a*b*", "a*****b", "a**b", "ab*b*b",
+ };
+
+ /**
+ * Constructor for PatternTestCase.
+ * @param name
+ */
+ public NamePatternTestCase(String name) {
+ super(name);
+ }
+
+ public void testMatch() {
+ checkMatch("abcde", matchAll, true);
+ checkMatch("abcde", match1, true);
+ checkMatch("abcde", match2, false);
+
+ checkMatch("abababab", matchAll, true);
+ checkMatch("abababab", match1, false);
+ checkMatch("abababab", match2, true);
+
+ }
+
+ /**
+ * Method checkMatch.
+ * @param string
+ * @param matchAll
+ * @param b
+ */
+ private void checkMatch(String string, String[] patterns, boolean shouldMatch) {
+ for (int i=0, len=patterns.length; i < len; i++) {
+ NamePattern p = new NamePattern(patterns[i]);
+ checkMatch(string, p, shouldMatch);
+ }
+ }
+
+ private void checkMatch(String string, NamePattern p, boolean shouldMatch) {
+ String msg = "matching " + string + " to " + p;
+ assertEquals(msg, shouldMatch, p.matches(string));
+ }
+
+
+ public void testSerialization() throws IOException {
+ checkSerialization(matchAll);
+ checkSerialization(match1);
+ checkSerialization(match2);
+ }
+
+ private void checkSerialization(String[] patterns) throws IOException {
+ for (int i=0, len=patterns.length; i < len; i++) {
+ NamePattern p = new NamePattern(patterns[i]);
+ checkSerialization(p);
+ }
+ }
+
+
+ private void checkSerialization(NamePattern p) throws IOException {
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ DataInputStream in = new DataInputStream(bi);
+ NamePattern newP = NamePattern.read(in);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java
new file mode 100644
index 000000000..d6f17f3e9
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java
@@ -0,0 +1,70 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.util.*;
+
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.weaver.bcel.BcelShadow;
+
+import junit.framework.TestCase;
+import org.aspectj.weaver.*;
+
+/**
+ * @author hugunin
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class ParserTestCase extends TestCase {
+
+ public ParserTestCase(String arg0) {
+ super(arg0);
+ }
+
+ World world = new BcelWorld();
+
+ public void testNamePatterns() {
+
+
+// checkNoMatch("abc *", "abcd");
+// checkNoMatch("* d", "abcd");
+ }
+
+
+
+ public void testParse() {
+ PatternParser parser = new PatternParser("execution(void Hello.*(..))");
+ KindedPointcut p = (KindedPointcut) parser.parsePointcut();
+ //System.out.println(p);
+ assertEquals(p.kind, BcelShadow.MethodExecution);
+ assertTrue(p.signature.getName().matches("foobar"));
+
+
+ try {
+ new PatternParser("initialization(void foo())").parsePointcut();
+ this.fail("should have been a parse error");
+ } catch (ParserException pe) {
+ // good
+ }
+
+
+
+ }
+}
+
+
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/PatternsTests.java b/weaver/testsrc/org/aspectj/weaver/patterns/PatternsTests.java
new file mode 100644
index 000000000..e66fd3e12
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/PatternsTests.java
@@ -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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import junit.framework.*;
+
+public class PatternsTests extends TestCase {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(PatternsTests.class.getName());
+ //$JUnit-BEGIN$
+ suite.addTestSuite(AndOrNotTestCase.class);
+ suite.addTestSuite(BindingTestCase.class);
+ suite.addTestSuite(DeclareErrorOrWarningTestCase.class);
+ suite.addTestSuite(ModifiersPatternTestCase.class);
+ suite.addTestSuite(NamePatternParserTestCase.class);
+ suite.addTestSuite(NamePatternTestCase.class);
+ suite.addTestSuite(ParserTestCase.class);
+ suite.addTestSuite(SignaturePatternTestCase.class);
+ suite.addTestSuite(ThisOrTargetTestCase.class);
+ suite.addTestSuite(TypePatternListTestCase.class);
+ suite.addTestSuite(TypePatternTestCase.class);
+ suite.addTestSuite(WithinTestCase.class);
+ //$JUnit-END$
+ return suite;
+ }
+
+ public PatternsTests(String name) { super(name); }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/SignaturePatternTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/SignaturePatternTestCase.java
new file mode 100644
index 000000000..b7c8789dc
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/SignaturePatternTestCase.java
@@ -0,0 +1,175 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import junit.framework.*;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.bcel.*;
+
+public class SignaturePatternTestCase extends TestCase {
+ /**
+ * Constructor for PatternTestCase.
+ * @param name
+ */
+ public SignaturePatternTestCase(String name) {
+ super(name);
+ }
+
+ BcelWorld world = new BcelWorld();
+
+ public void testThrowsMatch() throws IOException {
+ Member onlyDerivedOnDerived = Member.methodFromString("static void fluffy.Derived.onlyDerived()");
+ Member mOnBase = Member.methodFromString("void fluffy.Base.m()");
+ Member mOnDerived = Member.methodFromString("void fluffy.Derived.m()");
+
+ checkMatch(makeMethodPat("* fluffy.Base.*(..) throws java.lang.CloneNotSupportedException"),
+ new Member[] { mOnBase },
+ new Member[] { mOnDerived });
+
+ checkMatch(makeMethodPat("* fluffy.Derived.*(..) throws java.lang.CloneNotSupportedException"),
+ new Member[] { },
+ new Member[] { mOnBase, mOnDerived });
+
+ //XXX need pattern checks
+ Member[] NONE = new Member[] {};
+ Member[] M = new Member[] { onlyDerivedOnDerived };
+ Member[] NO_EXCEPTIONS = new Member[] { mOnDerived };
+ Member[] BOTH = new Member[] {mOnDerived, onlyDerivedOnDerived};
+
+ checkMatch(makeMethodPat("* *(..)"), M, NONE);
+ checkMatch(makeMethodPat("* *(..) throws !*"), NO_EXCEPTIONS, M);
+ checkMatch(makeMethodPat("* *(..) throws *"), M, NO_EXCEPTIONS);
+ checkMatch(makeMethodPat("* *(..) throws *, !*"), NONE, BOTH);
+
+ checkMatch(makeMethodPat("* *(..) throws (!*)"), NONE, BOTH);
+ checkMatch(makeMethodPat("* *(..) throws !(!*)"), BOTH, NONE);
+
+ checkMatch(makeMethodPat("* *(..) throws *..IOException"), M, NO_EXCEPTIONS);
+ checkMatch(makeMethodPat("* *(..) throws *..IOException, *..Clone*"), M, NO_EXCEPTIONS);
+ checkMatch(makeMethodPat("* *(..) throws *..IOException, !*..Clone*"), NONE, BOTH);
+ checkMatch(makeMethodPat("* *(..) throws !*..IOException"), NO_EXCEPTIONS, M);
+ }
+
+ public void testInstanceMethodMatch() throws IOException {
+ Member objectToString = Member.methodFromString("java.lang.String java.lang.Object.toString()");
+ Member integerToString = Member.methodFromString("java.lang.String java.lang.Integer.toString()");
+ Member integerIntValue = Member.methodFromString("int java.lang.Integer.intValue()");
+ //Member objectToString = Member.methodFromString("java.lang.String java.lang.Object.toString()");
+
+ checkMatch(makeMethodPat("* java.lang.Object.*(..)"),
+ new Member[] { objectToString, integerToString },
+ new Member[] { integerIntValue });
+
+ checkMatch(makeMethodPat("* java.lang.Integer.*(..)"),
+ new Member[] { integerIntValue, integerToString },
+ new Member[] { objectToString });
+ }
+
+
+ public void testStaticMethodMatch() throws IOException {
+ Member onlyBaseOnBase = Member.methodFromString("static void fluffy.Base.onlyBase()");
+ Member onlyBaseOnDerived = Member.methodFromString("static void fluffy.Derived.onlyBase()");
+ Member onlyDerivedOnDerived = Member.methodFromString("static void fluffy.Derived.onlyDerived()");
+ Member bothOnBase = Member.methodFromString("static void fluffy.Base.both()");
+ Member bothOnDerived = Member.methodFromString("static void fluffy.Derived.both()");
+
+ checkMatch(makeMethodPat("* fluffy.Base.*(..)"),
+ new Member[] { onlyBaseOnBase, onlyBaseOnDerived, bothOnBase },
+ new Member[] { onlyDerivedOnDerived, bothOnDerived });
+
+ checkMatch(makeMethodPat("* fluffy.Derived.*(..)"),
+ new Member[] { onlyBaseOnDerived, bothOnDerived, onlyDerivedOnDerived },
+ new Member[] { onlyBaseOnBase, bothOnBase });
+ }
+
+ public void testFieldMatch() throws IOException {
+ Member onlyBaseOnBase = Member.fieldFromString("int fluffy.Base.onlyBase");
+ Member onlyBaseOnDerived = Member.fieldFromString("int fluffy.Derived.onlyBase");
+ Member onlyDerivedOnDerived = Member.fieldFromString("int fluffy.Derived.onlyDerived");
+ Member bothOnBase = Member.fieldFromString("int fluffy.Base.both");
+ Member bothOnDerived = Member.fieldFromString("int fluffy.Derived.both");
+
+ checkMatch(makeFieldPat("* fluffy.Base.*"),
+ new Member[] { onlyBaseOnBase, onlyBaseOnDerived, bothOnBase },
+ new Member[] { onlyDerivedOnDerived, bothOnDerived });
+
+ checkMatch(makeFieldPat("* fluffy.Derived.*"),
+ new Member[] { onlyBaseOnDerived, bothOnDerived, onlyDerivedOnDerived },
+ new Member[] { onlyBaseOnBase, bothOnBase });
+ }
+
+ public void testConstructorMatch() throws IOException {
+ Member onBase = Member.methodFromString("void fluffy.Base.<init>()");
+ Member onDerived = Member.methodFromString("void fluffy.Derived.<init>()");
+ Member onBaseWithInt = Member.methodFromString("void fluffy.Base.<init>(int)");
+
+
+ checkMatch(makeMethodPat("fluffy.Base.new(..)"),
+ new Member[] { onBase, onBaseWithInt },
+ new Member[] { onDerived });
+
+ checkMatch(makeMethodPat("fluffy.Derived.new(..)"),
+ new Member[] { onDerived},
+ new Member[] { onBase, onBaseWithInt });
+ }
+
+
+
+
+
+ public void checkMatch(SignaturePattern p, Member[] yes, Member[] no) throws IOException {
+ p = p.resolveBindings(new TestScope(world, new FormalBinding[0]), new Bindings(0));
+
+ for (int i=0; i < yes.length; i++) {
+ checkMatch(p, yes[i], true);
+ }
+
+ for (int i=0; i < no.length; i++) {
+ checkMatch(p, no[i], false);
+ }
+
+ checkSerialization(p);
+ }
+
+ private void checkMatch(SignaturePattern p, Member member, boolean b) {
+ boolean matches = p.matches(member, world);
+ assertEquals(p.toString() + " matches " + member.toString(), b, matches);
+ }
+
+
+ private SignaturePattern makeMethodPat(String pattern) {
+ return new PatternParser(pattern).parseMethodOrConstructorSignaturePattern();
+ }
+
+ private SignaturePattern makeFieldPat(String pattern) {
+ return new PatternParser(pattern).parseFieldSignaturePattern();
+ }
+
+ private void checkSerialization(SignaturePattern p) throws IOException {
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ DataInputStream in = new DataInputStream(bi);
+ SignaturePattern newP = SignaturePattern.read(in, null);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/TestScope.java b/weaver/testsrc/org/aspectj/weaver/patterns/TestScope.java
new file mode 100644
index 000000000..d18f8f63c
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/TestScope.java
@@ -0,0 +1,30 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.*;
+
+public class TestScope extends SimpleScope {
+
+ public TestScope(
+ World world,
+ FormalBinding[] bindings)
+ {
+ super(world, bindings);
+ }
+
+ public TestScope(String[] formalTypes, String[] formalNames, World world) {
+ super(world, SimpleScope.makeFormalBindings(TypeX.forNames(formalTypes), formalNames));
+ }
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/ThisOrTargetTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/ThisOrTargetTestCase.java
new file mode 100644
index 000000000..9fd2a9e07
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/ThisOrTargetTestCase.java
@@ -0,0 +1,102 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.lang.reflect.*;
+
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.util.FuzzyBoolean;
+
+import junit.framework.TestCase;
+import org.aspectj.weaver.*;
+
+/**
+ * @author hugunin
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class ThisOrTargetTestCase extends TestCase {
+ /**
+ * Constructor for PatternTestCase.
+ * @param name
+ */
+ public ThisOrTargetTestCase(String name) {
+ super(name);
+ }
+
+ World world;
+
+
+ public void testMatch() throws IOException {
+ world = new BcelWorld();
+
+
+
+ }
+
+ private Pointcut makePointcut(String pattern) {
+ return new PatternParser(pattern).parsePointcut();
+ }
+
+ private void checkEquals(String pattern, Pointcut p) throws IOException {
+ assertEquals(pattern, p, makePointcut(pattern));
+ checkSerialization(pattern);
+ }
+
+
+// private void checkMatch(Pointcut p, Signature[] matches, boolean shouldMatch) {
+// for (int i=0; i<matches.length; i++) {
+// boolean result = p.matches(matches[i]);
+// String msg = "matches " + p + " to " + matches[i] + " expected ";
+// if (shouldMatch) {
+// assertTrue(msg + shouldMatch, result);
+// } else {
+// assertTrue(msg + shouldMatch, !result);
+// }
+// }
+// }
+//
+// public void testSerialization() throws IOException {
+// String[] patterns = new String[] {
+// "public * *(..)", "void *.foo(A, B)", "A b()"
+// };
+//
+// for (int i=0, len=patterns.length; i < len; i++) {
+// checkSerialization(patterns[i]);
+// }
+// }
+
+ /**
+ * Method checkSerialization.
+ * @param string
+ */
+ private void checkSerialization(String string) throws IOException {
+ Pointcut p = makePointcut(string);
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ DataInputStream in = new DataInputStream(bi);
+ Pointcut newP = Pointcut.read(in, null);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/TypePatternListTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/TypePatternListTestCase.java
new file mode 100644
index 000000000..e756d11f4
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/TypePatternListTestCase.java
@@ -0,0 +1,190 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.util.Arrays;
+
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.util.*;
+
+import junit.framework.TestCase;
+import org.aspectj.weaver.*;
+
+/**
+ * @author hugunin
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class TypePatternListTestCase extends TestCase {
+ /**
+ * Constructor for PatternTestCase.
+ * @param name
+ */
+ public TypePatternListTestCase(String name) {
+ super(name);
+ }
+
+ World world;
+
+ //XXX when instanceof matching works add tests for that here
+
+
+ public void testMatch() {
+ world = new BcelWorld();
+
+ checkStaticMatch("()", new String[] {}, FuzzyBoolean.YES);
+ checkStaticMatch("()", new String[] {"java.lang.Object"}, FuzzyBoolean.NO);
+
+ checkStaticMatch("(java.lang.Object)", new String[] {"java.lang.Object"}, FuzzyBoolean.YES);
+
+ checkStaticMatch("(java.lang.String)", new String[] {"java.lang.Object"}, FuzzyBoolean.NO);
+
+ checkStaticMatch("(java.lang.Object)", new String[] {"java.lang.String"}, FuzzyBoolean.NO);
+
+ checkStaticMatch("()", new String[] {"java.lang.Object"}, FuzzyBoolean.NO);
+
+ checkStaticMatch("(..)", new String[] {}, FuzzyBoolean.YES);
+ checkStaticMatch("(..)", new String[] {"int", "char"}, FuzzyBoolean.YES);
+
+
+ checkStaticMatch("(int,..,int)", new String[] {"int", "int"}, FuzzyBoolean.YES);
+
+ checkStaticMatch("(int,..)", new String[] {}, FuzzyBoolean.NO);
+ checkStaticMatch("(int,..)", new String[] {"int"}, FuzzyBoolean.YES);
+
+ checkStaticMatch("(..,int,..)", new String[] {"int"}, FuzzyBoolean.YES);
+
+ // these checks are taken from new/ExpandedDotPattern.java
+ stupidCheck("( .., .., ..)", new boolean[] { true, true, true, true, true });
+ stupidCheck("( .., .., int)", new boolean[] { false, true, true, true, true });
+ stupidCheck("( .., int, ..)", new boolean[] { false, true, true, true, true });
+ stupidCheck("( .., int, int)", new boolean[] { false, false, true, true, true });
+ stupidCheck("(int, .., ..)", new boolean[] { false, true, true, true, true });
+ stupidCheck("(int, .., int)", new boolean[] { false, false, true, true, true });
+ stupidCheck("(int, int, ..)", new boolean[] { false, false, true, true, true });
+ stupidCheck("(int, int, int)", new boolean[] { false, false, false, true, false });
+
+ stupidCheck("( .., .., .., ..)", new boolean[] { true, true, true, true, true });
+ stupidCheck("( .., .., .., int)", new boolean[] { false, true, true, true, true });
+ stupidCheck("( .., .., int, ..)", new boolean[] { false, true, true, true, true });
+ stupidCheck("( .., .., int, int)", new boolean[] { false, false, true, true, true });
+ stupidCheck("( .., int, .., ..)", new boolean[] { false, true, true, true, true });
+ stupidCheck("( .., int, .., int)", new boolean[] { false, false, true, true, true });
+ stupidCheck("( .., int, int, ..)", new boolean[] { false, false, true, true, true });
+ stupidCheck("( .., int, int, int)", new boolean[] { false, false, false, true, true });
+
+ stupidCheck("(int, .., .., ..)", new boolean[] { false, true, true, true, true });
+ stupidCheck("(int, .., .., int)", new boolean[] { false, false, true, true, true });
+ stupidCheck("(int, .., int, ..)", new boolean[] { false, false, true, true, true });
+ stupidCheck("(int, .., int, int)", new boolean[] { false, false, false, true, true });
+ stupidCheck("(int, int, .., ..)", new boolean[] { false, false, true, true, true });
+ stupidCheck("(int, int, .., int)", new boolean[] { false, false, false, true, true });
+ stupidCheck("(int, int, int, ..)", new boolean[] { false, false, false, true, true });
+ stupidCheck("(int, int, int, int)", new boolean[] { false, false, false, false, true });
+ }
+
+ private TypePatternList makeArgumentsPattern(String pattern) {
+ return new PatternParser(pattern).parseArgumentsPattern();
+ }
+
+ private void checkStaticMatch(String pattern, String[] names,
+ FuzzyBoolean shouldMatchStatically) {
+ // We're only doing TypePattern.STATIC matching here because my intent was
+ // to test the wildcarding, and we don't do DYNAMIC matching on wildcarded things.
+
+ TypePatternList p = makeArgumentsPattern(pattern);
+ ResolvedTypeX[] types = new ResolvedTypeX[names.length];
+ for (int i = 0; i < names.length; i++) {
+ types[i] = world.resolve(names[i]);
+ }
+
+ p.resolveBindings(makeTestScope(), Bindings.NONE, false);
+ //System.out.println("type: " + type);
+ FuzzyBoolean result = p.matches(types, TypePattern.STATIC);
+ String msg = "matches statically " + pattern + " to " + Arrays.asList(types);
+ assertEquals(msg, shouldMatchStatically, result);
+ }
+
+ private TestScope makeTestScope() {
+ TestScope scope = new TestScope(CollectionUtil.NO_STRINGS, CollectionUtil.NO_STRINGS, world);
+ return scope;
+ }
+
+ public void stupidCheck(String pattern, boolean[] matches) {
+ TypePatternList p = makeArgumentsPattern(pattern);
+ p.resolveBindings(makeTestScope(), Bindings.NONE, false);
+
+ int len = matches.length;
+
+ for (int j = 0; j < len; j++) {
+
+ ResolvedTypeX[] types = new ResolvedTypeX[j];
+ for (int i = 0; i < j; i++) {
+ types[i] = world.resolve("int");
+ }
+
+ FuzzyBoolean result = p.matches(types, TypePattern.STATIC);
+ String msg = "matches statically " + pattern + " to " + Arrays.asList(types);
+ assertEquals(msg, FuzzyBoolean.fromBoolean(matches[j]), result);
+ }
+ }
+
+ public void testSerialization() throws IOException {
+ String[] patterns = new String[] {
+ "( .., .., .., int)",
+ "( .., .., int, ..)",
+ "( .., .., int, int)",
+ "( .., int, .., ..)",
+ "( .., int, .., int)",
+ "( .., int, int, ..)",
+ "( .., int, int, int)",
+
+ "(int, .., .., ..)",
+ "(int, .., .., int)",
+ "(int, .., int, ..)",
+ "(int, .., int, int)",
+ "(int, int, .., ..)",
+ "(int, int, .., int)",
+ "(int, int, int, ..)",
+ "(int, int, int, int)"
+ };
+
+ for (int i=0, len=patterns.length; i < len; i++) {
+ checkSerialization(patterns[i]);
+ }
+ }
+
+ /**
+ * Method checkSerialization.
+ * @param string
+ */
+ private void checkSerialization(String string) throws IOException {
+ TypePatternList p = makeArgumentsPattern(string);
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ DataInputStream in = new DataInputStream(bi);
+ TypePatternList newP = TypePatternList.read(in, null);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/TypePatternTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/TypePatternTestCase.java
new file mode 100644
index 000000000..5b3c702e8
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/TypePatternTestCase.java
@@ -0,0 +1,290 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+import java.util.*;
+
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.bridge.AbortException;
+import org.aspectj.util.FuzzyBoolean;
+
+import junit.framework.TestCase;
+import org.aspectj.weaver.*;
+
+public class TypePatternTestCase extends TestCase {
+ /**
+ * Constructor for PatternTestCase.
+ * @param name
+ */
+ public TypePatternTestCase(String name) {
+ super(name);
+ }
+
+ World world;
+
+ public void testStaticMatch() {
+ world = new BcelWorld();
+
+ checkMatch("java.lang.Object", "java.lang.Object", true);
+ checkMatch("java.lang.Object+", "java.lang.Object", true);
+ checkMatch("java.lang.Object+", "java.lang.String", true);
+ checkMatch("java.lang.String+", "java.lang.Object", false);
+ checkMatch("java.lang.Integer", "java.lang.String", false);
+
+ checkMatch("java.lang.Integer", "int", false);
+
+ checkMatch("java.lang.Number+", "java.lang.Integer", true);
+
+
+ checkMatch("java..*", "java.lang.Integer", true);
+ checkMatch("java..*", "java.lang.reflect.Modifier", true);
+ checkMatch("java..*", "int", false);
+ checkMatch("java..*", "javax.swing.Action", false);
+ checkMatch("java..*+", "javax.swing.Action", true);
+
+ checkMatch("*.*.Object", "java.lang.Object", true);
+ checkMatch("*.Object", "java.lang.Object", false);
+ checkMatch("*..*", "java.lang.Object", true);
+ checkMatch("*..*", "int", false);
+ checkMatch("java..Modifier", "java.lang.reflect.Modifier", true);
+ checkMatch("java.lang.reflect.Mod..ifier", "java.lang.reflect.Modifier", false);
+
+ checkMatch("java..reflect..Modifier", "java.lang.reflect.Modifier", true);
+ checkMatch("java..lang..Modifier", "java.lang.reflect.Modifier", true);
+ checkMatch("java..*..Modifier", "java.lang.reflect.Modifier", true);
+ checkMatch("java..*..*..Modifier", "java.lang.reflect.Modifier", true);
+ checkMatch("java..*..*..*..Modifier", "java.lang.reflect.Modifier", false);
+ //checkMatch("java..reflect..Modifier", "java.lang.reflect.Modxifier", false);
+ checkMatch("ja*va..Modifier", "java.lang.reflect.Modifier", true);
+ checkMatch("java..*..Mod*ifier", "java.lang.reflect.Modifier", true);
+
+ }
+
+
+ // three levels:
+ // 0. defined in current compilation unit, or imported by name
+ // 1. defined in current package/type/whatever
+ // 2. defined in package imported by *
+ /**
+ * We've decided not to test this here, but rather in any compilers
+ */
+ public void testImportResolve() {
+ world = new BcelWorld();
+// checkIllegalImportResolution("List", new String[] { "java.util", "java.awt", },
+// ZERO_STRINGS);
+
+
+ }
+
+
+ // Assumption for bcweaver: Already resolved type patterns with no *s or ..'s into exact type
+ // patterns. Exact type patterns don't have import lists. non-exact-type pattens don't
+ // care about precedence, so the current package can be included with all the other packages,
+ // and we don't care about compilation units, and we don't care about ordering.
+
+ // only giving this wild-type patterns
+ public void testImportMatch() {
+ world = new BcelWorld();
+
+ checkImportMatch("*List", new String[] { "java.awt.", }, ZERO_STRINGS, "java.awt.List", true);
+ checkImportMatch("*List", new String[] { "java.awt.", }, ZERO_STRINGS, "java.awt.List", true);
+ checkImportMatch("*List", new String[] { "java.awt.", }, ZERO_STRINGS, "java.util.List", false);
+ checkImportMatch("*List", new String[] { "java.util.", }, ZERO_STRINGS, "java.awt.List", false);
+ checkImportMatch("*List", new String[] { "java.util.", }, ZERO_STRINGS, "java.util.List", true);
+
+ checkImportMatch("*List", ZERO_STRINGS, new String[] { "java.awt.List", }, "java.awt.List", true);
+
+ checkImportMatch("awt.*List", ZERO_STRINGS, new String[] { "java.awt.List", }, "java.awt.List", false);
+ checkImportMatch("*Foo", ZERO_STRINGS, new String[] { "java.awt.List", }, "java.awt.List", false);
+
+ checkImportMatch("*List", new String[] { "java.util.", "java.awt.", },
+ ZERO_STRINGS, "java.util.List", true);
+ checkImportMatch("*List", new String[] { "java.util.", "java.awt.", },
+ ZERO_STRINGS, "java.awt.List", true);
+
+ checkImportMatch("*..List", new String[] { "java.util." }, ZERO_STRINGS, "java.util.List", true);
+ checkImportMatch("*..List", new String[] { "java.util." }, ZERO_STRINGS, "java.awt.List", true);
+
+ }
+
+ public void testImportMatchWithInners() {
+ world = new BcelWorld();
+ checkImportMatch("*Entry", new String[] { "java.util.", "java.util.Map$"}, ZERO_STRINGS,
+ "java.util.Map$Entry", true);
+
+ checkImportMatch("java.util.Map.*Entry", ZERO_STRINGS, ZERO_STRINGS,
+ "java.util.Map$Entry", true);
+
+ checkImportMatch("*Entry", new String[] { "java.util.", }, ZERO_STRINGS,
+ "java.util.Map$Entry", false);
+
+ checkImportMatch("*.Entry", new String[] { "java.util.", }, ZERO_STRINGS,
+ "java.util.Map$Entry", true);
+
+ checkImportMatch("Map.*", new String[] { "java.util.", }, ZERO_STRINGS,
+ "java.util.Map$Entry", true);
+
+ checkImportMatch("Map.*", ZERO_STRINGS, new String[] { "java.util.Map" },
+ "java.util.Map$Entry", true);
+ }
+
+ private void checkImportMatch(
+ String wildPattern,
+ String[] importedPackages,
+ String[] importedNames,
+ String matchName,
+ boolean shouldMatch)
+ {
+ WildTypePattern p = makeResolvedWildTypePattern(wildPattern, importedPackages, importedNames);
+ checkPatternMatch(p, matchName, shouldMatch);
+ }
+
+
+ private WildTypePattern makeResolvedWildTypePattern(
+ String wildPattern,
+ String[] importedPackages,
+ String[] importedNames)
+ {
+ WildTypePattern unresolved = (WildTypePattern) new PatternParser(wildPattern).parseTypePattern();
+
+ WildTypePattern resolved = resolve(unresolved, importedPackages, importedNames);
+ return resolved;
+
+ }
+
+ private WildTypePattern resolve(
+ WildTypePattern unresolved,
+ String[] importedPrefixes,
+ String[] importedNames)
+ {
+
+ TestScope scope = makeTestScope();
+ scope.setImportedPrefixes(importedPrefixes);
+ scope.setImportedNames(importedNames);
+ return (WildTypePattern) unresolved.resolveBindings(scope, Bindings.NONE, false);
+ }
+
+
+
+ public static final String[] ZERO_STRINGS = new String[0];
+
+ public void testInstanceofMatch() {
+ world = new BcelWorld();
+
+ checkInstanceofMatch("java.lang.Object", "java.lang.Object", FuzzyBoolean.YES);
+
+ checkIllegalInstanceofMatch("java.lang.Object+", "java.lang.Object");
+ checkIllegalInstanceofMatch("java.lang.Object+", "java.lang.String");
+ checkIllegalInstanceofMatch("java.lang.String+", "java.lang.Object");
+ checkIllegalInstanceofMatch("java.lang.*", "java.lang.Object");
+ checkInstanceofMatch("java.lang.Integer", "java.lang.String", FuzzyBoolean.NO);
+
+ checkInstanceofMatch("java.lang.Number", "java.lang.Integer", FuzzyBoolean.YES);
+ checkInstanceofMatch("java.lang.Integer", "java.lang.Number", FuzzyBoolean.MAYBE);
+
+
+ checkIllegalInstanceofMatch("java..Integer", "java.lang.Integer");
+
+
+ checkInstanceofMatch("*", "java.lang.Integer", FuzzyBoolean.YES);
+
+
+ }
+
+ private void checkIllegalInstanceofMatch(String pattern, String name) {
+ try {
+ TypePattern p = makeTypePattern(pattern);
+ ResolvedTypeX type = world.resolve(name);
+ FuzzyBoolean result = p.matchesInstanceof(type);
+ } catch (AbortException e) {
+ return;
+ }
+ assertTrue("matching " + pattern + " with " + name + " should fail", false);
+ }
+
+ private void checkInstanceofMatch(String pattern, String name, FuzzyBoolean shouldMatch) {
+ TypePattern p = makeTypePattern(pattern);
+ ResolvedTypeX type = world.resolve(name);
+
+ p = p.resolveBindings(makeTestScope(), null, false);
+
+
+ //System.out.println("type: " + p);
+ FuzzyBoolean result = p.matchesInstanceof(type);
+ String msg = "matches " + pattern + " to " + type;
+ assertEquals(msg, shouldMatch, result);
+ }
+
+ private TestScope makeTestScope() {
+ TestScope scope = new TestScope(ZERO_STRINGS, ZERO_STRINGS, world);
+ return scope;
+ }
+
+ private TypePattern makeTypePattern(String pattern) {
+ return new PatternParser(pattern).parseSingleTypePattern();
+ }
+
+ private void checkMatch(String pattern, String name, boolean shouldMatch) {
+ TypePattern p = makeTypePattern(pattern);
+ p = p.resolveBindings(makeTestScope(), null, false);
+ checkPatternMatch(p, name, shouldMatch);
+ }
+
+ private void checkPatternMatch(
+ TypePattern p,
+ String name,
+ boolean shouldMatch)
+ {
+ ResolvedTypeX type = world.resolve(name);
+ //System.out.println("type: " + type);
+ boolean result = p.matchesStatically(type);
+ String msg = "matches " + p + " to " + type + " expected ";
+ if (shouldMatch) {
+ assertTrue(msg + shouldMatch, result);
+ } else {
+ assertTrue(msg + shouldMatch, !result);
+ }
+ }
+
+ public void testSerialization() throws IOException {
+ String[] patterns = new String[] {
+ "java.lang.Object", "java.lang.Object+", "java.lang.Integer",
+ "int", "java..*", "java..util..*", "*.*.Object", "*",
+ };
+
+ for (int i=0, len=patterns.length; i < len; i++) {
+ checkSerialization(patterns[i]);
+ }
+ }
+
+ /**
+ * Method checkSerialization.
+ * @param string
+ */
+ private void checkSerialization(String string) throws IOException {
+ TypePattern p = makeTypePattern(string);
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ DataInputStream in = new DataInputStream(bi);
+ TypePattern newP = TypePattern.read(in, null);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/WithinTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/WithinTestCase.java
new file mode 100644
index 000000000..4d8fef75b
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/WithinTestCase.java
@@ -0,0 +1,102 @@
+/* *******************************************************************
+ * 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 Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.*;
+
+import junit.framework.TestCase;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.bcel.*;
+import org.aspectj.weaver.bcel.BcelWorld;
+import org.aspectj.util.FuzzyBoolean;
+
+public class WithinTestCase extends TestCase {
+
+ World world = new BcelWorld();
+
+ public WithinTestCase(String name) {
+ super(name);
+ }
+
+ public void testMatch() throws IOException {
+ Shadow getOutFromArrayList = new TestShadow(
+ Shadow.FieldGet,
+ Member.fieldFromString("java.io.PrintStream java.lang.System.out"),
+ TypeX.forName("java.util.ArrayList"),
+ world);
+
+ checkMatch(makePointcut("within(*)"), getOutFromArrayList, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util.*)"), getOutFromArrayList, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.lang.*)"), getOutFromArrayList, FuzzyBoolean.NO);
+ checkMatch(makePointcut("within(java.util.List+)"), getOutFromArrayList, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.uti*.List+)"), getOutFromArrayList, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.uti*..*)"), getOutFromArrayList, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util.*List)"), getOutFromArrayList, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util.List*)"), getOutFromArrayList, FuzzyBoolean.NO);
+
+
+ Shadow getOutFromEntry = new TestShadow(
+ Shadow.FieldGet,
+ Member.fieldFromString("java.io.PrintStream java.lang.System.out"),
+ TypeX.forName("java.util.Map$Entry"),
+ world);
+
+ checkMatch(makePointcut("within(*)"), getOutFromEntry, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util.*)"), getOutFromEntry, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util.Map.*)"), getOutFromEntry, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util..*)"), getOutFromEntry, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util.Map..*)"), getOutFromEntry, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.lang.*)"), getOutFromEntry, FuzzyBoolean.NO);
+ checkMatch(makePointcut("within(java.util.List+)"), getOutFromEntry, FuzzyBoolean.NO);
+ checkMatch(makePointcut("within(java.util.Map+)"), getOutFromEntry, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.lang.Object+)"), getOutFromEntry, FuzzyBoolean.YES);
+
+ //this is something we should in type patterns tests
+ //checkMatch(makePointcut("within(*List)"), getOut, FuzzyBoolean.NO);
+
+ }
+
+ public Pointcut makePointcut(String pattern) {
+ Pointcut pointcut0 = Pointcut.fromString(pattern);
+
+ Bindings bindingTable = new Bindings(0);
+ IScope scope = new SimpleScope(world, FormalBinding.NONE);
+
+ pointcut0.resolveBindings(scope, bindingTable);
+ Pointcut pointcut1 = pointcut0;
+ return pointcut1.concretize1(null, new IntMap());
+ }
+
+
+ private void checkMatch(Pointcut p, Shadow s, FuzzyBoolean shouldMatch) throws IOException {
+ FuzzyBoolean doesMatch = p.match(s);
+ assertEquals(p + " matches " + s, shouldMatch, doesMatch);
+ checkSerialization(p);
+ }
+
+ private void checkSerialization(Pointcut p) throws IOException {
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ DataInputStream in = new DataInputStream(bi);
+ Pointcut newP = Pointcut.read(in, null);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}