1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.seasar.uruma.desc.impl;
17
18 import java.lang.reflect.Field;
19 import java.lang.reflect.Method;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Map.Entry;
26
27 import org.seasar.framework.beans.BeanDesc;
28 import org.seasar.framework.beans.PropertyDesc;
29 import org.seasar.framework.beans.factory.BeanDescFactory;
30 import org.seasar.framework.exception.EmptyRuntimeException;
31 import org.seasar.framework.util.StringUtil;
32 import org.seasar.uruma.annotation.ApplicationContext;
33 import org.seasar.uruma.annotation.AsyncMethod;
34 import org.seasar.uruma.annotation.EventListener;
35 import org.seasar.uruma.annotation.InitializeMethod;
36 import org.seasar.uruma.annotation.PostOpenMethod;
37 import org.seasar.uruma.binding.context.ApplicationContextDef;
38 import org.seasar.uruma.binding.method.EventListenerDef;
39 import org.seasar.uruma.core.UrumaMessageCodes;
40 import org.seasar.uruma.desc.PartActionDesc;
41 import org.seasar.uruma.exception.IllegalMethodException;
42 import org.seasar.uruma.exception.InitializeMethodException;
43 import org.seasar.uruma.exception.MethodInvocationException;
44 import org.seasar.uruma.jobs.ProgressMonitor;
45 import org.seasar.uruma.util.AssertionUtil;
46
47
48
49
50
51
52 public class PartActionDescImpl implements PartActionDesc, UrumaMessageCodes {
53
54 private Class<?> partActionClass;
55
56 private BeanDesc beanDesc;
57
58 private Method initializeMethod;
59
60 private Method postOpenMethod;
61
62 private Map<String, List<Method>> methodsCache = new HashMap<String, List<Method>>();
63
64 private Map<String, Field> fieldsCache = new HashMap<String, Field>();
65
66 private List<EventListenerDef> eventListenerDefs = new ArrayList<EventListenerDef>();
67
68 private List<ApplicationContextDef> appContextDefs = new ArrayList<ApplicationContextDef>();
69
70 private boolean isAsyncAction;
71
72 private PropertyDesc progressMonitorProperty;
73
74
75
76
77
78
79
80 public PartActionDescImpl(final Class<?> partActionClass) {
81 if (partActionClass == null) {
82 throw new EmptyRuntimeException("partActionClass");
83 }
84
85 this.partActionClass = partActionClass;
86 this.beanDesc = BeanDescFactory.getBeanDesc(partActionClass);
87
88 setupIsAsyncMethod();
89 setupMethods();
90 setupFields();
91 setupProgressMonitorProperty();
92 }
93
94
95
96
97 public Method getInitializeMethod() {
98 return this.initializeMethod;
99 }
100
101
102
103
104 public void invokeInitializeMethod(final Object target) {
105 if (initializeMethod != null) {
106 AssertionUtil.assertNotNull("target", target);
107 try {
108 initializeMethod.invoke(target, (Object[]) null);
109 } catch (Throwable ex) {
110 throw new InitializeMethodException(ex.getCause(),
111 partActionClass, initializeMethod, target);
112 }
113 }
114 }
115
116
117
118
119 public Method getPostOpenMethod() {
120 return this.postOpenMethod;
121 }
122
123
124
125
126 public void invokePostOpenMethod(final Object target) {
127 if (postOpenMethod != null) {
128 AssertionUtil.assertNotNull("target", target);
129 try {
130 postOpenMethod.invoke(target, (Object[]) null);
131 } catch (Throwable ex) {
132 throw new MethodInvocationException(ex);
133 }
134 }
135 }
136
137
138
139
140 public List<EventListenerDef> getEventListenerDefList() {
141 return Collections.unmodifiableList(eventListenerDefs);
142 }
143
144
145
146
147 public List<ApplicationContextDef> getApplicationContextDefList() {
148 return Collections.unmodifiableList(appContextDefs);
149 }
150
151
152
153
154 public BeanDesc getBeanDesc() {
155 return this.beanDesc;
156 }
157
158
159
160
161 public Class<?> getPartActionClass() {
162 return this.partActionClass;
163 }
164
165
166
167
168
169 public void injectProgressMonitor(final Object target,
170 final ProgressMonitor monitor) {
171 if (progressMonitorProperty != null) {
172 progressMonitorProperty.setValue(target, monitor);
173 }
174 }
175
176 protected void setupMethods() {
177 Map<String, List<Method>> methodListMap = new HashMap<String, List<Method>>();
178 Method[] methods = partActionClass.getMethods();
179 for (int i = 0; i < methods.length; i++) {
180 List<Method> methodList = methodListMap.get(methods[i].getName());
181 if (methodList == null) {
182 methodList = new ArrayList<Method>();
183 methodListMap.put(methods[i].getName(), methodList);
184 }
185 methodList.add(methods[i]);
186
187 setupInitializeMethod(methods[i]);
188 setupPostOpenMethod(methods[i]);
189 setupEventListenerMethod(methods[i]);
190 }
191
192 for (Entry<String, List<Method>> entry : methodListMap.entrySet()) {
193 String methodName = entry.getKey();
194 List<Method> methodList = entry.getValue();
195 methodsCache.put(methodName, methodList);
196 }
197 }
198
199 protected void setupInitializeMethod(final Method method) {
200 if (method.isAnnotationPresent(InitializeMethod.class)) {
201 if ((method.getReturnType() == Void.TYPE)
202 && (method.getParameterTypes().length == 0)) {
203 if (initializeMethod == null) {
204 initializeMethod = method;
205 } else {
206 throw new IllegalMethodException(
207 DUPLICATE_ANNOTATED_METHOD, partActionClass, method);
208 }
209 } else {
210 throw new IllegalMethodException(ILLEGAL_METHOD_SIGNATURE,
211 partActionClass, method);
212 }
213 }
214 }
215
216 protected void setupPostOpenMethod(final Method method) {
217 if (method.isAnnotationPresent(PostOpenMethod.class)) {
218 if ((method.getReturnType() == Void.TYPE)
219 && (method.getParameterTypes().length == 0)) {
220 if (postOpenMethod == null) {
221 postOpenMethod = method;
222 } else {
223 throw new InitializeMethodException(
224 DUPLICATE_ANNOTATED_METHOD, partActionClass, method);
225 }
226 } else {
227 throw new InitializeMethodException(ILLEGAL_METHOD_SIGNATURE,
228 partActionClass, method);
229 }
230 }
231 }
232
233 protected void setupEventListenerMethod(final Method method) {
234 EventListener anno = method.getAnnotation(EventListener.class);
235 if (anno != null) {
236 AsyncMethod asyncMethod = method.getAnnotation(AsyncMethod.class);
237 EventListenerDef def = new EventListenerDef(method, anno,
238 asyncMethod);
239 eventListenerDefs.add(def);
240 }
241 }
242
243 protected void setupApplicationContext(final Field field) {
244 ApplicationContext anno = field.getAnnotation(ApplicationContext.class);
245 if (anno != null) {
246 String name = anno.name();
247 if (StringUtil.isEmpty(name)) {
248 name = field.getName();
249 }
250
251 PropertyDesc pd = beanDesc.getPropertyDesc(field.getName());
252 ApplicationContextDef def = new ApplicationContextDef(pd, name);
253 appContextDefs.add(def);
254 }
255 }
256
257 protected void setupFields() {
258 setupFieldsByClass(partActionClass);
259 Class<?> superClass = partActionClass.getSuperclass();
260 while (superClass != Object.class && superClass != null) {
261 setupFieldsByClass(superClass);
262 superClass = superClass.getSuperclass();
263 }
264 }
265
266 protected void setupFieldsByClass(final Class<?> targetClass) {
267 Field[] fields = targetClass.getDeclaredFields();
268 for (int i = 0; i < fields.length; i++) {
269 Field field = fields[i];
270 String fieldName = field.getName();
271 if (!fieldsCache.containsKey(fieldName)) {
272 field.setAccessible(true);
273 fieldsCache.put(fieldName, field);
274
275 setupApplicationContext(field);
276 }
277 }
278 }
279
280 protected void setupIsAsyncMethod() {
281 if (partActionClass.isAnnotationPresent(AsyncMethod.class)) {
282 this.isAsyncAction = true;
283 } else {
284 this.isAsyncAction = false;
285 }
286 }
287
288 protected void setupProgressMonitorProperty() {
289 BeanDesc desc = BeanDescFactory.getBeanDesc(partActionClass);
290 int size = desc.getPropertyDescSize();
291 for (int i = 0; i < size; i++) {
292 PropertyDesc pd = desc.getPropertyDesc(i);
293 Class<?> type = pd.getPropertyType();
294 if (type.isAssignableFrom(ProgressMonitor.class) && pd.isWritable()) {
295 this.progressMonitorProperty = pd;
296 break;
297 }
298 }
299 }
300 }