1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.osgi.context.support;
18
19 import org.springframework.beans.BeansException;
20 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
21 import org.springframework.context.ApplicationContext;
22 import org.springframework.context.ApplicationContextException;
23 import org.springframework.context.event.ApplicationEventMulticaster;
24 import org.springframework.osgi.context.DelegatedExecutionOsgiBundleApplicationContext;
25 import org.springframework.osgi.context.OsgiBundleApplicationContextExecutor;
26 import org.springframework.osgi.context.event.OsgiBundleApplicationContextEventMulticaster;
27 import org.springframework.osgi.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;
28 import org.springframework.osgi.context.event.OsgiBundleContextFailedEvent;
29 import org.springframework.osgi.context.event.OsgiBundleContextRefreshedEvent;
30 import org.springframework.osgi.util.OsgiBundleUtils;
31 import org.springframework.osgi.util.OsgiStringUtils;
32 import org.springframework.osgi.util.internal.ClassUtils;
33 import org.springframework.util.Assert;
34 import org.springframework.util.ObjectUtils;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public abstract class AbstractDelegatedExecutionApplicationContext extends AbstractOsgiBundleApplicationContext
54 implements DelegatedExecutionOsgiBundleApplicationContext {
55
56
57
58
59
60
61
62
63 private static class NoDependenciesWaitRefreshExecutor implements OsgiBundleApplicationContextExecutor {
64
65 private final DelegatedExecutionOsgiBundleApplicationContext context;
66
67
68 private NoDependenciesWaitRefreshExecutor(DelegatedExecutionOsgiBundleApplicationContext ctx) {
69 context = ctx;
70 }
71
72 public void refresh() throws BeansException, IllegalStateException {
73 context.normalRefresh();
74 }
75
76 public void close() {
77 context.normalClose();
78 }
79 }
80
81
82
83 private OsgiBundleApplicationContextExecutor executor = new NoDependenciesWaitRefreshExecutor(this);
84
85
86 private final Object contextMonitor = new Object();
87
88
89 private final Object availableMonitor = new Object();
90
91 private boolean available = false;
92
93
94 private OsgiBundleApplicationContextEventMulticaster delegatedMulticaster;
95
96 private ContextClassLoaderProvider cclProvider;
97
98
99
100
101
102
103
104 public AbstractDelegatedExecutionApplicationContext() {
105 super();
106 }
107
108
109
110
111
112
113
114 public AbstractDelegatedExecutionApplicationContext(ApplicationContext parent) {
115 super(parent);
116 }
117
118 boolean isAvailable() {
119 synchronized (availableMonitor) {
120 return available;
121 }
122 }
123
124
125
126
127
128
129
130
131
132
133
134
135 public void refresh() throws BeansException, IllegalStateException {
136 executor.refresh();
137 }
138
139 public void normalRefresh() {
140 Assert.notNull(getBundleContext(), "bundle context should be set before refreshing the application context");
141
142 Thread currentThread = Thread.currentThread();
143 ClassLoader oldTCCL = currentThread.getContextClassLoader();
144
145 try {
146 currentThread.setContextClassLoader(contextClassLoaderProvider().getContextClassLoader());
147 try {
148 super.refresh();
149 sendRefreshedEvent();
150 }
151 catch (Throwable th) {
152 logger.error("Refresh error", th);
153 sendFailedEvent(th);
154
155
156 if (th instanceof RuntimeException) {
157 throw (RuntimeException) th;
158 }
159 else {
160 throw (Error) th;
161 }
162 }
163 }
164 finally {
165 currentThread.setContextClassLoader(oldTCCL);
166 }
167 }
168
169 public void normalClose() {
170 Thread currentThread = Thread.currentThread();
171 ClassLoader oldTCCL = currentThread.getContextClassLoader();
172
173 try {
174 currentThread.setContextClassLoader(contextClassLoaderProvider().getContextClassLoader());
175 super.doClose();
176 }
177 finally {
178 currentThread.setContextClassLoader(oldTCCL);
179 }
180 }
181
182
183 protected void doClose() {
184 synchronized (availableMonitor) {
185 available = false;
186 }
187 executor.close();
188 }
189
190 public void startRefresh() {
191
192
193 if (!ClassUtils.concurrentLibAvailable())
194 throw new IllegalStateException(
195 "JVM 5+ or backport-concurrent library (for JVM 1.4) required; see the FAQ for more details");
196
197 Thread thread = Thread.currentThread();
198 ClassLoader oldTCCL = thread.getContextClassLoader();
199
200 try {
201 synchronized (contextMonitor) {
202 thread.setContextClassLoader(contextClassLoaderProvider().getContextClassLoader());
203
204 if (ObjectUtils.isEmpty(getConfigLocations())) {
205 setConfigLocations(getDefaultConfigLocations());
206 }
207 if (!OsgiBundleUtils.isBundleActive(getBundle())) {
208 throw new ApplicationContextException("Unable to refresh application context: bundle is "
209 + OsgiStringUtils.bundleStateAsString(getBundle()));
210 }
211
212 ConfigurableListableBeanFactory beanFactory = null;
213
214 prepareRefresh();
215
216
217 beanFactory = obtainFreshBeanFactory();
218
219
220 prepareBeanFactory(beanFactory);
221
222 try {
223
224
225 postProcessBeanFactory(beanFactory);
226
227
228
229 invokeBeanFactoryPostProcessors(beanFactory);
230
231
232 registerBeanPostProcessors(beanFactory);
233
234 }
235 catch (BeansException ex) {
236
237
238 beanFactory.destroySingletons();
239 cancelRefresh(ex);
240
241 throw ex;
242 }
243 }
244 }
245 catch (Throwable th) {
246 logger.error("Pre refresh error", th);
247
248 sendFailedEvent(th);
249
250 if (th instanceof RuntimeException) {
251 throw (RuntimeException) th;
252 }
253 else {
254 throw (Error) th;
255 }
256 }
257 finally {
258 thread.setContextClassLoader(oldTCCL);
259 }
260 }
261
262 public void completeRefresh() {
263 Thread thread = Thread.currentThread();
264 ClassLoader oldTCCL = thread.getContextClassLoader();
265
266 try {
267
268 synchronized (contextMonitor) {
269 thread.setContextClassLoader(contextClassLoaderProvider().getContextClassLoader());
270
271 try {
272 ConfigurableListableBeanFactory beanFactory = getBeanFactory();
273
274
275 initMessageSource();
276
277
278 initApplicationEventMulticaster();
279
280
281
282 onRefresh();
283
284
285 registerListeners();
286
287
288 finishBeanFactoryInitialization(beanFactory);
289
290
291 finishRefresh();
292
293
294 sendRefreshedEvent();
295 }
296 catch (BeansException ex) {
297
298
299 getBeanFactory().destroySingletons();
300 cancelRefresh(ex);
301
302 throw ex;
303 }
304 }
305 }
306 catch (Throwable th) {
307 logger.error("Post refresh error", th);
308
309 sendFailedEvent(th);
310
311 if (th instanceof RuntimeException) {
312 throw (RuntimeException) th;
313 }
314 else {
315 throw (Error) th;
316 }
317 }
318 finally {
319 thread.setContextClassLoader(oldTCCL);
320 }
321 }
322
323 protected void finishRefresh() {
324 super.finishRefresh();
325
326 synchronized (availableMonitor) {
327 available = true;
328 }
329
330 publishContextAsOsgiServiceIfNecessary();
331 }
332
333 public Object getMonitor() {
334 return contextMonitor;
335 }
336
337 public void setExecutor(OsgiBundleApplicationContextExecutor executor) {
338 this.executor = executor;
339 }
340
341 public void setDelegatedEventMulticaster(OsgiBundleApplicationContextEventMulticaster multicaster) {
342 this.delegatedMulticaster = multicaster;
343 }
344
345
346
347
348
349
350
351
352
353
354
355 public void setDelegatedEventMulticaster(ApplicationEventMulticaster multicaster) {
356 this.delegatedMulticaster = new OsgiBundleApplicationContextEventMulticasterAdapter(multicaster);
357 }
358
359 public OsgiBundleApplicationContextEventMulticaster getDelegatedEventMulticaster() {
360 return this.delegatedMulticaster;
361 }
362
363 private void sendFailedEvent(Throwable cause) {
364 if (delegatedMulticaster != null)
365 delegatedMulticaster.multicastEvent(new OsgiBundleContextFailedEvent(this, this.getBundle(), cause));
366 }
367
368 private void sendRefreshedEvent() {
369 if (delegatedMulticaster != null)
370 delegatedMulticaster.multicastEvent(new OsgiBundleContextRefreshedEvent(this, this.getBundle()));
371 }
372
373
374
375
376
377
378
379
380
381
382
383
384 protected ClassLoader getContextClassLoader() {
385 return contextClassLoaderProvider().getContextClassLoader();
386 }
387
388
389 private ContextClassLoaderProvider contextClassLoaderProvider() {
390 if (cclProvider == null) {
391 DefaultContextClassLoaderProvider defaultProvider = new DefaultContextClassLoaderProvider();
392 defaultProvider.setBeanClassLoader(getClassLoader());
393 cclProvider = defaultProvider;
394 }
395 return cclProvider;
396 }
397
398
399
400
401
402
403
404
405
406
407 public void setContextClassLoaderProvider(ContextClassLoaderProvider contextClassLoaderProvider) {
408 this.cclProvider = contextClassLoaderProvider;
409 }
410 }