1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.data.provider.impl;
17
18 import com.google.common.base.Predicate;
19 import com.google.common.collect.Iterables;
20 import com.google.common.collect.LinkedHashMultimap;
21 import com.google.common.collect.Multimap;
22 import org.apache.commons.lang.ClassUtils;
23 import org.apache.commons.lang.Validate;
24 import org.apache.log4j.Logger;
25 import org.kuali.rice.krad.data.DataObjectService;
26 import org.kuali.rice.krad.data.KradDataServiceLocator;
27 import org.kuali.rice.krad.data.provider.MetadataProvider;
28 import org.kuali.rice.krad.data.provider.PersistenceProvider;
29 import org.kuali.rice.krad.data.provider.Provider;
30 import org.kuali.rice.krad.data.provider.ProviderRegistry;
31 import org.springframework.aop.framework.Advised;
32 import org.springframework.aop.support.AopUtils;
33
34 import java.lang.reflect.Method;
35 import java.util.ArrayList;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.List;
39
40
41
42
43
44
45 public class ProviderRegistryImpl implements ProviderRegistry {
46
47 private static final Logger LOG = Logger.getLogger(ProviderRegistry.class);
48
49 private static final String GET_DATA_OBJECT_SERVICE_METHOD_NAME = "getDataObjectService";
50 private static final String SET_DATA_OBJECT_SERVICE_METHOD_NAME = "setDataObjectService";
51
52
53
54
55 private final Multimap<Class<? extends Provider>, Provider> providersByType = LinkedHashMultimap.<Class<? extends Provider>, Provider>create();
56
57
58
59
60
61
62
63 protected Iterable<Class<? extends Provider>> enumerateProviderInterfaces(Provider provider) {
64 List<? extends Class> interfaces = ClassUtils.getAllInterfaces(provider.getClass());
65 Iterable<? extends Class> providerInterfaces = Iterables.filter(interfaces, new Predicate<Class>() {
66 @Override
67 public boolean apply(Class input) {
68 return Provider.class.isAssignableFrom(input);
69 }
70 });
71 return (Iterable<Class<? extends Provider>>) providerInterfaces;
72 }
73
74
75
76
77 @Override
78 public synchronized void registerProvider(Provider provider) {
79 Validate.notNull(provider, "Provider must be non-null");
80
81 if (hasDataObjectServiceMethod(provider, GET_DATA_OBJECT_SERVICE_METHOD_NAME, new Class[] { })) {
82 injectDataObjectService(provider);
83 }
84
85
86
87 for (Class<? extends Provider> providerInterface: enumerateProviderInterfaces(provider)) {
88 providersByType.put(providerInterface, provider);
89 }
90 }
91
92
93
94
95 @Override
96 public synchronized boolean unregisterProvider(Provider provider) {
97 Validate.notNull(provider, "Provider must be non-null");
98 boolean removed = false;
99 Collection<Provider> providers = providersByType.values();
100
101
102
103 while (providers.remove(provider)) {
104 removed = true;
105 }
106
107 return removed;
108 }
109
110
111
112
113 @Override
114 public synchronized List<Provider> getProviders() {
115 return Collections.unmodifiableList(new ArrayList<Provider>(providersByType.get(Provider.class)));
116 }
117
118
119
120
121 @Override
122 public synchronized List<Provider> getProvidersForType(Class<? extends Provider> providerType) {
123 Validate.isTrue(providerType != null, "Provider type must be non-null");
124 return Collections.unmodifiableList(new ArrayList<Provider>(providersByType.get(providerType)));
125 }
126
127
128
129
130 @Override
131 public synchronized List<MetadataProvider> getMetadataProviders() {
132 Collection<Provider> metadataProviders = providersByType.get(MetadataProvider.class);
133 return Collections.unmodifiableList(new ArrayList(metadataProviders));
134 }
135
136
137
138
139 @Override
140 public synchronized PersistenceProvider getPersistenceProvider(Class<?> type) {
141 Validate.notNull(type, "Data object type must be non-null");
142 Collection<Provider> persistenceProviders = providersByType.get(PersistenceProvider.class);
143
144
145 for (Provider provider: persistenceProviders) {
146 PersistenceProvider persistenceProvider = (PersistenceProvider) provider;
147 if (persistenceProvider.handles(type)) {
148 return persistenceProvider;
149 }
150 }
151 return null;
152 }
153
154
155
156
157 @Override
158 public MetadataProvider getMetadataProvider(Class<?> type) {
159 Validate.notNull(type, "Data object type must be non-null");
160 Collection<MetadataProvider> metadataProviders = getMetadataProviders();
161
162
163 for (MetadataProvider provider : metadataProviders) {
164 if (provider.handles(type)) {
165 return provider;
166 }
167 }
168 return null;
169 }
170
171
172
173
174
175
176
177
178
179 protected boolean hasDataObjectServiceMethod(Provider provider, String methodName, Class[] args) {
180 Method methodToFind;
181
182 try {
183 methodToFind = unwrapProxy(provider).getClass().getMethod(methodName, args);
184 } catch (Exception e) {
185 return false;
186 }
187
188 return (methodToFind != null);
189 }
190
191
192
193
194
195
196
197
198 private Object unwrapProxy(Object bean) throws Exception {
199
200
201
202
203
204 if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
205
206 Advised advised = (Advised) bean;
207
208 bean = advised.getTargetSource().getTarget();
209 }
210
211 return bean;
212 }
213
214
215
216
217
218
219
220 private void injectDataObjectService(Provider provider) {
221 try {
222 Method getterMethod = unwrapProxy(provider).getClass().getMethod(GET_DATA_OBJECT_SERVICE_METHOD_NAME);
223 if (getterMethod.invoke(unwrapProxy(provider)) == null) {
224 if (hasDataObjectServiceMethod(provider, SET_DATA_OBJECT_SERVICE_METHOD_NAME,
225 new Class[] { DataObjectService.class })) {
226
227 Method setterMethod = unwrapProxy(provider).getClass().getMethod(
228 SET_DATA_OBJECT_SERVICE_METHOD_NAME, new Class[]{DataObjectService.class});
229 setterMethod.invoke(unwrapProxy(provider), KradDataServiceLocator.getDataObjectService());
230 }
231 }
232 } catch (Exception e) {
233 LOG.warn("Error injecting DataObjectService while registering provider: " + provider.getClass());
234 }
235 }
236
237 }