1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package ch.elca.el4j.util.metadata;
19
20 import java.lang.reflect.Method;
21 import java.lang.reflect.Proxy;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28
29 import org.springframework.aop.support.AopUtils;
30 import org.springframework.core.BridgeMethodResolver;
31 import org.springframework.util.Assert;
32
33 import ch.elca.el4j.util.codingsupport.CollectionUtils;
34
35
36
37
38
39
40
41
42
43 public class DefaultGenericMetaDataSource implements GenericMetaDataSource {
44
45
46
47
48 protected static final Collection NULL_METADATA = Collections.EMPTY_LIST;
49
50
51
52
53 protected final Map<String, Collection> m_cache
54 = Collections.synchronizedMap(new HashMap<String, Collection>());
55
56
57
58
59 private Attributes m_metaDataDelegator;
60
61
62
63
64 private List<Class> m_interceptingMetaData;
65
66
67
68
69
70
71
72
73
74
75 protected String getCacheKey(Method method, Class targetClass) {
76
77
78
79 StringBuffer key = new StringBuffer();
80 if (targetClass != null) {
81 if (Proxy.isProxyClass(targetClass)) {
82 key.append("JdkProxy");
83 } else if (AopUtils.isCglibProxyClass(targetClass)) {
84 key.append("CglibProxy");
85 } else {
86 key.append(targetClass);
87 }
88 } else {
89 key.append("unknown");
90 }
91 key.append(';');
92 key.append(method);
93 return key.toString();
94 }
95
96
97
98
99 public Collection getMetaData(Method method, Class targetClass) {
100
101 String cacheKey = getCacheKey(method, targetClass);
102 Collection cachedMetaData = m_cache.get(cacheKey);
103
104 if (cachedMetaData != null) {
105
106
107 return cachedMetaData == NULL_METADATA ? null : cachedMetaData;
108 } else {
109
110 Collection metaData = computeMetaData(method, targetClass);
111
112 m_cache.put(cacheKey, metaData == null ? NULL_METADATA : metaData);
113
114 return metaData;
115 }
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129 @SuppressWarnings("unchecked")
130 protected Collection computeMetaData(Method method, Class targetClass) {
131 Assert.notNull(method);
132
133
134
135 Method bridgeMethod = BridgeMethodResolver.findBridgedMethod(method);
136
137 Method specificMethod = AopUtils.getMostSpecificMethod(
138 bridgeMethod, targetClass);
139
140
141 Collection metaDataOnMethod = new ArrayList();
142
143
144 CollectionUtils.nullSaveAddAll(metaDataOnMethod,
145 filterMetaData(findAllAttributes(specificMethod)));
146
147 if (metaDataOnMethod.isEmpty() && !specificMethod.equals(method)) {
148
149 CollectionUtils.nullSaveAddAll(metaDataOnMethod,
150 filterMetaData(findAllAttributes(method)));
151 }
152
153
154 Collection metaDataOnClass = new ArrayList();
155
156
157 if (targetClass != null) {
158 CollectionUtils.nullSaveAddAll(metaDataOnClass,
159 filterMetaData(findAllAttributes(targetClass)));
160 }
161
162 if (metaDataOnClass.isEmpty()) {
163
164 CollectionUtils.nullSaveAddAll(metaDataOnClass,
165 filterMetaData(
166 findAllAttributes(specificMethod.getDeclaringClass())));
167 }
168
169 if (metaDataOnClass.isEmpty() && !specificMethod.equals(method)) {
170
171 CollectionUtils.nullSaveAddAll(metaDataOnClass,
172 filterMetaData(findAllAttributes(
173 method.getDeclaringClass())));
174 }
175
176 Collection result = new ArrayList();
177 result.addAll(metaDataOnMethod);
178 result.addAll(metaDataOnClass);
179 return result.isEmpty() ? null : result;
180 }
181
182
183
184
185
186
187 protected Collection findAllAttributes(Method m) {
188 return getMetaDataDelegator().getAttributes(m);
189 }
190
191
192
193
194
195
196 protected Collection findAllAttributes(Class clazz) {
197 return getMetaDataDelegator().getAttributes(clazz);
198 }
199
200
201
202
203
204
205
206 @SuppressWarnings("unchecked")
207 protected Collection filterMetaData(Collection metaData) {
208 List<Class> interceptingMetaData = getInterceptingMetaData();
209 Assert.notEmpty(interceptingMetaData,
210 "There is no metadata defined to be used for interception.");
211
212 if (metaData == null || metaData.isEmpty()) {
213 return null;
214 }
215
216 List filteredMetaData = new ArrayList();
217 for (Class metaDataClass : interceptingMetaData) {
218 for (Object metaDataObject : metaData) {
219 if (metaDataClass.isInstance(metaDataObject)) {
220 filteredMetaData.add(metaDataObject);
221 }
222 }
223 }
224 return filteredMetaData.isEmpty() ? null : filteredMetaData;
225 }
226
227
228
229
230 public Attributes getMetaDataDelegator() {
231 return m_metaDataDelegator;
232 }
233
234
235
236
237 public void setMetaDataDelegator(Attributes metaDataDelegator) {
238 m_metaDataDelegator = metaDataDelegator;
239 }
240
241
242
243
244 public List<Class> getInterceptingMetaData() {
245 return m_interceptingMetaData;
246 }
247
248
249
250
251 @Override
252 public void setInterceptingMetaData(List<Class> interceptedAttributes) {
253 m_interceptingMetaData = interceptedAttributes;
254 }
255 }