KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > aspectwerkz > definition > SystemDefinition


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.aspectwerkz.definition;
5
6
7 import com.tc.aspectwerkz.DeploymentModel;
8 import com.tc.aspectwerkz.expression.ExpressionContext;
9 import com.tc.aspectwerkz.expression.ExpressionInfo;
10 import com.tc.aspectwerkz.expression.ExpressionVisitor;
11 import com.tc.aspectwerkz.cflow.CflowBinding;
12 import com.tc.aspectwerkz.perx.PerObjectAspect;
13 import com.tc.aspectwerkz.transform.Properties;
14 import com.tc.aspectwerkz.util.SequencedHashMap;
15
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 HashMap();
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   }
82
83   /**
84    * Sets the UUID for the definition.
85    *
86    * @param uuid the UUID
87    */

88   private void setUuid(final String JavaDoc uuid) {
89     m_uuid = uuid;
90   }
91
92   /**
93    * Returns the UUID for the definition.
94    *
95    * @return the UUID
96    */

97   public String JavaDoc getUuid() {
98     return m_uuid;
99   }
100
101   /**
102    * Returns the include packages.
103    *
104    * @return the include packages
105    */

106   public Set JavaDoc getIncludePackages() {
107     return m_includePackages;
108   }
109
110   /**
111    * Returns the exclude packages.
112    *
113    * @return the exclude packages
114    */

115   public Set JavaDoc getExcludePackages() {
116     return m_excludePackages;
117   }
118
119   /**
120    * Returns a collection with the aspect definitions registered.
121    *
122    * @return the aspect definitions
123    */

124   public Collection JavaDoc getAspectDefinitions() {
125     Collection JavaDoc clone = new ArrayList JavaDoc(m_aspectMap.size());
126     for (Iterator JavaDoc it = m_aspectMap.values().iterator(); it.hasNext();) {
127       clone.add(it.next());
128     }
129     return clone;
130   }
131
132   /**
133    * Returns a collection with the mixin definitions registered.
134    *
135    * @return the mixin definitions
136    */

137   public Collection JavaDoc getMixinDefinitions() {
138     Collection JavaDoc clone = new ArrayList JavaDoc(m_mixinMap.size());
139     for (Iterator JavaDoc it = m_mixinMap.values().iterator(); it.hasNext();) {
140       clone.add(it.next());
141     }
142     return clone;
143   }
144
145   /**
146    * Returns a collection with the advice definitions registered.
147    *
148    * @return the advice definitions
149    */

150   public Collection JavaDoc getAdviceDefinitions() {
151     final Collection JavaDoc adviceDefs = new ArrayList JavaDoc();
152     for (Iterator JavaDoc it = m_aspectMap.values().iterator(); it.hasNext();) {
153       AspectDefinition aspectDef = (AspectDefinition) it.next();
154       adviceDefs.addAll(aspectDef.getAroundAdviceDefinitions());
155       adviceDefs.addAll(aspectDef.getBeforeAdviceDefinitions());
156       adviceDefs.addAll(aspectDef.getAfterAdviceDefinitions());
157     }
158     return adviceDefs;
159   }
160
161   /**
162    * Returns a specific aspect definition.
163    *
164    * @param name the name of the aspect definition
165    * @return the aspect definition
166    */

167   public AspectDefinition getAspectDefinition(final String JavaDoc name) {
168     return (AspectDefinition) m_aspectMap.get(name);
169   }
170
171   /**
172    * Returns the mixin definitions matching a specfic expression.
173    *
174    * @param ctx the expression context
175    * @return a list with the mixin definitions
176    */

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

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

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

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

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

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

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

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

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

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

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

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

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

455   public boolean isAdvised(final ExpressionContext[] ctxs) {
456     if (ctxs == null) {
457       throw new IllegalArgumentException JavaDoc("context array can not be null");
458     }
459     for (Iterator JavaDoc it = m_aspectMap.values().iterator(); it.hasNext();) {
460       AspectDefinition aspectDef = (AspectDefinition) it.next();
461       List JavaDoc advices = aspectDef.getAdviceDefinitions();
462       for (Iterator JavaDoc it2 = advices.iterator(); it2.hasNext();) {
463         AdviceDefinition adviceDef = (AdviceDefinition) it2.next();
464         for (int i = 0; i < ctxs.length; i++) {
465           ExpressionContext ctx = ctxs[i];
466           final ExpressionInfo expressionInfo = adviceDef.getExpressionInfo();
467           if (expressionInfo == null) {
468             continue;
469           }
470           if (expressionInfo.getAdvisedClassFilterExpression().match(ctx)) {
471             return true;
472           }
473         }
474       }
475     }
476     return false;
477   }
478
479   /**
480    * Checks if a class is advised.
481    *
482    * @param ctx the expression context
483    * @return boolean
484    */

485   public boolean isAdvised(final ExpressionContext ctx) {
486     if (ctx == null) {
487       throw new IllegalArgumentException JavaDoc("context can not be null");
488     }
489     for (Iterator JavaDoc it = m_aspectMap.values().iterator(); it.hasNext();) {
490       AspectDefinition aspectDef = (AspectDefinition) it.next();
491       List JavaDoc advices = aspectDef.getAdviceDefinitions();
492       for (Iterator JavaDoc it2 = advices.iterator(); it2.hasNext();) {
493         AdviceDefinition adviceDef = (AdviceDefinition) it2.next();
494         final ExpressionInfo expressionInfo = adviceDef.getExpressionInfo();
495         if (expressionInfo == null) {
496           continue;
497         }
498         if (expressionInfo.getAdvisedClassFilterExpression().match(ctx) /*||
499                     expressionInfo.getAdvisedCflowClassFilterExpression().match(ctx) ALEX XXX CFLOW*/
) {
500           return true;
501         }
502       }
503     }
504     return false;
505   }
506
507   /**
508    * Checks if a class has an mixin.
509    *
510    * @param ctxs an array with the expression contexts
511    * @return boolean
512    */

513   public boolean hasMixin(final ExpressionContext[] ctxs) {
514     if (ctxs == null) {
515       throw new IllegalArgumentException JavaDoc("context array can not be null");
516     }
517     for (Iterator JavaDoc it = m_mixinMap.values().iterator(); it.hasNext();) {
518       MixinDefinition introDef = (MixinDefinition) it.next();
519       ExpressionInfo[] expressionInfos = introDef.getExpressionInfos();
520       for (int i = 0; i < expressionInfos.length; i++) {
521         ExpressionInfo expressionInfo = expressionInfos[i];
522         for (int j = 0; j < ctxs.length; j++) {
523           if (expressionInfo.getExpression().match(ctxs[j])) {
524             return true;
525           }
526         }
527       }
528     }
529     return false;
530   }
531
532   /**
533    * Checks if a class has an mixin.
534    *
535    * @param ctx the expression context
536    * @return boolean
537    */

538   public boolean hasMixin(final ExpressionContext ctx) {
539     if (ctx == null) {
540       throw new IllegalArgumentException JavaDoc("context can not be null");
541     }
542     for (Iterator JavaDoc it = m_mixinMap.values().iterator(); it.hasNext();) {
543       MixinDefinition introDef = (MixinDefinition) it.next();
544       ExpressionInfo[] expressionInfos = introDef.getExpressionInfos();
545       for (int i = 0; i < expressionInfos.length; i++) {
546         ExpressionInfo expressionInfo = expressionInfos[i];
547         if (expressionInfo.getExpression().match(ctx)) {
548           return true;
549         }
550       }
551     }
552     return false;
553   }
554
555   /**
556    * Checks if a class is advised with an interface introduction.
557    *
558    * @param ctxs the expression contexts
559    * @return boolean
560    */

561   public boolean hasIntroducedInterface(final ExpressionContext[] ctxs) {
562     if (ctxs == null) {
563       throw new IllegalArgumentException JavaDoc("context array can not be null");
564     }
565     for (Iterator JavaDoc iterator = m_aspectMap.values().iterator(); iterator.hasNext();) {
566       AspectDefinition aspectDef = (AspectDefinition) iterator.next();
567       for (Iterator JavaDoc it = aspectDef.getInterfaceIntroductionDefinitions().iterator(); it.hasNext();) {
568         InterfaceIntroductionDefinition introDef = (InterfaceIntroductionDefinition) it.next();
569         ExpressionInfo[] expressionInfos = introDef.getExpressionInfos();
570         for (int i = 0; i < expressionInfos.length; i++) {
571           ExpressionInfo expressionInfo = expressionInfos[i];
572           for (int j = 0; j < ctxs.length; j++) {
573             if (expressionInfo.getExpression().match(ctxs[i])) {
574               return true;
575             }
576           }
577         }
578       }
579     }
580     return false;
581   }
582
583   /**
584    * Checks if a class is advised with an interface introduction.
585    *
586    * @param ctx the expression context
587    * @return boolean
588    */

589   public boolean hasIntroducedInterface(final ExpressionContext ctx) {
590     if (ctx == null) {
591       throw new IllegalArgumentException JavaDoc("context can not be null");
592     }
593     for (Iterator JavaDoc iterator = m_aspectMap.values().iterator(); iterator.hasNext();) {
594       AspectDefinition aspectDefinition = (AspectDefinition) iterator.next();
595       for (Iterator JavaDoc it = aspectDefinition.getInterfaceIntroductionDefinitions().iterator(); it.hasNext();) {
596         InterfaceIntroductionDefinition introDef = (InterfaceIntroductionDefinition) it.next();
597         ExpressionInfo[] expressionInfos = introDef.getExpressionInfos();
598         for (int i = 0; i < expressionInfos.length; i++) {
599           ExpressionInfo expressionInfo = expressionInfos[i];
600           if (expressionInfo.getExpression().match(ctx)) {
601             return true;
602           }
603         }
604       }
605     }
606     return false;
607   }
608
609   /**
610    * Returns a collection with all deployment scopes in the system.
611    *
612    * @return a collection with all deployment scopes in the system
613    */

614   public Collection JavaDoc getDeploymentScopes() {
615     return m_deploymentScopes.values();
616   }
617
618   /**
619    * Returns the deployment scope with the name specified.
620    *
621    * @param name the name of the deployment scope
622    * @return the deployment scope with the name specified
623    */

624   public DeploymentScope getDeploymentScope(final String JavaDoc name) {
625     return (DeploymentScope) m_deploymentScopes.get(name);
626   }
627
628   /**
629    * Adds a deployment scope to the system.
630    *
631    * @param deploymentScope the deployment scope
632    */

633   public void addDeploymentScope(final DeploymentScope deploymentScope) {
634     m_deploymentScopes.put(deploymentScope.getName(), deploymentScope);
635
636     //TODO do we need to take care of cflow aspects
637
}
638
639   public boolean equals(Object JavaDoc o) {
640     return ((SystemDefinition) o).m_uuid.equals(m_uuid);
641   }
642
643   public int hashCode() {
644     return m_uuid.hashCode();
645   }
646
647   /**
648    * Create a new virtual system definition for the given loader and add the virtual aspect in it.
649    *
650    * @param loader
651    * @return the def
652    */

653   public static SystemDefinition createVirtualDefinitionAt(ClassLoader JavaDoc loader) {
654     SystemDefinition def = new SystemDefinition(SystemDefinitionContainer.getVirtualDefinitionUuidFor(loader));
655     DocumentParser.addVirtualAspect(def);
656     return def;
657   }
658 }
659
Popular Tags