1
16
17 import org.as2lib.core.BasicClass;
18 import org.as2lib.aop.Weaver;
19 import org.as2lib.env.overload.Overload;
20 import org.as2lib.aop.Aspect;
21 import org.as2lib.env.reflect.PackageInfo;
22 import org.as2lib.env.reflect.ClassInfo;
23 import org.as2lib.env.reflect.PropertyInfo;
24 import org.as2lib.env.reflect.TypeMemberInfo;
25 import org.as2lib.aop.JoinPoint;
26 import org.as2lib.aop.joinpoint.MethodJoinPoint;
27 import org.as2lib.aop.joinpoint.GetPropertyJoinPoint;
28 import org.as2lib.aop.joinpoint.SetPropertyJoinPoint;
29 import org.as2lib.aop.Advice;
30 import org.as2lib.data.holder.map.HashMap;
31 import org.as2lib.data.holder.Map;
32 import org.as2lib.env.reflect.MethodInfo;
33 import org.as2lib.env.reflect.ConstructorInfo;
34 import org.as2lib.aop.joinpoint.ConstructorJoinPoint;
35 import org.as2lib.aop.joinpoint.AbstractJoinPoint;
36 import org.as2lib.util.ArrayUtil;
37
38
44 class org.as2lib.aop.weaver.SimpleWeaver extends BasicClass implements Weaver {
45
46
47 private var advices:Map;
48
49
52 public function SimpleWeaver(Void) {
53 advices = new HashMap();
54 }
55
56
59 public function weave(Void):Void {
60 var affectedTypes:Array = advices.getKeys();
61 for (var i:Number = 0; i < affectedTypes.length; i++) {
62 var affectedType:ClassInfo = affectedTypes[i];
63 var affectedAdvices:Array = advices.get(affectedType);
64 if (affectedType) {
65 weaveByTypeAndAdvices(affectedType, affectedAdvices);
66 } else {
67 weaveByPackageAndAdvices(PackageInfo.getRootPackage(), affectedAdvices);
68 }
69 }
70 }
71
72 private function weaveByPackageAndAdvices(package:PackageInfo, advices:Array):Void {
73 if (package) {
74 if (advices) {
75 var classes:Array = package.getMemberClasses(false);
76 if (classes) {
77 for (var i:Number = 0; i < classes.length; i++) {
78 var clazz:ClassInfo = ClassInfo(classes[i]);
79 if (clazz) {
80 weaveByTypeAndAdvices(clazz, advices);
81 }
82 }
83 }
84 }
85 }
86 }
87
88 private function weaveByTypeAndAdvices(type:ClassInfo, advices:Array):Void {
89 if (type) {
90 var constructor:ConstructorInfo = type.getConstructor();
91 if (constructor) {
92 weaveByJoinPointAndAdvices(new ConstructorJoinPoint(constructor, null), advices);
93 }
94 var prototype:Object = type.getType().prototype;
95 if (prototype.__constructor__) {
96
97 var superClassConstructor:ConstructorInfo = new ConstructorInfo(ClassInfo(type.getSuperType()), Function(type.getSuperType().getType().valueOf()));
98
99
100 prototype.__constructor__ = superClassConstructor.getMethod();
101 if (this.advices.containsKey(superClassConstructor.getDeclaringType())) {
102 weaveSuperClassConstructor(new ConstructorJoinPoint(superClassConstructor, null), prototype, this.advices.get(superClassConstructor.getDeclaringType()));
103
104 }
105 }
106 var methods:Array = type.getMethodsByFlag(true);
107 if (methods) {
108 for (var i:Number = 0; i < methods.length; i++) {
109 var method:MethodInfo = MethodInfo(methods[i]);
110 if (method) {
111 weaveByJoinPointAndAdvices(new MethodJoinPoint(method, null), advices);
112 }
113 }
114 }
115 var properties:Array = type.getPropertiesByFlag(true);
116 if (properties) {
117 for (var i:Number = 0; i < properties.length; i++) {
118 var property:PropertyInfo = PropertyInfo(properties[i]);
119 if (property) {
120 weaveByJoinPointAndAdvices(new GetPropertyJoinPoint(property, null), advices);
121 weaveByJoinPointAndAdvices(new SetPropertyJoinPoint(property, null), advices);
122 }
123 }
124 }
125 }
126 }
127
128 private function weaveSuperClassConstructor(superClassConstructorJoinPoint:ConstructorJoinPoint, prototype, advices:Array):Void {
129 if (prototype && advices) {
130 for (var i:Number = 0; i < advices.length; i++) {
131 var advice:Advice = Advice(advices[i]);
132 if (advice) {
133 if (advice.captures(superClassConstructorJoinPoint)) {
134
135
136 var c:ConstructorInfo = new ConstructorInfo(ClassInfo(superClassConstructorJoinPoint.getInfo().getDeclaringType()), prototype.__constructor__);
137 prototype.__constructor__ = advice.getProxy(new ConstructorJoinPoint(c, null));
138 }
139 }
140 }
141 }
142 }
143
144 private function weaveByJoinPointAndAdvices(joinPoint:JoinPoint, advices:Array):Void {
145 if (joinPoint) {
146 if (advices) {
147 for (var i:Number = 0; i < advices.length; i++) {
148 var advice:Advice = Advice(advices[i]);
149 if (advice) {
150 if (advice.captures(joinPoint)) {
151 weaveByJoinPointAndAdvice(joinPoint.snapshot(), advice);
152 }
153 }
154 }
155 }
156 }
157 }
158
159 private function weaveByJoinPointAndAdvice(joinPoint:JoinPoint, advice:Advice):Void {
160 var proxy:Function = advice.getProxy(joinPoint);
161 var info:TypeMemberInfo = joinPoint.getInfo();
162 if (joinPoint.getType() == AbstractJoinPoint.CONSTRUCTOR) {
163 info.getDeclaringType().getPackage().getPackage()[info.getDeclaringType().getName()] = proxy;
164 } else {
165 if (info.isStatic()) {
166 info.getDeclaringType().getType()[info.getName()] = proxy;
167 } else {
168 info.getDeclaringType().getType().prototype[info.getName()] = proxy;
169 }
170 }
171 }
172
173
179 public function addAspect():Void {
180 var o:Overload = new Overload(this);
181 o.addHandler([Aspect], addAspectForAllTypes);
182 o.addHandler([Aspect, Object], addAspectForAllTypesInPackage);
183 o.addHandler([Aspect, Array], addAspectForMultipleAffectedTypes);
184 o.addHandler([Aspect, Function], addAspectForOneAffectedType);
185 o.forward(arguments);
186 }
187
188
195 public function addAspectForAllTypes(aspect:Aspect):Void {
196 if (aspect) {
197 addAspectForAllTypesInPackage(aspect, PackageInfo.getRootPackage());
198 }
199 }
200
201
211 public function addAspectForAllTypesInPackage(aspect:Aspect, affectedPackage:Object):Void {
212 if (aspect) {
213 if (affectedPackage !== null && affectedPackage !== undefined) {
214 var packageInfo:PackageInfo = PackageInfo.forPackage(affectedPackage);
215 if (packageInfo) {
216 var classes:Array = packageInfo.getMemberClasses(false);
217 for (var i:Number = 0; i < classes.length; i++) {
218 var clazz:ClassInfo = ClassInfo(classes[i]);
219 if (clazz) {
220 addAspectForOneAffectedType(aspect, clazz.getType());
221 }
222 }
223 }
224 }
225 }
226 }
227
228
236 public function addAspectForMultipleAffectedTypes(aspect:Aspect, affectedTypes:Array):Void {
237 if (aspect) {
238 if (affectedTypes) {
239 for (var i:Number = 0; i < affectedTypes.length; i++) {
240 var affectedType:Function = Function(affectedTypes[i]);
241 if (affectedType) {
242 addAspectForOneAffectedType(aspect, affectedType);
243 }
244 }
245 }
246 }
247 }
248
249
257 public function addAspectForOneAffectedType(aspect:Aspect, affectedType:Function):Void {
258 if (aspect) {
259 if (affectedType) {
260 var advices:Array = aspect.getAdvices();
261 if (advices) {
262 for (var i:Number = 0; i < advices.length; i++) {
263 var advice:Advice = Advice(advices[i]);
264 if (advice) {
265 addAdviceForOneAffectedType(advice, affectedType);
266 }
267 }
268 }
269 }
270 }
271 }
272
273
279 public function addAdvice():Void {
280 var o:Overload = new Overload(this);
281 o.addHandler([Advice], addAdviceForAllTypes);
282 o.addHandler([Advice, Object], addAdviceForAllTypesInPackage);
283 o.addHandler([Advice, Array], addAdviceForMultipleAffectedTypes);
284 o.addHandler([Advice, Function], addAdviceForOneAffectedType);
285 o.forward(arguments);
286 }
287
288
295 public function addAdviceForAllTypes(advice:Advice):Void {
296 if (advice) {
297 addAdviceForAllTypesInPackage(advice, PackageInfo.getRootPackage());
298 }
299 }
300
301
309 public function addAdviceForAllTypesInPackage(advice:Advice, package:Object):Void {
310 if (advice) {
311 if (package !== null && package !== undefined) {
312 var packageInfo:PackageInfo = PackageInfo.forPackage(package);
313 if (packageInfo) {
314 var classes:Array = packageInfo.getMemberClasses(false);
315 for (var i:Number = 0; i < classes.length; i++) {
316 var clazz:ClassInfo = ClassInfo(classes[i]);
317 if (clazz) {
318 addAdviceForOneAffectedType(advice, clazz.getType());
319 }
320 }
321 }
322 }
323 }
324 }
325
326
334 public function addAdviceForMultipleAffectedTypes(advice:Advice, affectedTypes:Array):Void {
335 if (advice) {
336 if (affectedTypes) {
337 for (var i:Number = 0; i < affectedTypes.length; i++) {
338 var affectedType:Function = Function(affectedTypes[i]);
339 if (affectedType) {
340 addAdviceForOneAffectedType(advice, affectedType);
341 }
342 }
343 }
344 }
345 }
346
347
355 public function addAdviceForOneAffectedType(advice:Advice, affectedType:Function):Void {
356 if (advice) {
357 var typeInfo:ClassInfo = null;
358 if (affectedType) {
359 typeInfo = ClassInfo.forClass(affectedType);
360 }
361 if (!advices.containsKey(typeInfo)) {
362 advices.put(typeInfo, new Array());
363 }
364 var affectedAdvices:Array = advices.get(typeInfo);
365
366 if (!ArrayUtil.contains(affectedAdvices, advice)) {
367 affectedAdvices.push(advice);
368 }
369 if (typeInfo.getSuperType()) {
370 addAdviceForOneAffectedType(advice, typeInfo.getSuperType().getType());
371 }
372 }
373 }
374
375 }