1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package ch.elca.el4j.services.persistence.generic.dao.impl;
19
20 import java.lang.reflect.Proxy;
21 import java.util.Map;
22 import java.util.concurrent.ConcurrentHashMap;
23
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26 import org.springframework.aop.framework.AopProxyUtils;
27 import org.springframework.beans.BeansException;
28 import org.springframework.context.ApplicationContext;
29 import org.springframework.context.ApplicationContextAware;
30 import org.springframework.util.PatternMatchUtils;
31
32 import ch.elca.el4j.core.context.ModuleApplicationListener;
33 import ch.elca.el4j.core.context.RefreshableModuleApplicationContext;
34 import ch.elca.el4j.services.monitoring.notification.CoreNotificationHelper;
35 import ch.elca.el4j.services.persistence.generic.dao.DaoRegistry;
36 import ch.elca.el4j.services.persistence.generic.dao.GenericDao;
37
38 import net.sf.cglib.proxy.Enhancer;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 public class DefaultDaoRegistry implements DaoRegistry, ApplicationContextAware, ModuleApplicationListener {
67
68
69
70
71 private static Logger s_logger
72 = LoggerFactory.getLogger(DefaultDaoRegistry.class);
73
74
75
76
77 protected boolean m_collectDaos = true;
78
79
80
81
82 protected Map<Class<?>, GenericDao<?>> m_beanClassDaos = new ConcurrentHashMap<Class<?>, GenericDao<?>>();
83
84
85
86
87 protected Map<Class<?>, GenericDao<?>> m_daoClassDaos = new ConcurrentHashMap<Class<?>, GenericDao<?>>();
88
89
90
91
92 protected ApplicationContext m_applicationContext;
93
94
95
96
97
98 protected String m_daoNamePattern = "*";
99
100
101
102
103 protected boolean m_initialized = false;
104
105
106
107
108 protected long m_creatorThreadId;
109
110
111
112
113 protected volatile boolean m_applicationContextIsReady = false;
114
115
116 public synchronized void onContextRefreshed() {
117 m_applicationContextIsReady = true;
118 this.notify();
119 }
120
121
122
123
124 public synchronized void waitUntilApplicationContextIsReady() {
125
126 if (Thread.currentThread().getId() != m_creatorThreadId) {
127
128 while (!m_applicationContextIsReady) {
129 try {
130 s_logger.debug("Waiting for Spring context to be fully initialized.");
131 this.wait();
132 } catch (InterruptedException e) {
133 s_logger.debug("Interrupted: Application context might be ready now.");
134 }
135 }
136 }
137
138
139 if (!m_applicationContextIsReady) {
140 if (m_applicationContext instanceof RefreshableModuleApplicationContext) {
141 RefreshableModuleApplicationContext context
142 = (RefreshableModuleApplicationContext) m_applicationContext;
143 m_applicationContextIsReady = context.isRefreshed();
144 }
145 }
146
147 if (!m_applicationContextIsReady) {
148 CoreNotificationHelper.notifyMisconfiguration("Trying to get DAOs before Spring context is "
149 + "fully initialized. Some DAOs might not be found. "
150 + "Implement ch.elca.el4j.core.context.ModuleApplicationListener to get notified as soon "
151 + "Spring context is fully initialized");
152 }
153 }
154
155
156
157
158 @SuppressWarnings("unchecked")
159 public <T> GenericDao<T> getFor(Class<T> entityType) {
160
161 if ((!m_initialized) && m_collectDaos) {
162 m_initialized = true;
163 initDaosFromSpringBeans();
164 }
165
166 Class<T> actualEntityType = entityType;
167
168
169 if (Enhancer.isEnhanced(entityType)) {
170
171 actualEntityType = (Class<T>) entityType.getSuperclass();
172 }
173
174 GenericDao<T> candidateReturn = (GenericDao<T>) m_beanClassDaos.get(actualEntityType);
175
176 if (candidateReturn != null) {
177 return candidateReturn;
178 } else if (Proxy.isProxyClass(actualEntityType)) {
179
180 Class[] otherPossibilities
181 = AopProxyUtils.proxiedUserInterfaces(actualEntityType);
182 if (otherPossibilities != null) {
183 s_logger.info("Trying to unwrap JDK proxy to get DAO for type");
184 for (Class c : otherPossibilities) {
185 candidateReturn = (GenericDao<T>) m_beanClassDaos.get(c);
186 if (candidateReturn != null) {
187 return candidateReturn;
188 }
189 }
190 }
191 }
192
193 return null;
194
195 }
196
197
198 @SuppressWarnings("unchecked")
199 public <T> T getDao(Class<T> doaType) {
200
201 if ((!m_initialized) && m_collectDaos) {
202 m_initialized = true;
203 initDaosFromSpringBeans();
204 }
205
206 T candidateReturn = (T) m_daoClassDaos.get(doaType);
207 return candidateReturn;
208 }
209
210
211
212
213
214
215
216 public void setNamePattern(String namePattern) {
217 m_daoNamePattern = namePattern;
218
219 }
220
221
222
223
224 protected void initDaosFromSpringBeans() {
225 waitUntilApplicationContextIsReady();
226
227 String[] beanNamesToLoad = m_applicationContext.getBeanNamesForType(GenericDao.class);
228 for (String name : beanNamesToLoad) {
229 if (!PatternMatchUtils.simpleMatch(m_daoNamePattern, name)) {
230
231 continue;
232 }
233
234 GenericDao<?> dao = (GenericDao<?>) m_applicationContext.getBean(name);
235
236
237 if (!m_beanClassDaos.values().contains(dao)) {
238 initDao(dao);
239 m_beanClassDaos.put(dao.getPersistentClass(), dao);
240
241
242
243 Class<?>[] interfaceList = dao.getClass().getInterfaces();
244 for (Class<?> c : interfaceList) {
245
246 if (GenericDao.class.isAssignableFrom(c)) {
247 m_daoClassDaos.put(c, dao);
248 }
249 }
250 }
251 }
252 }
253
254
255
256
257
258
259 protected void initDao(GenericDao<?> dao) {
260 }
261
262
263 public Map<Class<?>, ? extends GenericDao<?>> getDaos() {
264 if ((!m_initialized) && m_collectDaos) {
265 m_initialized = true;
266 initDaosFromSpringBeans();
267 }
268
269 return m_beanClassDaos;
270 }
271
272
273
274
275 public void setDaos(Map<Class<?>, GenericDao<?>> daos) {
276 m_beanClassDaos = daos;
277
278 m_daoClassDaos.clear();
279 for (GenericDao<?> dao : daos.values()) {
280 initDao(dao);
281
282 m_daoClassDaos.put(dao.getClass(), dao);
283 }
284 }
285
286
287
288
289 public void setApplicationContext(ApplicationContext applicationContext)
290 throws BeansException {
291 m_applicationContext = applicationContext;
292 m_creatorThreadId = Thread.currentThread().getId();
293 }
294
295
296
297
298
299 public boolean isCollectDaos() {
300 return m_collectDaos;
301 }
302
303
304
305
306
307
308
309 public void setCollectDaos(boolean collectDaos) {
310 m_collectDaos = collectDaos;
311 }
312 }