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
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 }