View Javadoc

1   /*************************************************
2    * Copyright (c) Shen Li. All rights reserved.  *
3    * http://joyaop.sourceforge.net                *
4    * -------------------------------------------- *
5    * Distributable under LGPL license.            *
6    * See terms of license at gnu.org.             *
7    ************************************************/
8   package net.sf.joyaop.config;
9   
10  import net.sf.joyaop.AbstractInterceptor;
11  import net.sf.joyaop.AspectRuntimeException;
12  import net.sf.joyaop.Interceptor;
13  import net.sf.joyaop.framework.AspectRuntime;
14  import net.sf.joyaop.framework.InterceptorAspect;
15  import net.sf.joyaop.framework.InterfaceAspect;
16  import net.sf.joyaop.framework.MixinAspect;
17  import net.sf.joyaop.framework.Pointcut;
18  import net.sf.joyaop.impl.aspect.AbstractGenericInterceptorAspectImpl;
19  import net.sf.joyaop.impl.aspect.AopAllianceMethodInterceptorAspectImpl;
20  import net.sf.joyaop.impl.aspect.DecoratorAspectImpl;
21  import net.sf.joyaop.impl.aspect.GenericInterceptorAspectImpl;
22  import net.sf.joyaop.impl.aspect.InterfaceAspectImpl;
23  import net.sf.joyaop.impl.aspect.MixinAspectImpl;
24  import net.sf.joyaop.util.ClassUtils;
25  import org.aopalliance.intercept.MethodInterceptor;
26  import org.dom4j.Document;
27  import org.dom4j.DocumentException;
28  import org.dom4j.Element;
29  import org.dom4j.io.SAXReader;
30  
31  import java.util.ArrayList;
32  import java.util.HashMap;
33  import java.util.Iterator;
34  import java.util.List;
35  import java.util.Map;
36  
37  /***
38   * @author Shen Li
39   */
40  public class XmlConfiguration implements Configuration {
41      private static final String DEFAULT_CONFIG_FILE_NAME = "aop.xml";
42  
43      private static final String INTERCEPTOR = "interceptor";
44      private static final String MIXIN = "mixin";
45      private static final String INTERFACE = "interface";
46      private static final String ASPECT_SCOPE = "scope";
47      private static final String ASPECT_CLASS = "class";
48      private static final String MIXIN_INTERFACE = "interface";
49  
50      private static final String EXPR = "expr";
51      private static final String EXPR_NAME = "name";
52  
53      private static final String POINTCUT = "pointcut";
54      private static final String POINTCUT_EXPR = "expr";
55      private static final String POINTCUT_PARAM = "param";
56      private static final String POINTCUT_PARAM_NAME = "name";
57  
58      private static final String INTERCEPTOR_PRECEDENCE = "interceptor-precedence";
59  
60      private final String configFileName;
61  
62      public XmlConfiguration() {
63          this(DEFAULT_CONFIG_FILE_NAME);
64      }
65  
66      public XmlConfiguration(String configFileName) {
67          this.configFileName = configFileName;
68      }
69  
70      public void configure(AspectRuntime aspectRuntime) {
71          Document doc = null;
72          SAXReader reader = new SAXReader();
73          try {
74              doc = reader.read(getClass().getClassLoader().getResourceAsStream(configFileName));
75          } catch (DocumentException e) {
76              throw new AspectRuntimeException(e);
77          }
78  
79          Map mixinElements = new HashMap();
80          Map interceptorElements = new HashMap();
81          Map interfaceElements = new HashMap();
82          PointcutExpressionParser pointcutParser = new PointcutExpressionParser();
83          // assume only one interceptor-precedence element
84          List interceptorPrecedence = new ArrayList();
85          Element rootElement = doc.getRootElement();
86  
87          for (Iterator i = rootElement.elementIterator(); i.hasNext();) {
88              Element element = (Element) i.next();
89              if (INTERCEPTOR.equals(element.getName())) {
90                  interceptorElements.put(element.attribute(ASPECT_CLASS).getValue(), element);
91              } else if (MIXIN.equals(element.getName())) {
92                  mixinElements.put(element.attribute(ASPECT_CLASS).getValue(), element);
93              } else if (INTERFACE.equals(element.getName())) {
94                  interfaceElements.put(element.attribute(ASPECT_CLASS).getValue(), element);
95              } else if (EXPR.equals(element.getName())) {
96                  pointcutParser.addPointcutDefinition(element.attribute(EXPR_NAME).getValue(), element.getTextTrim());
97              } else if (INTERCEPTOR_PRECEDENCE.equals(element.getName())) {
98                  for (Iterator it = element.elementIterator(INTERCEPTOR); it.hasNext();) {
99                      interceptorPrecedence.add(((Element) it.next()).attribute(ASPECT_CLASS).getValue());
100                 }
101             }
102         }
103 
104         for (Iterator i = rootElement.elementIterator(POINTCUT); i.hasNext();) {
105             Element aspectElement = ((Element) i.next());
106             Pointcut pointcut = pointcutParser.parse(aspectElement.attribute(POINTCUT_EXPR).getValue());
107 
108             Map params = new HashMap();
109             for (Iterator it = aspectElement.elementIterator(POINTCUT_PARAM); it.hasNext();) {
110                 Element paramElement = (Element) it.next();
111                 String paramName = paramElement.attribute(POINTCUT_PARAM_NAME).getValue().trim();
112                 String paramValue = paramElement.getTextTrim();
113                 params.put(paramName, paramValue);
114             }
115 
116             for (Iterator it = aspectElement.elementIterator(); it.hasNext();) {
117                 Element element = (Element) it.next();
118                 if (INTERCEPTOR.equals(element.getName())) {
119                     if (interceptorElements.containsKey(element.attribute(ASPECT_CLASS).getValue())) {
120                         element = (Element) interceptorElements.get(element.attribute(ASPECT_CLASS).getValue());
121                     }
122                     InterceptorAspect interceptorAspect =
123                             createInterceptorAspect(element, pointcut, interceptorPrecedence, params);
124                     aspectRuntime.addInterceptor(interceptorAspect);
125                 } else if (MIXIN.equals(element.getName())) {
126                     if (mixinElements.containsKey(element.attribute(ASPECT_CLASS).getValue())) {
127                         element = (Element) mixinElements.get(element.attribute(ASPECT_CLASS).getValue());
128                     }
129                     MixinAspect mixinAspect =
130                             createMixinAspect(element, pointcut, params);
131                     aspectRuntime.addMixin(mixinAspect);
132                 } else if (INTERFACE.equals(element.getName())) {
133                     if (interfaceElements.containsKey(element.attribute(ASPECT_CLASS).getValue())) {
134                         element = (Element) interfaceElements.get(element.attribute(ASPECT_CLASS).getValue());
135                     }
136                     InterfaceAspect interfaceAspect =
137                             createInterfaceAspect(element, pointcut);
138                     aspectRuntime.addInterface(interfaceAspect);
139                 }
140             }
141         }
142     }
143 
144     private InterceptorAspect createInterceptorAspect(Element interceptorElement, Pointcut pointcut,
145                                                       List interceptorPrecedence, Map params) {
146         String aspectClassName = (String) interceptorElement.attribute(ASPECT_CLASS).getValue();
147         Class aspectClass = ClassUtils.loadClass(aspectClassName);
148         InterceptorAspect aspect;
149         if (Interceptor.class.isAssignableFrom(aspectClass)) {
150             aspect = new GenericInterceptorAspectImpl();
151         } else if (AbstractInterceptor.class.isAssignableFrom(aspectClass)) {
152             aspect = new AbstractGenericInterceptorAspectImpl();
153         } else if (MethodInterceptor.class.isAssignableFrom(aspectClass)) {
154             aspect = new AopAllianceMethodInterceptorAspectImpl();
155         } else {
156             aspect = new DecoratorAspectImpl();
157         }
158         aspect.setAspectClass(aspectClass);
159         if (interceptorElement.attribute(ASPECT_SCOPE) != null) {
160             aspect.setScope((String) interceptorElement.attribute(ASPECT_SCOPE).getValue());
161         }
162         aspect.setPointcut(pointcut);
163         int precedence = 0;
164         for (int i = 0; i < interceptorPrecedence.size(); i++) {
165             if (aspectClassName.equals(interceptorPrecedence.get(i))) {
166                 precedence = interceptorPrecedence.size() - i;
167                 break;
168             }
169         }
170         aspect.setPrecedence(precedence);
171         aspect.setParameters(params);
172         return aspect;
173     }
174 
175     private MixinAspect createMixinAspect(Element mixinElement, Pointcut pointcut, Map params) {
176         MixinAspect aspect = new MixinAspectImpl();
177         if (mixinElement.attribute(MIXIN_INTERFACE) == null) {
178             throw new AspectRuntimeException("The interface attribute of the mixin element has not been defined.");
179         }
180         String interfaceClassName = (String) mixinElement.attribute(MIXIN_INTERFACE).getValue();
181         aspect.setInterfaceClass(ClassUtils.loadClass(interfaceClassName));
182         String aspectClassName = (String) mixinElement.attribute(ASPECT_CLASS).getValue();
183         aspect.setAspectClass(ClassUtils.loadClass(aspectClassName));
184         if (mixinElement.attribute(ASPECT_SCOPE) != null) {
185             aspect.setScope((String) mixinElement.attribute(ASPECT_SCOPE).getValue());
186         }
187         aspect.setPointcut(pointcut);
188         aspect.setParameters(params);
189         return aspect;
190     }
191 
192     private InterfaceAspect createInterfaceAspect(Element interfaceElement, Pointcut pointcut) {
193         InterfaceAspect aspect = new InterfaceAspectImpl();
194         String aspectClassName = (String) interfaceElement.attribute(ASPECT_CLASS).getValue();
195         aspect.setAspectClass(ClassUtils.loadClass(aspectClassName));
196         aspect.setPointcut(pointcut);
197         return aspect;
198     }
199 }