KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > definition > SystemDefinition


1 /**************************************************************************************
2  * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
3  * http://aspectwerkz.codehaus.org *
4  * ---------------------------------------------------------------------------------- *
5  * The software in this package is published under the terms of the LGPL license *
6  * a copy of which has been included with this distribution in the license.txt file. *
7  **************************************************************************************/

8 package org.codehaus.aspectwerkz.definition;
9
10 import org.codehaus.aspectwerkz.expression.ExpressionContext;
11 import org.codehaus.aspectwerkz.expression.ExpressionInfo;
12 import org.codehaus.aspectwerkz.expression.ExpressionVisitor;
13 import org.codehaus.aspectwerkz.util.SequencedHashMap;
14 import org.codehaus.aspectwerkz.transform.AspectWerkzPreProcessor;
15 import org.codehaus.aspectwerkz.cflow.CflowBinding;
16
17 import java.util.ArrayList JavaDoc;
18 import java.util.Collection JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.HashSet JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.Set JavaDoc;
25
26 /**
27  * TODO clean up - remove methods not used, refactor etc.
28  * <p/>
29  * Abstraction of the system definition, defines the aspect system.
30  *
31  * @author <a HREF="mailto:jboner@codehaus.org">Jonas BonŽr </a>
32  * @author <a HREF="mailto:alex@gnilux.com">Alexandre Vasseur </a>
33  */

34 public class SystemDefinition {
35
36     /**
37      * Empty hash map.
38      */

39     public static final Map EMPTY_HASH_MAP = new HashMap();
40
41     /**
42      * Maps the aspects to it's name.
43      */

44     private final Map m_aspectMap = new SequencedHashMap();
45
46     /**
47      * Maps the mixins to it's name.
48      */

49     private final Map m_mixinMap = new SequencedHashMap();
50
51     /**
52      * The UUID for this definition.
53      */

54     private String JavaDoc m_uuid = "default";
55
56     /**
57      * The include packages.
58      */

59     private final Set JavaDoc m_includePackages = new HashSet JavaDoc();
60
61     /**
62      * The exclude packages.
63      */

64     private final Set JavaDoc m_excludePackages = new HashSet JavaDoc();
65
66     /**
67      * The prepare packages.
68      */

69     private final Set JavaDoc m_preparePackages = new HashSet JavaDoc();
70
71     /**
72      * All prepared pointcuts defined in the system.
73      */

74     private final Map m_deploymentScopes = new HashMap();
75
76     /**
77      * Creates a new instance, creates and sets the system cflow aspect.
78      */

79     public SystemDefinition(final String JavaDoc uuid) {
80         setUuid(uuid);
81         //TODO REMOVE below
82
// AspectDefinition systemAspect = new AspectDefinition(
83
// CFlowSystemAspect.class.getName(),
84
// JavaClassInfo.getClassInfo(CFlowSystemAspect.class),
85
// this
86
// );
87
// systemAspect.setDeploymentModel(CFlowSystemAspect.DEPLOYMENT_MODEL);
88
// m_aspectMap.put(CFlowSystemAspect.CLASS_NAME, systemAspect);
89
}
90
91     /**
92      * Sets the UUID for the definition.
93      *
94      * @param uuid the UUID
95      */

96     private void setUuid(final String JavaDoc uuid) {
97         m_uuid = uuid;
98     }
99
100     /**
101      * Returns the UUID for the definition.
102      *
103      * @return the UUID
104      */

105     public String JavaDoc getUuid() {
106         return m_uuid;
107     }
108
109     /**
110      * Returns the include packages.
111      *
112      * @return the include packages
113      */

114     public Set JavaDoc getIncludePackages() {
115         return m_includePackages;
116     }
117
118     /**
119      * Returns the exclude packages.
120      *
121      * @return the exclude packages
122      */

123     public Set JavaDoc getExcludePackages() {
124         return m_excludePackages;
125     }
126
127     /**
128      * Returns a collection with the aspect definitions registered.
129      *
130      * @return the aspect definitions
131      */

132     public Collection JavaDoc getAspectDefinitions() {
133         Collection JavaDoc clone = new ArrayList JavaDoc(m_aspectMap.size());
134         for (Iterator JavaDoc it = m_aspectMap.values().iterator(); it.hasNext();) {
135             clone.add(it.next());
136         }
137         return clone;
138     }
139
140     /**
141      * Returns a collection with the mixin definitions registered.
142      *
143      * @return the mixin definitions
144      */

145     public Collection JavaDoc getMixinDefinitions() {
146         Collection JavaDoc clone = new ArrayList JavaDoc(m_mixinMap.size());
147         for (Iterator JavaDoc it = m_mixinMap.values().iterator(); it.hasNext();) {
148             clone.add(it.next());
149         }
150         return clone;
151     }
152
153     /**
154      * Returns a collection with the advice definitions registered.
155      *
156      * @return the advice definitions
157      */

158     public Collection JavaDoc getAdviceDefinitions() {
159         final Collection JavaDoc adviceDefs = new ArrayList JavaDoc();
160         for (Iterator JavaDoc it = m_aspectMap.values().iterator(); it.hasNext();) {
161             AspectDefinition aspectDef = (AspectDefinition) it.next();
162             adviceDefs.addAll(aspectDef.getAroundAdviceDefinitions());
163             adviceDefs.addAll(aspectDef.getBeforeAdviceDefinitions());
164             adviceDefs.addAll(aspectDef.getAfterAdviceDefinitions());
165         }
166         return adviceDefs;
167     }
168
169     /**
170      * Returns a specific aspect definition.
171      *
172      * @param name the name of the aspect definition
173      * @return the aspect definition
174      */

175     public AspectDefinition getAspectDefinition(final String JavaDoc name) {
176         return (AspectDefinition) m_aspectMap.get(name);
177     }
178
179     /**
180      * Returns the mixin definitions matching a specfic expression.
181      *
182      * @param ctx the expression context
183      * @return a list with the mixin definitions
184      */

185     public List JavaDoc getMixinDefinitions(final ExpressionContext ctx) {
186         final List JavaDoc introDefs = new ArrayList JavaDoc();
187         for (Iterator JavaDoc it = m_mixinMap.values().iterator(); it.hasNext();) {
188             MixinDefinition introDef = (MixinDefinition) it.next();
189             for (int i = 0; i < introDef.getExpressionInfos().length; i++) {
190                 if (introDef.getExpressionInfos()[i].getExpression().match(ctx)) {
191                     introDefs.add(introDef);
192                 }
193             }
194         }
195         return introDefs;
196     }
197
198     /**
199      * Returns the interface introductions for a certain class merged with the implementation based introductions as
200      * well.
201      *
202      * @param ctx the expression context
203      * @return the names
204      */

205     public List JavaDoc getInterfaceIntroductionDefinitions(final ExpressionContext ctx) {
206         if (ctx == null) {
207             throw new IllegalArgumentException JavaDoc("context can not be null");
208         }
209         List JavaDoc interfaceIntroductionDefs = new ArrayList JavaDoc();
210         for (Iterator JavaDoc iterator = m_aspectMap.values().iterator(); iterator.hasNext();) {
211             AspectDefinition aspectDef = (AspectDefinition) iterator.next();
212             for (Iterator JavaDoc it = aspectDef.getInterfaceIntroductionDefinitions().iterator(); it.hasNext();) {
213                 InterfaceIntroductionDefinition introDef = (InterfaceIntroductionDefinition) it.next();
214                 ExpressionInfo[] expressionInfos = introDef.getExpressionInfos();
215                 for (int i = 0; i < expressionInfos.length; i++) {
216                     ExpressionInfo expressionInfo = expressionInfos[i];
217                     ExpressionVisitor expression = expressionInfo.getExpression();
218                     if (expression.match(ctx)) {
219                         interfaceIntroductionDefs.add(introDef);
220                     }
221                 }
222             }
223         }
224         return interfaceIntroductionDefs;
225     }
226
227     /**
228      * Adds a new aspect definition
229      * For each of its bounded pointcut, register cflow aspects as necessary.
230      *
231      * @param aspectDef the aspect definition
232      */

233     public void addAspect(final AspectDefinition aspectDef) {
234         if (aspectDef == null) {
235             throw new IllegalArgumentException JavaDoc("aspect definition can not be null");
236         }
237
238         synchronized (m_aspectMap) {
239             if (m_aspectMap.containsKey(aspectDef.getName())) {
240                 return;
241             }
242
243             // register the "cflow" aspects for this aspect bindings
244
// note: this one will even support cflow(xx && cflow())
245
// note: the cflow aspect MUST be registered FIRST for precedence purpose
246
// so that pcX && cflow(pcX) match on pcX
247
for (Iterator JavaDoc iterator = aspectDef.getAdviceDefinitions().iterator(); iterator.hasNext();) {
248                 AdviceDefinition adviceDefinition = (AdviceDefinition) iterator.next();
249                 List JavaDoc cflowBindings = CflowBinding.getCflowBindingsForCflowOf(adviceDefinition.getExpressionInfo());
250                 for (Iterator JavaDoc cflows = cflowBindings.iterator(); cflows.hasNext();) {
251                     CflowBinding cflowBinding = (CflowBinding) cflows.next();
252                     if (!cflowBinding.isCflowBelow()) {
253                         addAspect(cflowBinding.getAspectDefinition(this, aspectDef.getClassInfo().getClassLoader()));
254                     }
255                 }
256             }
257
258             // register the aspect itself
259
m_aspectMap.put(aspectDef.getName(), aspectDef);
260
261             // register the "cflowbelow" aspects for this aspect bindings
262
// note: this one will even support cflowbelow(xx && cflowbelow())
263
// note: the cflowbelow aspect MUST be registered LAST for precedence purpose
264
// so that pcX && cflowbelow(pcX) does not match on just the pcX joinpoint
265
for (Iterator JavaDoc iterator = aspectDef.getAdviceDefinitions().iterator(); iterator.hasNext();) {
266                 AdviceDefinition adviceDefinition = (AdviceDefinition) iterator.next();
267                 List JavaDoc cflowBindings = CflowBinding.getCflowBindingsForCflowOf(adviceDefinition.getExpressionInfo());
268                 for (Iterator JavaDoc cflows = cflowBindings.iterator(); cflows.hasNext();) {
269                     CflowBinding cflowBinding = (CflowBinding) cflows.next();
270                     if (cflowBinding.isCflowBelow()) {
271                         addAspect(cflowBinding.getAspectDefinition(this, aspectDef.getClassInfo().getClassLoader()));
272                     }
273                 }
274             }
275         }
276     }
277
278     /**
279      * Adds a new aspect definition, overwrites the previous one with the same name (if there is one).
280      *
281      * @param aspectDef the aspect definition
282      */

283     public void addAspectOverwriteIfExists(final AspectDefinition aspectDef) {
284         if (aspectDef == null) {
285             throw new IllegalArgumentException JavaDoc("aspect definition can not be null");
286         }
287         synchronized (m_aspectMap) {
288             m_aspectMap.put(aspectDef.getName(), aspectDef);
289         }
290     }
291
292     /**
293      * Adds a new mixin definition.
294      *
295      * @param mixinDef the mixin definition
296      */

297     public void addMixinDefinition(final MixinDefinition mixinDef) {
298         if (mixinDef == null) {
299             throw new IllegalArgumentException JavaDoc("mixin definition can not be null");
300         }
301         synchronized (m_mixinMap) {
302             if (m_mixinMap.containsKey(mixinDef.getMixinImpl().getName())) {
303                 MixinDefinition def = (MixinDefinition) m_mixinMap.get(mixinDef.getMixinImpl().getName());
304                 def.addExpressionInfos(mixinDef.getExpressionInfos());
305                 return;
306             }
307             m_mixinMap.put(mixinDef.getMixinImpl().getName(), mixinDef);
308         }
309     }
310
311     /**
312      * Adds a new include package.
313      *
314      * @param includePackage the new include package
315      */

316     public void addIncludePackage(final String JavaDoc includePackage) {
317         synchronized (m_includePackages) {
318             m_includePackages.add(includePackage + '.');
319         }
320     }
321
322     /**
323      * Adds a new exclude package.
324      *
325      * @param excludePackage the new exclude package
326      */

327     public void addExcludePackage(final String JavaDoc excludePackage) {
328         synchronized (m_excludePackages) {
329             m_excludePackages.add(excludePackage + '.');
330         }
331     }
332
333     /**
334      * Adds a new prepare package.
335      *
336      * @param preparePackage the new prepare package
337      */

338     public void addPreparePackage(final String JavaDoc preparePackage) {
339         synchronized (m_preparePackages) {
340             m_preparePackages.add(preparePackage + '.');
341         }
342     }
343
344     /**
345      * Returns the prepare packages.
346      *
347      * @return
348      */

349     public Set JavaDoc getPreparePackages() {
350         return m_preparePackages;
351     }
352
353     /**
354      * Checks if a class should be included.
355      *
356      * @param className the name or the class
357      * @return boolean
358      */

359     public boolean inIncludePackage(final String JavaDoc className) {
360         if (className == null) {
361             throw new IllegalArgumentException JavaDoc("class name can not be null");
362         }
363         if (m_includePackages.isEmpty()) {
364             return true;
365         }
366         for (Iterator JavaDoc it = m_includePackages.iterator(); it.hasNext();) {
367             String JavaDoc packageName = (String JavaDoc) it.next();
368             if (className.startsWith(packageName)) {
369                 return true;
370             }
371         }
372         return false;
373     }
374
375     /**
376      * Checks if a class should be excluded.
377      *
378      * @param className the name or the class
379      * @return boolean
380      */

381     public boolean inExcludePackage(final String JavaDoc className) {
382         if (className == null) {
383             throw new IllegalArgumentException JavaDoc("class name can not be null");
384         }
385         for (Iterator JavaDoc it = m_excludePackages.iterator(); it.hasNext();) {
386             String JavaDoc packageName = (String JavaDoc) it.next();
387             if (className.startsWith(packageName)) {
388                 return true;
389             }
390         }
391         return false;
392     }
393
394     /**
395      * Checks if a class is in prepare declaration
396      *
397      * @param className the name or the class
398      * @return boolean
399      */

400     public boolean inPreparePackage(String JavaDoc className) {
401         if (className == null) {
402             throw new IllegalArgumentException JavaDoc("class name can not be null");
403         }
404         for (Iterator JavaDoc it = m_preparePackages.iterator(); it.hasNext();) {
405             String JavaDoc packageName = (String JavaDoc) it.next();
406             if (className.startsWith(packageName)) {
407                 return true;
408             }
409         }
410         return false;
411     }
412
413     /**
414      * Checks if a context has a pointcut.
415      *
416      * @param ctx the expression context
417      * @return boolean
418      */

419     public boolean hasPointcut(final ExpressionContext ctx) {
420         if (ctx == null) {
421             throw new IllegalArgumentException JavaDoc("context can not be null");
422         }
423         for (Iterator JavaDoc it = m_aspectMap.values().iterator(); it.hasNext();) {
424             AspectDefinition aspectDef = (AspectDefinition) it.next();
425             for (Iterator JavaDoc it2 = aspectDef.getAdviceDefinitions().iterator(); it2.hasNext();) {
426                 AdviceDefinition adviceDef = (AdviceDefinition) it2.next();
427                 final ExpressionInfo expressionInfo = adviceDef.getExpressionInfo();
428                 if (expressionInfo == null) {
429                     continue;
430                 }
431                 ExpressionVisitor expression = expressionInfo.getExpression();
432
433                 if (expression.match(ctx)) {
434                     if (AspectWerkzPreProcessor.DETAILS) {
435                         System.out.println(
436                                 "[TRACE - match: " + expression + " @ "
437                                 + aspectDef.getQualifiedName() + "/" +
438                                 adviceDef.getName()
439                         );
440                         System.out.println("[ for " + ctx.getReflectionInfo());
441                         System.out.println("[ within " + ctx.getWithinReflectionInfo());
442                         System.out.println("[ type " + ctx.getPointcutType().toString());
443                     }
444                     return true;
445                 }
446             }
447         }
448         return false;
449     }
450
451     /**
452      * Checks if a class is advised.
453      *
454      * @param ctxs an array with the expression contexts
455      * @return boolean
456      */

457     public boolean isAdvised(final ExpressionContext[] ctxs) {
458         if (ctxs == null) {
459             throw new IllegalArgumentException JavaDoc("context array can not be null");
460         }
461         for (Iterator JavaDoc it = m_aspectMap.values().iterator(); it.hasNext();) {
462             AspectDefinition aspectDef = (AspectDefinition) it.next();
463             List JavaDoc advices = aspectDef.getAdviceDefinitions();
464             for (Iterator JavaDoc it2 = advices.iterator(); it2.hasNext();) {
465                 AdviceDefinition adviceDef = (AdviceDefinition) it2.next();
466                 for (int i = 0; i < ctxs.length; i++) {
467                     ExpressionContext ctx = ctxs[i];
468                     final ExpressionInfo expressionInfo = adviceDef.getExpressionInfo();
469                     if (expressionInfo == null) {
470                         continue;
471                     }
472                     if (expressionInfo.getAdvisedClassFilterExpression().match(ctx)) {
473                         if (AspectWerkzPreProcessor.DETAILS) {
474                             System.out.println(
475                                     "[TRACE - earlymatch: " + expressionInfo + " @ "
476                                     + aspectDef.getQualifiedName() + "/" +
477                                     adviceDef.getName()
478                             );
479                             System.out.println("[ for " + ctx.getReflectionInfo());
480                             System.out.println("[ within " + ctx.getWithinReflectionInfo());
481                             System.out.println("[ type " + ctx.getPointcutType().toString());
482                         }
483                         return true;
484                     }
485                 }
486             }
487         }
488         return false;
489     }
490
491     /**
492      * Checks if a class is advised.
493      *
494      * @param ctx the expression context
495      * @return boolean
496      */

497     public boolean isAdvised(final ExpressionContext ctx) {
498         if (ctx == null) {
499             throw new IllegalArgumentException JavaDoc("context can not be null");
500         }
501         for (Iterator JavaDoc it = m_aspectMap.values().iterator(); it.hasNext();) {
502             AspectDefinition aspectDef = (AspectDefinition) it.next();
503             List JavaDoc advices = aspectDef.getAdviceDefinitions();
504             for (Iterator JavaDoc it2 = advices.iterator(); it2.hasNext();) {
505                 AdviceDefinition adviceDef = (AdviceDefinition) it2.next();
506                 final ExpressionInfo expressionInfo = adviceDef.getExpressionInfo();
507                 if (expressionInfo == null) {
508                     continue;
509                 }
510                 if (expressionInfo.getAdvisedClassFilterExpression().match(ctx) /*||
511                     expressionInfo.getAdvisedCflowClassFilterExpression().match(ctx) ALEX XXX CFLOW*/
) {
512                     return true;
513                 }
514             }
515         }
516         return false;
517     }
518
519     /**
520      * Checks if a class has an mixin.
521      *
522      * @param ctxs an array with the expression contexts
523      * @return boolean
524      */

525     public boolean hasMixin(final ExpressionContext[] ctxs) {
526         if (ctxs == null) {
527             throw new IllegalArgumentException JavaDoc("context array can not be null");
528         }
529         for (Iterator JavaDoc it = m_mixinMap.values().iterator(); it.hasNext();) {
530             MixinDefinition introDef = (MixinDefinition) it.next();
531             ExpressionInfo[] expressionInfos = introDef.getExpressionInfos();
532             for (int i = 0; i < expressionInfos.length; i++) {
533                 ExpressionInfo expressionInfo = expressionInfos[i];
534                 for (int j = 0; j < ctxs.length; j++) {
535                     if (expressionInfo.getExpression().match(ctxs[j])) {
536                         return true;
537                     }
538                 }
539             }
540         }
541         return false;
542     }
543
544     /**
545      * Checks if a class has an mixin.
546      *
547      * @param ctx the expression context
548      * @return boolean
549      */

550     public boolean hasMixin(final ExpressionContext ctx) {
551         if (ctx == null) {
552             throw new IllegalArgumentException JavaDoc("context can not be null");
553         }
554         for (Iterator JavaDoc it = m_mixinMap.values().iterator(); it.hasNext();) {
555             MixinDefinition introDef = (MixinDefinition) it.next();
556             ExpressionInfo[] expressionInfos = introDef.getExpressionInfos();
557             for (int i = 0; i < expressionInfos.length; i++) {
558                 ExpressionInfo expressionInfo = expressionInfos[i];
559                 if (expressionInfo.getExpression().match(ctx)) {
560                     return true;
561                 }
562             }
563         }
564         return false;
565     }
566
567     /**
568      * Checks if a class is advised with an interface introduction.
569      *
570      * @param ctxs the expression contexts
571      * @return boolean
572      */

573     public boolean hasIntroducedInterface(final ExpressionContext[] ctxs) {
574         if (ctxs == null) {
575             throw new IllegalArgumentException JavaDoc("context array can not be null");
576         }
577         for (Iterator JavaDoc iterator = m_aspectMap.values().iterator(); iterator.hasNext();) {
578             AspectDefinition aspectDef = (AspectDefinition) iterator.next();
579             for (Iterator JavaDoc it = aspectDef.getInterfaceIntroductionDefinitions().iterator(); it.hasNext();) {
580                 InterfaceIntroductionDefinition introDef = (InterfaceIntroductionDefinition) it.next();
581                 ExpressionInfo[] expressionInfos = introDef.getExpressionInfos();
582                 for (int i = 0; i < expressionInfos.length; i++) {
583                     ExpressionInfo expressionInfo = expressionInfos[i];
584                     for (int j = 0; j < ctxs.length; j++) {
585                         if (expressionInfo.getExpression().match(ctxs[i])) {
586                             return true;
587                         }
588                     }
589                 }
590             }
591         }
592         return false;
593     }
594
595     /**
596      * Checks if a class is advised with an interface introduction.
597      *
598      * @param ctx the expression context
599      * @return boolean
600      */

601     public boolean hasIntroducedInterface(final ExpressionContext ctx) {
602         if (ctx == null) {
603             throw new IllegalArgumentException JavaDoc("context can not be null");
604         }
605         for (Iterator JavaDoc iterator = m_aspectMap.values().iterator(); iterator.hasNext();) {
606             AspectDefinition aspectDefinition = (AspectDefinition) iterator.next();
607             for (Iterator JavaDoc it = aspectDefinition.getInterfaceIntroductionDefinitions().iterator(); it.hasNext();) {
608                 InterfaceIntroductionDefinition introDef = (InterfaceIntroductionDefinition) it.next();
609                 ExpressionInfo[] expressionInfos = introDef.getExpressionInfos();
610                 for (int i = 0; i < expressionInfos.length; i++) {
611                     ExpressionInfo expressionInfo = expressionInfos[i];
612                     if (expressionInfo.getExpression().match(ctx)) {
613                         return true;
614                     }
615                 }
616             }
617         }
618         return false;
619     }
620
621     /**
622      * Returns a collection with all deployment scopes in the system.
623      *
624      * @return a collection with all deployment scopes in the system
625      */

626     public Collection JavaDoc getDeploymentScopes() {
627         return m_deploymentScopes.values();
628     }
629
630     /**
631      * Returns the deployment scope with the name specified.
632      *
633      * @param name the name of the deployment scope
634      * @return the deployment scope with the name specified
635      */

636     public DeploymentScope getDeploymentScope(final String JavaDoc name) {
637         return (DeploymentScope) m_deploymentScopes.get(name);
638     }
639
640     /**
641      * Adds a deployment scope to the system.
642      *
643      * @param deploymentScope the deployment scope
644      */

645     public void addDeploymentScope(final DeploymentScope deploymentScope) {
646         m_deploymentScopes.put(deploymentScope.getName(), deploymentScope);
647
648         //TODO do we need to take care of cflow aspects
649
}
650
651     public boolean equals(Object JavaDoc o) {
652         return ((SystemDefinition) o).m_uuid.equals(m_uuid);
653     }
654
655     public int hashCode() {
656         return m_uuid.hashCode();
657     }
658
659     /**
660      * Create a new virtual system definition for the given loader and add the virtual aspect in it.
661      *
662      * @param loader
663      * @return
664      */

665     public static SystemDefinition createVirtualDefinitionAt(ClassLoader JavaDoc loader) {
666         SystemDefinition def = new SystemDefinition(SystemDefinitionContainer.getVirtualDefinitionUuid(loader));
667         DocumentParser.addVirtualAspect(def);
668         return def;
669     }
670 }
Popular Tags