KickJava   Java API By Example, From Geeks To Geeks.

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


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 //import org.dom4j.Attribute;
7
//import org.dom4j.Document;
8
//import org.dom4j.DocumentException;
9
//import org.dom4j.Element;
10

11 import org.w3c.dom.Attr JavaDoc;
12 import org.w3c.dom.Document JavaDoc;
13 import org.w3c.dom.Element JavaDoc;
14 import org.w3c.dom.NamedNodeMap JavaDoc;
15 import org.w3c.dom.Node JavaDoc;
16 import org.w3c.dom.NodeList JavaDoc;
17 import org.w3c.dom.Text JavaDoc;
18
19 import com.tc.aspectwerkz.DeploymentModel;
20 import com.tc.aspectwerkz.expression.ExpressionInfo;
21 import com.tc.aspectwerkz.expression.ExpressionNamespace;
22 import com.tc.aspectwerkz.annotation.AspectAnnotationParser;
23 import com.tc.aspectwerkz.annotation.MixinAnnotationParser;
24 import com.tc.aspectwerkz.aspect.AdviceType;
25 import com.tc.aspectwerkz.exception.DefinitionException;
26 import com.tc.aspectwerkz.intercept.AdvisableImpl;
27 import com.tc.aspectwerkz.reflect.impl.asm.AsmClassInfo;
28 import com.tc.aspectwerkz.reflect.impl.java.JavaClassInfo;
29 import com.tc.aspectwerkz.reflect.impl.java.JavaMethodInfo;
30 import com.tc.aspectwerkz.reflect.ClassInfo;
31 import com.tc.aspectwerkz.reflect.MethodInfo;
32 import com.tc.aspectwerkz.transform.inlining.AspectModelManager;
33 import com.tc.aspectwerkz.util.Strings;
34
35 import java.io.IOException JavaDoc;
36 import java.util.ArrayList JavaDoc;
37 import java.util.HashSet JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.List JavaDoc;
40 import java.util.Set JavaDoc;
41 import java.util.StringTokenizer JavaDoc;
42
43 /**
44  * Parses the XML definition using <tt>dom4j</tt>.
45  *
46  * @author <a HREF="mailto:jboner@codehaus.org">Jonas BonŽr </a>
47  * @author <a HREF="mailto:alex@gnilux.com">Alexandre Vasseur </a>
48  */

49 public class DocumentParser {
50
51   /**
52    * Parses aspect class names.
53    *
54    * @param document the defintion as a document
55    * @return the aspect class names
56    */

57   public static List JavaDoc parseAspectClassNames(Document JavaDoc document) {
58     List JavaDoc aspectClassNames = new ArrayList JavaDoc();
59     
60     Element JavaDoc documentElement = document.getDocumentElement();
61     NodeList JavaDoc systemNodes = documentElement.getChildNodes();
62     for (int i = 0; i<systemNodes.getLength(); i++) {
63       Node JavaDoc systemNode = systemNodes.item(i);
64       String JavaDoc nodeName = systemNode.getNodeName();
65       if(nodeName.equals("system")) {
66         String JavaDoc basePackage = getBasePackage((Element JavaDoc) systemNode);
67         
68         NodeList JavaDoc childNodes = systemNode.getChildNodes();
69         for (int j = 0; j < childNodes.getLength(); j++) {
70           Node JavaDoc childNode = childNodes.item(j);
71           if(childNode.getNodeName().equals("aspect")) {
72             addAspectClassName(aspectClassNames, childNode, basePackage);
73             
74           } else if(childNode.getNodeName().equals("package")) {
75             NodeList JavaDoc aspectNodes = childNode.getChildNodes();
76             for (int k = 0; k < aspectNodes.getLength(); k++) {
77               Node JavaDoc aspectNode = aspectNodes.item(k);
78               if(aspectNode.getNodeName().equals("aspect")) {
79                 addAspectClassName(aspectClassNames, aspectNode, basePackage);
80               }
81             }
82           }
83         }
84       }
85     }
86     
87     aspectClassNames.add(Virtual.class.getName());
88     return aspectClassNames;
89   }
90
91   private static void addAspectClassName(List JavaDoc aspectClassNames, Node JavaDoc aspectNode, String JavaDoc basePackage) {
92     if(aspectNode.getNodeName().equals("aspect")) {
93       NamedNodeMap JavaDoc attrs = aspectNode.getAttributes();
94       for (int l = 0; l < attrs.getLength(); l++) {
95         Node JavaDoc attr = attrs.item(l);
96         if(attr.getNodeName().equals("class")) {
97           aspectClassNames.add(basePackage + ((Attr JavaDoc) attr).getValue().trim());
98         }
99       }
100     }
101   }
102
103   /**
104    * Parses the definition DOM document.
105    *
106    * @param xmlDef the defintion xml
107    * @param systemDef the system definition
108    * @param aspectClass the aspect class
109    * @return the definition
110    * @throws DocumentParserException
111    */

112   public static AspectDefinition parseAspectDefinition(String JavaDoc xmlDef,
113                                                        SystemDefinition systemDef,
114                                                        Class JavaDoc aspectClass) {
115     Document JavaDoc document;
116     try {
117       document = XmlParser.createDocument(xmlDef);
118     } catch (IOException JavaDoc e) {
119       throw new DefinitionException("Unable to parse definition; "+e.toString());
120     }
121
122     Element JavaDoc aspectElement = document.getDocumentElement();
123
124     if (!"aspect".equals(aspectElement.getNodeName())) {
125       throw new DefinitionException("XML definition for aspect is not well-formed: " + xmlDef);
126     }
127     String JavaDoc specialAspectName = null;
128     String JavaDoc className = null;
129     String JavaDoc deploymentModelAsString = null;
130     String JavaDoc containerClassName = null;
131     NamedNodeMap JavaDoc aspectAttributes = aspectElement.getAttributes();
132     for (int i = 0; i < aspectAttributes.getLength(); i++) {
133       Node JavaDoc attribute = aspectAttributes.item(i);
134       String JavaDoc name = attribute.getNodeName().trim();
135       if (name.equalsIgnoreCase("class")) {
136         className = ((Attr JavaDoc) attribute).getValue().trim();
137       } else if (name.equalsIgnoreCase("deployment-model")) {
138         deploymentModelAsString = ((Attr JavaDoc) attribute).getValue().trim();
139       } else if (name.equalsIgnoreCase("name")) {
140         specialAspectName = ((Attr JavaDoc) attribute).getValue().trim();
141       } else if (name.equalsIgnoreCase("container")) {
142         containerClassName = ((Attr JavaDoc) attribute).getValue().trim();
143       }
144     }
145     if (specialAspectName == null || specialAspectName.trim().length() == 0) {
146       specialAspectName = className;
147     }
148
149     ClassInfo classInfo = JavaClassInfo.getClassInfo(aspectClass);
150     ClassLoader JavaDoc loader = aspectClass.getClassLoader();
151
152     // create the aspect definition
153
AspectDefinition aspectDef = new AspectDefinition(specialAspectName, classInfo, systemDef);
154     //TODO: if this XML centric deployment is supposed to PRESERVE @Aspect values, then it is broken
155
aspectDef.setContainerClassName(containerClassName);
156     aspectDef.setDeploymentModel(DeploymentModel.getDeploymentModelFor(deploymentModelAsString));
157
158     parsePointcutElements(aspectElement, aspectDef); //needed to support undefined named pointcut in Attributes AW-152
159

160     // load the different aspect model and let them define their aspects
161
AspectModelManager.defineAspect(classInfo, aspectDef, loader);
162
163     // parse the aspect info
164
parseParameterElements(aspectElement, aspectDef);
165     parsePointcutElements(aspectElement, aspectDef); //reparse pc for XML override (AW-152)
166
parseAdviceElements(aspectElement, aspectDef, JavaClassInfo.getClassInfo(aspectClass));
167     parseIntroduceElements(aspectElement, aspectDef, "", aspectClass.getClassLoader());
168     return aspectDef;
169   }
170
171   /**
172    * Parses the definition DOM document.
173    *
174    * @param loader the current class loader
175    * @param document the defintion as a document
176    * @return the definitions
177    */

178   public static Set JavaDoc parse(ClassLoader JavaDoc loader, Document JavaDoc document) {
179     // parse the transformation scopes
180
return parseSystemElements(loader, document.getDocumentElement());
181   }
182
183   /**
184    * Parses the <tt>system</tt> elements.
185    *
186    * @param loader the current class loader
187    * @param root the root element
188    */

189   private static Set JavaDoc parseSystemElements(ClassLoader JavaDoc loader, Element JavaDoc root) {
190     Set JavaDoc systemDefs = new HashSet JavaDoc();
191     
192     NodeList JavaDoc rootNodes = root.getChildNodes();
193     for (int i = 0; i < rootNodes.getLength(); i++) {
194       Node JavaDoc childNode = rootNodes.item(i);
195       if(childNode.getNodeName().equals("system")) {
196         Element JavaDoc systemElement = (Element JavaDoc) childNode;
197         SystemDefinition definition = parseSystemElement(loader, systemElement, getBasePackage(systemElement));
198         if (definition != null) {
199           systemDefs.add(definition);
200         }
201       }
202     }
203     return systemDefs;
204   }
205
206   /**
207    * Parses the <tt>system</tt> elements.
208    *
209    * @param loader the current class loader
210    * @param systemElement the system element
211    * @param basePackage the base package
212    * @return the definition for the system
213    */

214   private static SystemDefinition parseSystemElement(ClassLoader JavaDoc loader,
215                                                      Element JavaDoc systemElement,
216                                                      String JavaDoc basePackage) {
217     String JavaDoc uuid = systemElement.getAttribute("id");
218     if (uuid == null || uuid.equals("")) {
219       throw new DefinitionException("system UUID must be specified");
220     }
221     SystemDefinition definition = new SystemDefinition(uuid);
222
223     // add the virtual aspect
224
addVirtualAspect(definition);
225
226     // parse the global pointcuts
227
List JavaDoc globalPointcuts = parseGlobalPointcutDefs(systemElement);
228     
229     //FIXME: systemDef should link a namespace, + remove static hashmap in Namespace (uuid clash in parallel CL)
230
ExpressionNamespace systemNamespace = ExpressionNamespace.getNamespace(definition.getUuid());
231     for (Iterator JavaDoc iterator = globalPointcuts.iterator(); iterator.hasNext();) {
232       PointcutInfo pointcutInfo = (PointcutInfo) iterator.next();
233       systemNamespace.addExpressionInfo(
234               pointcutInfo.name, new ExpressionInfo(pointcutInfo.expression, systemNamespace.getName())
235       );
236     }
237
238     // parse the global deployment scopes definitions
239
parseDeploymentScopeDefs(systemElement, definition);
240
241     // parse the global advisable definitions
242
parseAdvisableDefs(systemElement, definition);
243
244     // parse the include, exclude and prepare elements
245
parseIncludePackageElements(systemElement, definition, basePackage);
246     parseExcludePackageElements(systemElement, definition, basePackage);
247     parsePrepareElements(systemElement, definition, basePackage);
248
249     // parse without package elements
250
parseAspectElements(loader, systemElement, definition, basePackage, globalPointcuts);
251
252     // parse without package elements
253
parseMixinElements(loader, systemElement, definition, basePackage);
254
255     // parse with package elements
256
parsePackageElements(loader, systemElement, definition, basePackage, globalPointcuts);
257
258     // add all deployment scopes to the virtual advice
259
DefinitionParserHelper.attachDeploymentScopeDefsToVirtualAdvice(definition);
260
261     return definition;
262   }
263
264   /**
265    * Parses the global pointcuts.
266    *
267    * @param systemElement the system element
268    * @return a list with the pointcuts
269    */

270   private static List JavaDoc parseGlobalPointcutDefs(Element JavaDoc systemElement) {
271     List JavaDoc globalPointcuts = new ArrayList JavaDoc();
272     
273     NodeList JavaDoc childNodes = systemElement.getChildNodes();
274     for (int i = 0; i < childNodes.getLength(); i++) {
275       Node JavaDoc childNode = childNodes.item(i);
276       if (childNode.getNodeName().equals("pointcut")) {
277         Element JavaDoc pointcutElement = (Element JavaDoc) childNode;
278         PointcutInfo pointcutInfo = new PointcutInfo();
279         pointcutInfo.name = pointcutElement.getAttribute("name");
280         pointcutInfo.expression = pointcutElement.getAttribute("expression").trim();
281         // pointcut CDATA is expression unless already specified as an attribute
282
if (pointcutInfo.expression == null || pointcutInfo.expression.trim().length() == 0) {
283           pointcutInfo.expression = getText(pointcutElement).trim().replace('\n', ' ');
284         }
285         globalPointcuts.add(pointcutInfo);
286       }
287     }
288
289     return globalPointcuts;
290   }
291
292   /**
293    * Parses the global deployment-scope elements.
294    *
295    * @param systemElement the system element
296    * @param definition
297    */

298   private static void parseDeploymentScopeDefs(Element JavaDoc systemElement, SystemDefinition definition) {
299     NodeList JavaDoc childNodes = systemElement.getChildNodes();
300     for (int i = 0; i < childNodes.getLength(); i++) {
301       Node JavaDoc childNode = childNodes.item(i);
302       if (childNode.getNodeName().equals("deployment-scope")) {
303         Element JavaDoc deploymentScopeElement = (Element JavaDoc) childNode;
304         String JavaDoc name = deploymentScopeElement.getAttribute("name");
305         String JavaDoc expression = deploymentScopeElement.getAttribute("expression");
306         // pointcut CDATA is expression unless already specified as an attribute
307
if (expression == null || expression.trim().length() == 0) {
308           expression = getText(deploymentScopeElement).trim();
309         }
310         DefinitionParserHelper.createAndAddDeploymentScopeDef(name, expression, definition);
311       }
312     }
313   }
314
315   /**
316    * Parses the global advisable elements.
317    *
318    * @param systemElement the system element
319    * @param definition
320    */

321   private static void parseAdvisableDefs(Element JavaDoc systemElement, SystemDefinition definition) {
322     NodeList JavaDoc childNodes = systemElement.getChildNodes();
323     for (int i = 0; i < childNodes.getLength(); i++) {
324       Node JavaDoc childNode = childNodes.item(i);
325       if (childNode.getNodeName().equals("advisable")) {
326         Element JavaDoc advisableElement = (Element JavaDoc) childNode;
327         String JavaDoc pointcutTypes = advisableElement.getAttribute("pointcut-type");
328         if (pointcutTypes == null || pointcutTypes.trim().length() == 0) {
329           pointcutTypes = "all";
330         }
331         String JavaDoc expression = advisableElement.getAttribute("expression");
332         // pointcut CDATA is expression unless already specified as an attribute
333
if (expression == null || expression.trim().length() == 0) {
334           expression = getText(advisableElement).trim();
335         }
336         handleAdvisableDefinition(definition, expression, pointcutTypes);
337       }
338     }
339   }
340
341   /**
342    * Parses the definition DOM document.
343    *
344    * @param loader the current class loader
345    * @param systemElement the system element
346    * @param definition the definition
347    * @param basePackage the base package
348    * @param globalPointcuts the global pointcuts
349    */

350   private static void parsePackageElements(ClassLoader JavaDoc loader, Element JavaDoc systemElement, SystemDefinition definition,
351                                            String JavaDoc basePackage, List JavaDoc globalPointcuts) {
352     NodeList JavaDoc childNodes = systemElement.getChildNodes();
353     for (int i = 0; i < childNodes.getLength(); i++) {
354       Node JavaDoc childNode = childNodes.item(i);
355       if (childNode.getNodeName().equals("package")) {
356         Element JavaDoc packageElement = (Element JavaDoc) childNode;
357         String JavaDoc packageName = basePackage + getPackage(packageElement);
358         parseAspectElements(loader, packageElement, definition, packageName, globalPointcuts);
359         parseMixinElements(loader, packageElement, definition, packageName);
360         parseAdvisableDefs(packageElement, definition);
361       }
362     }
363   }
364
365   /**
366    * Parses the <tt>aspect</tt> elements.
367    *
368    * @param loader the current class loader
369    * @param systemElement the system element
370    * @param definition the definition object
371    * @param packageName the package name
372    * @param globalPointcuts the global pointcuts
373    */

374   private static void parseAspectElements(ClassLoader JavaDoc loader,
375                                           Element JavaDoc systemElement,
376                                           SystemDefinition definition,
377                                           String JavaDoc packageName,
378                                           List JavaDoc globalPointcuts) {
379     NodeList JavaDoc childNodes = systemElement.getChildNodes();
380     for (int i = 0; i < childNodes.getLength(); i++) {
381       Node JavaDoc childNode = childNodes.item(i);
382       if (childNode.getNodeName().equals("aspect")) {
383         Element JavaDoc aspectElement = (Element JavaDoc) childNode;
384         
385         String JavaDoc aspectName = aspectElement.getAttribute("name");
386         String JavaDoc className = aspectElement.getAttribute("class");
387         String JavaDoc deploymentModel = aspectElement.getAttribute("deployment-model");
388         String JavaDoc containerClassName = aspectElement.getAttribute("container");
389
390         // class is mandatory
391
if (Strings.isNullOrEmpty(className)) {
392           System.err.println("Warning: could not load aspect without 'class=..' attribute");
393           new Exception JavaDoc().printStackTrace();
394           continue;
395         }
396
397         String JavaDoc aspectClassName = packageName + className;
398         if (aspectName == null || aspectName.trim().length() == 0) {
399           aspectName = aspectClassName;
400         }
401
402         // create the aspect definition
403
ClassInfo aspectClassInfo;
404         try {
405           aspectClassInfo = AsmClassInfo.getClassInfo(aspectClassName, loader);
406         } catch (Exception JavaDoc e) {
407           System.err.println("Warning: could not load aspect " + aspectClassName + " from " + loader + "; "
408                              + e.toString());
409           e.printStackTrace();
410           continue;
411         }
412
413         AspectDefinition aspectDef = new AspectDefinition(aspectName, aspectClassInfo, definition);
414
415         // add the global pointcuts to the aspect
416
for (Iterator JavaDoc it = globalPointcuts.iterator(); it.hasNext();) {
417           PointcutInfo pointcutInfo = (PointcutInfo) it.next();
418           DefinitionParserHelper.createAndAddPointcutDefToAspectDef(
419                   pointcutInfo.name,
420                   pointcutInfo.expression,
421                   aspectDef
422           );
423         }
424         parsePointcutElements(aspectElement, aspectDef); //needed to support undefined named pointcut in Attributes AW-152
425

426         // load the different aspect model and let them define their aspects
427
AspectModelManager.defineAspect(aspectClassInfo, aspectDef, loader);
428
429         // parse the class bytecode annotations
430
AspectAnnotationParser.parse(aspectClassInfo, aspectDef, loader);
431
432         // XML definition settings always overrides attribute definition settings AW-357
433
if (!Strings.isNullOrEmpty(deploymentModel)) {
434           aspectDef.setDeploymentModel(DeploymentModel.getDeploymentModelFor(deploymentModel));
435         }
436         if (!Strings.isNullOrEmpty(aspectName)) {
437           aspectDef.setName(aspectName);
438         }
439         if (!Strings.isNullOrEmpty(containerClassName)) {
440           aspectDef.setContainerClassName(containerClassName);
441         }
442
443         // parse the aspect info
444
parseParameterElements(aspectElement, aspectDef);
445         parsePointcutElements(aspectElement, aspectDef); // reparse pc for XML override (AW-152)
446
parseAdviceElements(aspectElement, aspectDef, aspectClassInfo);
447         parseIntroduceElements(aspectElement, aspectDef, packageName, loader);
448
449         definition.addAspect(aspectDef);
450       }
451     }
452   }
453
454   /**
455    * Parses the <tt>mixin</tt> elements.
456    *
457    * @param loader the current class loader
458    * @param systemElement the system element
459    * @param systemDefinition the system definition
460    * @param packageName the package name
461    */

462   private static void parseMixinElements(ClassLoader JavaDoc loader,
463                                          Element JavaDoc systemElement,
464                                          SystemDefinition systemDefinition,
465                                          String JavaDoc packageName) {
466     NodeList JavaDoc childNodes = systemElement.getChildNodes();
467     for (int i = 0; i < childNodes.getLength(); i++) {
468       Node JavaDoc childNode = childNodes.item(i);
469       if (childNode.getNodeName().equals("mixin")) {
470         Element JavaDoc mixinElement = (Element JavaDoc) childNode;
471         
472         String JavaDoc className = mixinElement.getAttribute("class");
473         String JavaDoc deploymentModelAsString = mixinElement.getAttribute("deployment-model");
474         boolean isTransient = false;
475         boolean isTransientSetInXML = false;
476         String JavaDoc transientValue = mixinElement.getAttribute("transient");
477         if(transientValue!=null) {
478           isTransient = transientValue.equalsIgnoreCase("true");
479           isTransientSetInXML = true;
480         }
481         
482         String JavaDoc factoryClassName = mixinElement.getAttribute("factory");
483         String JavaDoc expression = mixinElement.getAttribute("bind-to");
484         
485         String JavaDoc mixinClassName = packageName + className;
486
487         // create the mixin definition
488
ClassInfo mixinClassInfo;
489         try {
490           mixinClassInfo = AsmClassInfo.getClassInfo(mixinClassName, loader);
491         } catch (Exception JavaDoc e) {
492           System.err.println("Warning: could not load mixin " + mixinClassName + " from " + loader + "; "
493                              + e.toString());
494           e.printStackTrace();
495           continue;
496         }
497
498         DeploymentModel deploymentModel = deploymentModelAsString == null
499                                           || deploymentModelAsString.trim().length() == 0 ? DeploymentModel.PER_INSTANCE
500             : DeploymentModel.getDeploymentModelFor(deploymentModelAsString);
501
502         MixinDefinition mixinDefinition = DefinitionParserHelper.createAndAddMixinDefToSystemDef(mixinClassInfo,
503                                                                                                  expression,
504                                                                                                  deploymentModel,
505                                                                                                  isTransient,
506                                                                                                  systemDefinition);
507
508         // parse the class bytecode annotations
509
MixinAnnotationParser.parse(mixinClassInfo, mixinDefinition);
510
511         // XML definition settings always overrides attribute definition settings if present
512
if (!Strings.isNullOrEmpty(deploymentModelAsString)) {
513           mixinDefinition.setDeploymentModel(DeploymentModel.getDeploymentModelFor(deploymentModelAsString));
514         }
515         if (!Strings.isNullOrEmpty(factoryClassName)) {
516           mixinDefinition.setFactoryClassName(factoryClassName);
517         }
518         if (isTransientSetInXML) {
519           mixinDefinition.setTransient(isTransient);
520         }
521
522         parseParameterElements(mixinElement, mixinDefinition);
523       }
524     }
525   }
526
527   /**
528    * Adds a virtual system aspect to the definition. Needed to do various tricks.
529    *
530    * @param definition
531    */

532   public static void addVirtualAspect(SystemDefinition definition) {
533     Class JavaDoc clazz = Virtual.class;
534     String JavaDoc aspectName = clazz.getName();
535     ClassInfo aspectClassInfo = JavaClassInfo.getClassInfo(clazz);
536     AspectDefinition aspectDef = new AspectDefinition(aspectName, aspectClassInfo, definition);
537     try {
538       MethodInfo methodInfo = JavaMethodInfo.getMethodInfo(clazz.getDeclaredMethod("virtual", new Class JavaDoc[]{}));
539       aspectDef.addBeforeAdviceDefinition(
540               new AdviceDefinition(
541                       methodInfo.getName(),
542                       AdviceType.BEFORE,
543                       null,
544                       aspectName,
545                       aspectName,
546                       null,
547                       methodInfo,
548                       aspectDef
549               )
550       );
551     } catch (NoSuchMethodException JavaDoc e) {
552       throw new Error JavaDoc("virtual aspect [" + aspectName + "] does not have expected method: " + e.toString());
553     }
554     definition.addAspect(aspectDef);
555   }
556
557   /**
558    * Parses the aspectElement parameters.
559    *
560    * @param aspectElement the aspect element
561    * @param aspectDef the aspect def
562    */

563   private static void parseParameterElements(Element JavaDoc aspectElement, AspectDefinition aspectDef) {
564     NodeList JavaDoc childNodes = aspectElement.getChildNodes();
565     for (int i = 0; i < childNodes.getLength(); i++) {
566       Node JavaDoc childNode = childNodes.item(i);
567       if (childNode.getNodeName().equals("param")) {
568         Element JavaDoc paramElement = (Element JavaDoc) childNode;
569         aspectDef.addParameter(paramElement.getAttribute("name"), paramElement.getAttribute("value"));
570       }
571     }
572   }
573
574   /**
575    * Parses the mixinElement parameters.
576    *
577    * @param mixinElement the mixin element
578    * @param mixinDef the mixin def
579    */

580   private static void parseParameterElements(Element JavaDoc mixinElement, MixinDefinition mixinDef) {
581     NodeList JavaDoc childNodes = mixinElement.getChildNodes();
582     for (int i = 0; i < childNodes.getLength(); i++) {
583       Node JavaDoc childNode = childNodes.item(i);
584       if (childNode.getNodeName().equals("param")) {
585         Element JavaDoc paramElement = (Element JavaDoc) childNode;
586         mixinDef.addParameter(paramElement.getAttribute("name"), paramElement.getAttribute("value"));
587       }
588     }
589   }
590
591   /**
592    * Parses the pointcuts.
593    *
594    * @param aspectElement the aspect element
595    * @param aspectDef the system definition
596    */

597   private static void parsePointcutElements(Element JavaDoc aspectElement, AspectDefinition aspectDef) {
598     NodeList JavaDoc aspectNodes = aspectElement.getChildNodes();
599     for (int i = 0; i < aspectNodes.getLength(); i++) {
600       Node JavaDoc childNode = aspectNodes.item(i);
601       if(childNode.getNodeType()!=Node.ELEMENT_NODE) {
602         continue;
603       }
604       Element JavaDoc childElement = (Element JavaDoc) childNode;
605       if (childElement.getNodeName().equals("pointcut")) {
606         String JavaDoc name = childElement.getAttribute("name");
607         String JavaDoc expression = childElement.getAttribute("expression");
608         // pointcut CDATA is expression unless already specified as an attribute
609
if (expression == null || expression.trim().length() == 0) {
610           expression = getText(childElement).trim();
611         }
612         DefinitionParserHelper.createAndAddPointcutDefToAspectDef(name, expression, aspectDef);
613       } else if (childElement.getNodeName().equals("deployment-scope")) {
614         String JavaDoc name = childElement.getAttribute("name");
615         String JavaDoc expression = childElement.getAttribute("expression");
616         // pointcut CDATA is expression unless already specified as an attribute
617
if (expression == null) {
618           expression = getText(childElement).trim();
619         }
620         DefinitionParserHelper.createAndAddDeploymentScopeDef(
621                 name, expression, aspectDef.getSystemDefinition()
622         );
623       } else if (childElement.getNodeName().equals("advisable")) {
624         String JavaDoc expression = childElement.getAttribute("expression");
625         String JavaDoc pointcutTypes = childElement.getAttribute("pointcut-type");
626         if (expression == null || expression.trim().length() == 0) {
627           expression = getText(childElement).trim();
628         }
629         handleAdvisableDefinition(aspectDef.getSystemDefinition(), expression, pointcutTypes);
630       }
631     }
632   }
633   
634   public static String JavaDoc getText(Element JavaDoc element) {
635     NodeList JavaDoc childNodes = element.getChildNodes();
636     for (int i = 0; i < childNodes.getLength(); i++) {
637       Node JavaDoc childNode = childNodes.item(i);
638       if(childNode.getNodeType()==Node.TEXT_NODE) {
639         return ((Text JavaDoc) childNode).getData();
640       }
641     }
642     return "";
643   }
644
645   /**
646    * Parses the advices.
647    *
648    * @param aspectElement the aspect element
649    * @param aspectDef the system definition
650    * @param aspectClassInfo the aspect class
651    */

652   private static void parseAdviceElements(Element JavaDoc aspectElement, AspectDefinition aspectDef, ClassInfo aspectClassInfo) {
653     NodeList JavaDoc childNodes = aspectElement.getChildNodes();
654     for (int i = 0; i < childNodes.getLength(); i++) {
655       Node JavaDoc childNode = childNodes.item(i);
656       if (childNode.getNodeName().equals("advice")) {
657         Element JavaDoc adviceElement = (Element JavaDoc) childNode;
658
659         String JavaDoc name = adviceElement.getAttribute("name");
660         String JavaDoc type = adviceElement.getAttribute("type");
661         String JavaDoc bindTo = adviceElement.getAttribute("bind-to");
662
663         MethodInfo method = DefinitionParserHelper.createMethodInfoForAdviceFQN(name, aspectDef, aspectClassInfo);
664         DefinitionParserHelper.createAndAddAdviceDefsToAspectDef(type, bindTo, name, method, aspectDef);
665
666         NodeList JavaDoc bindNodes = adviceElement.getChildNodes();
667         for (int j = 0; j < bindNodes.getLength(); j++) {
668           Node JavaDoc bindToNode = bindNodes.item(j);
669           if (bindToNode.getNodeName().equals("bind-to")) {
670             Element JavaDoc bindToElement = (Element JavaDoc) bindToNode;
671             String JavaDoc pointcut = bindToElement.getAttribute("pointcut");
672             DefinitionParserHelper.createAndAddAdviceDefsToAspectDef(type, pointcut, name, method, aspectDef);
673           }
674         }
675       }
676     }
677   }
678
679   /**
680    * Parses the interface introductions.
681    *
682    * @param aspectElement the aspect element
683    * @param aspectDef the system definition
684    * @param packageName
685    * @param loader
686    */

687   private static void parseIntroduceElements(Element JavaDoc aspectElement,
688                                              AspectDefinition aspectDef,
689                                              String JavaDoc packageName,
690                                              ClassLoader JavaDoc loader) {
691     NodeList JavaDoc childNodes = aspectElement.getChildNodes();
692     for (int i = 0; i < childNodes.getLength(); i++) {
693       Node JavaDoc childNode = childNodes.item(i);
694       if (childNode.getNodeName().equals("introduce")) {
695         Element JavaDoc introduceElement = (Element JavaDoc) childNode;
696         
697         String JavaDoc klass = introduceElement.getAttribute("class");
698         String JavaDoc name = introduceElement.getAttribute("name");
699         String JavaDoc bindTo = introduceElement.getAttribute("bind-to");
700
701         // default name = FQN
702
String JavaDoc fullClassName = packageName + klass;
703         if (name == null || name.length() == 0) {
704           name = fullClassName;
705         }
706
707         // load the class info to determine if it is a pure interface introduction
708
ClassInfo introductionClassInfo;
709         try {
710           introductionClassInfo = AsmClassInfo.getClassInfo(fullClassName, loader);
711         } catch (Exception JavaDoc e) {
712           throw new DefinitionException("could not find interface introduction: " + packageName + klass + "; "
713                                         + e.getMessage());
714         }
715
716         // pure interface introduction
717
if (introductionClassInfo.isInterface()) {
718           DefinitionParserHelper
719               .createAndAddInterfaceIntroductionDefToAspectDef(bindTo, name, fullClassName, aspectDef);
720
721           // handles nested "bind-to" elements
722
NodeList JavaDoc bindToNodes = introduceElement.getChildNodes();
723           for (int j = 0; j < bindToNodes.getLength(); j++) {
724             Node JavaDoc bindToNode = bindToNodes.item(j);
725             if (bindToNode.getNodeName().equals("bindTo")) {
726               Element JavaDoc bindToElement = (Element JavaDoc) bindToNode;
727               String JavaDoc pointcut = bindToElement.getAttribute("pointcut");
728               DefinitionParserHelper.createAndAddInterfaceIntroductionDefToAspectDef(pointcut, name, fullClassName,
729                                                                                      aspectDef);
730             }
731           }
732         }
733       }
734     }
735   }
736
737   /**
738    * Retrieves and returns the package.
739    *
740    * @param packageElement the package element
741    * @return the package as a string ending with DOT, or empty string
742    */

743   private static String JavaDoc getPackage(Element JavaDoc packageElement) {
744     String JavaDoc packageName = packageElement.getAttribute("name");
745     if (packageName != null) {
746       if (packageName.endsWith(".*")) {
747         return packageName.substring(0, packageName.length() - 1);
748       } else if (!packageName.endsWith(".")) {
749         return packageName + ".";
750       }
751     }
752     return "";
753   }
754
755   /**
756    * Parses the <tt>include</tt> elements.
757    *
758    * @param root the root element
759    * @param definition the definition object
760    * @param packageName the package name
761    */

762   private static void parseIncludePackageElements(Element JavaDoc root,
763                                                   SystemDefinition definition,
764                                                   String JavaDoc packageName) {
765     NodeList JavaDoc childNodes = root.getChildNodes();
766     for (int i = 0; i < childNodes.getLength(); i++) {
767       Node JavaDoc includeNode = childNodes.item(i);
768       if (includeNode.getNodeName().equals("include")) {
769         Element JavaDoc includeElement = (Element JavaDoc) includeNode;
770         String JavaDoc packageValue = includeElement.getAttribute("package");
771
772         String JavaDoc includePackage = "";
773         // handle base package
774
if (packageName.endsWith(".*")) {
775           includePackage = packageName.substring(0, packageName.length() - 2);
776         } else if (packageName.endsWith(".")) {
777           includePackage = packageName.substring(0, packageName.length() - 1);
778         }
779
780         // handle exclude package
781
includePackage = packageName + packageValue.trim();
782         if (includePackage.endsWith(".*")) {
783           includePackage = includePackage.substring(0, includePackage.length() - 2);
784         } else if (includePackage.endsWith(".")) {
785           includePackage = includePackage.substring(0, includePackage.length() - 1);
786         }
787         if (includePackage.length() != 0) {
788           definition.addIncludePackage(includePackage);
789         }
790       }
791     }
792   }
793
794   /**
795    * Parses the <tt>exclude</tt> elements.
796    *
797    * @param root the root element
798    * @param definition the definition object
799    * @param packageName the package name
800    */

801   private static void parseExcludePackageElements(Element JavaDoc root, SystemDefinition definition, String JavaDoc packageName) {
802     NodeList JavaDoc childNodes = root.getChildNodes();
803     for (int i = 0; i < childNodes.getLength(); i++) {
804       Node JavaDoc childNode = childNodes.item(i);
805       if (childNode.getNodeName().equals("exclude")) {
806         Element JavaDoc excludeElement = (Element JavaDoc) childNode;
807
808         String JavaDoc excludeValue = excludeElement.getAttribute("package");
809
810         String JavaDoc excludePackage = "";
811         // handle base package
812
if (packageName.endsWith(".*")) {
813           excludePackage = packageName.substring(0, packageName.length() - 2);
814         } else if (packageName.endsWith(".")) {
815           excludePackage = packageName.substring(0, packageName.length() - 1);
816         }
817
818         // handle exclude package
819
excludePackage = packageName + excludeValue.trim();
820         if (excludePackage.endsWith(".*")) {
821           excludePackage = excludePackage.substring(0, excludePackage.length() - 2);
822         } else if (excludePackage.endsWith(".")) {
823           excludePackage = excludePackage.substring(0, excludePackage.length() - 1);
824         }
825         if (excludePackage.length() != 0) {
826           definition.addExcludePackage(excludePackage);
827         }
828       }
829     }
830   }
831
832   /**
833    * Parses the <tt>prepare</tt> elements.
834    *
835    * @param root the root element
836    * @param definition the definition object
837    * @param packageName the base package name
838    */

839   private static void parsePrepareElements(Element JavaDoc root,
840                                           SystemDefinition definition,
841                                           String JavaDoc packageName) {
842     NodeList JavaDoc childNodes = root.getChildNodes();
843     for (int i = 0; i < childNodes.getLength(); i++) {
844       Node JavaDoc childNode = childNodes.item(i);
845       if (childNode.getNodeName().equals("prepare")) {
846         Element JavaDoc prepareElement = (Element JavaDoc) childNode;
847         String JavaDoc packageValue = prepareElement.getAttribute("package");
848         
849         String JavaDoc preparePackage = "";
850
851         // handle base package
852
if (packageName.endsWith(".*")) {
853           preparePackage = packageName.substring(0, packageName.length() - 2);
854         } else if (packageName.endsWith(".")) {
855           preparePackage = packageName.substring(0, packageName.length() - 1);
856         }
857
858         // handle prepare package
859
preparePackage = packageName + packageValue.trim();
860         if (preparePackage.endsWith(".*")) {
861           preparePackage = preparePackage.substring(0, preparePackage.length() - 2);
862         } else if (preparePackage.endsWith(".")) {
863           preparePackage = preparePackage.substring(0, preparePackage.length() - 1);
864         }
865         if (preparePackage.length() != 0) {
866           definition.addPreparePackage(preparePackage);
867         }
868       }
869     }
870   }
871
872   /**
873    * Retrieves and returns the base package for a system element
874    *
875    * @param system a system element
876    * @return the base package
877    */

878   private static String JavaDoc getBasePackage(Element JavaDoc system) {
879     String JavaDoc basePackage = "";
880     NamedNodeMap JavaDoc attrs = system.getAttributes();
881     for (int i = 0; i < attrs.getLength(); i++) {
882       Node JavaDoc item = attrs.item(i);
883       if (item.getNodeName().equalsIgnoreCase("base-package")) {
884         basePackage = ((Attr JavaDoc) item).getValue().trim();
885         if (basePackage.endsWith(".*")) {
886           basePackage = basePackage.substring(0, basePackage.length() - 1);
887         } else if (!basePackage.endsWith(".")) {
888           basePackage += ".";
889         }
890         break;
891       }
892     }
893     
894 /*
895     for (Iterator it2 = system.attributeIterator(); it2.hasNext();) {
896       Attribute attribute = (Attribute) it2.next();
897       if (attribute.getName().trim().equalsIgnoreCase("base-package")) {
898         basePackage = attribute.getValue().trim();
899         if (basePackage.endsWith(".*")) {
900           basePackage = basePackage.substring(0, basePackage.length() - 1);
901         } else if (basePackage.endsWith(".")) {
902           // skip
903         } else {
904           basePackage += ".";
905         }
906         break;
907       } else {
908         continue;
909       }
910     }
911 */

912     return basePackage;
913   }
914
915   /**
916    * Struct with pointcut info.
917    */

918   private static class PointcutInfo {
919     public String JavaDoc name;
920     public String JavaDoc expression;
921   }
922
923   /**
924    * Handles the advisable definition.
925    *
926    * @param definition
927    * @param withinPointcut
928    * @param pointcutTypes
929    */

930   private static void handleAdvisableDefinition(SystemDefinition definition,
931                                                 String JavaDoc withinPointcut,
932                                                 String JavaDoc pointcutTypes) {
933     // add the Advisable Mixin with the expression defined to the system definitions
934
definition.addMixinDefinition(
935             DefinitionParserHelper.createAndAddMixinDefToSystemDef(
936                     AdvisableImpl.CLASS_INFO,
937                     withinPointcut,
938                     DeploymentModel.PER_INSTANCE,
939                     false, // advisble mixin is NOT transient
940
definition
941             )
942     );
943
944     boolean hasAllPointcuts = false;
945     boolean hasExecutionPointcut = false;
946     boolean hasCallPointcut = false;
947     boolean hasSetPointcut = false;
948     boolean hasGetPointcut = false;
949     boolean hasHandlerPointcut = false;
950     if (pointcutTypes == null ||
951             pointcutTypes.equals("") ||
952             pointcutTypes.equalsIgnoreCase("all")) {
953       hasAllPointcuts = true;
954     } else {
955       StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(pointcutTypes, "|");
956       while (tokenizer.hasMoreTokens()) {
957         String JavaDoc token = tokenizer.nextToken();
958         if (token.trim().equalsIgnoreCase("all")) {
959           hasAllPointcuts = true;
960           break;
961         } else if (token.trim().equalsIgnoreCase("execution")) {
962           hasExecutionPointcut = true;
963         } else if (token.trim().equalsIgnoreCase("call")) {
964           hasCallPointcut = true;
965         } else if (token.trim().equalsIgnoreCase("set")) {
966           hasSetPointcut = true;
967         } else if (token.trim().equalsIgnoreCase("getDefault")) {
968           hasGetPointcut = true;
969         } else if (token.trim().equalsIgnoreCase("handler")) {
970           hasHandlerPointcut = true;
971         }
972       }
973     }
974     if (hasAllPointcuts || hasExecutionPointcut) {
975       DefinitionParserHelper.createAndAddAdvisableDef(
976               // TODO add ctor to expression - BUT: problem with mixin and ctor, ordering issue, Jp.invoke() calls field instance that has not been init yet in ctor (since body not invoked)
977
//"(( execution(!static * *.*(..)) || execution(*.new(..)) ) && " + withinPointcut + ')',
978
// we exclude static method execution since we need the advisable instance
979
"(execution(!static * *.*(..)) && " + withinPointcut + ')',
980               definition
981       );
982     }
983     if (hasAllPointcuts || hasCallPointcut) {
984       DefinitionParserHelper.createAndAddAdvisableDef(
985               // TODO add ctor to expression - BUT: problem with mixin and ctor, ordering issue, Jp.invoke() calls field instance that has not been init yet in ctor (since body not invoked) //"(call(!static * " + typePattern + ".*(..)) || call(" + typePattern + ".new(..)))",
986
// we exclude static method withincode since we need the advisable instance
987
// as a consequence, withincode(staticinitialization(..)) is also excluded
988
"(call(* *.*(..)) && withincode(!static * *.*(..)) && " + withinPointcut + ')',
989               definition
990       );
991     }
992     if (hasAllPointcuts || hasSetPointcut) {
993       DefinitionParserHelper.createAndAddAdvisableDef(
994               // we exclude static method withincode since we need the advisable instance
995
// as a consequence, withincode(staticinitialization(..)) is also excluded
996
"(set(* *.*) && withincode(!static * *.*(..)) && " + withinPointcut + ')',
997               definition
998       );
999     }
1000    if (hasAllPointcuts || hasGetPointcut) {
1001      DefinitionParserHelper.createAndAddAdvisableDef(
1002              // we exclude static method withincode since we need the advisable instance
1003
// as a consequence, withincode(staticinitialization(..)) is also excluded
1004
"(getDefault(* *.*) && withincode(!static * *.*(..)) && " + withinPointcut + ')',
1005              definition
1006      );
1007    }
1008    if (hasAllPointcuts || hasHandlerPointcut) {
1009      DefinitionParserHelper.createAndAddAdvisableDef(
1010              // we exclude static method withincode since we need the advisable instance
1011
// as a consequence, withincode(staticinitialization(..)) is also excluded
1012
"(handler(*..*) && withincode(!static * *.*(..)) && " + withinPointcut + ')',
1013              definition
1014      );
1015    }
1016  }
1017}
Popular Tags