Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 356683 | Differences between
and this patch

Collapse All | Expand All

(-)a/core/src/test/java/org/eclipse/gemini/blueprint/context/internal/classloader/ChainedClassLoaderTest.java (-1 lines)
Lines 96-102 public class ChainedClassLoaderTest extends TestCase { Link Here
96
	}
96
	}
97
97
98
	public void testGetResourceString() throws Exception {
98
	public void testGetResourceString() throws Exception {
99
		System.out.println(chainedLoader.getResource("java/lang/Object.class"));
100
		assertNull(chainedLoader.getResource("java/lang/Object.class"));
99
		assertNull(chainedLoader.getResource("java/lang/Object.class"));
101
		chainedLoader.addClassLoader(Object.class);
100
		chainedLoader.addClassLoader(Object.class);
102
		assertNotNull(chainedLoader.getResource("java/lang/Object.class"));
101
		assertNotNull(chainedLoader.getResource("java/lang/Object.class"));
(-)a/core/src/test/java/org/eclipse/gemini/blueprint/context/support/ConfigLocationsTest.java (-1 lines)
Lines 44-50 public class ConfigLocationsTest extends TestCase { Link Here
44
		context.setConfigLocations(cfgs);
44
		context.setConfigLocations(cfgs);
45
		String[] returned =
45
		String[] returned =
46
				(String[]) invokeMethod("expandLocations", new Class[] { String[].class }, new Object[] { cfgs });
46
				(String[]) invokeMethod("expandLocations", new Class[] { String[].class }, new Object[] { cfgs });
47
		System.out.println("returned " + Arrays.toString(returned));
48
		assertTrue(Arrays.equals(new String[] { "cnf/*.xml", "/cnf/*.xml" }, returned));
47
		assertTrue(Arrays.equals(new String[] { "cnf/*.xml", "/cnf/*.xml" }, returned));
49
	}
48
	}
50
49
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/BlueprintNamespaceHandlerActivator.java (+14 lines)
Added Link Here
1
package org.eclipse.gemini.blueprint.extender.internal.activator;
2
3
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintConfigUtils;
4
5
/**
6
 * @author Olaf Otto
7
 */
8
public class BlueprintNamespaceHandlerActivator extends NamespaceHandlerActivator {
9
10
    @Override
11
    protected String getManagedBundleExtenderVersionHeader() {
12
        return BlueprintConfigUtils.EXTENDER_VERSION;
13
    }
14
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ContextLoaderListener.java (-307 / +69 lines)
Lines 15-42 Link Here
15
15
16
package org.eclipse.gemini.blueprint.extender.internal.activator;
16
package org.eclipse.gemini.blueprint.extender.internal.activator;
17
17
18
import java.util.Map;
19
import java.util.WeakHashMap;
20
21
import org.apache.commons.logging.Log;
18
import org.apache.commons.logging.Log;
22
import org.apache.commons.logging.LogFactory;
19
import org.apache.commons.logging.LogFactory;
23
import org.osgi.framework.Bundle;
20
import org.eclipse.gemini.blueprint.extender.OsgiApplicationContextCreator;
24
import org.osgi.framework.BundleActivator;
21
import org.eclipse.gemini.blueprint.extender.internal.activator.listeners.BaseListener;
25
import org.osgi.framework.BundleContext;
26
import org.osgi.framework.BundleEvent;
27
import org.osgi.framework.SynchronousBundleListener;
28
import org.osgi.framework.Version;
29
import org.springframework.beans.BeanUtils;
30
import org.springframework.beans.CachedIntrospectionResults;
31
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;
32
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
22
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
33
import org.eclipse.gemini.blueprint.extender.internal.support.NamespaceManager;
23
import org.eclipse.gemini.blueprint.extender.support.DefaultOsgiApplicationContextCreator;
34
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
24
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
35
import org.eclipse.gemini.blueprint.service.exporter.support.OsgiServiceFactoryBean;
36
import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceCollectionProxyFactoryBean;
37
import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceProxyFactoryBean;
38
import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
25
import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
39
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
26
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
27
import org.osgi.framework.*;
40
28
41
/**
29
/**
42
 * Osgi Extender that bootstraps 'Spring powered bundles'.
30
 * Osgi Extender that bootstraps 'Spring powered bundles'.
Lines 80-202 import org.eclipse.gemini.blueprint.util.OsgiStringUtils; Link Here
80
 */
68
 */
81
public class ContextLoaderListener implements BundleActivator {
69
public class ContextLoaderListener implements BundleActivator {
82
70
83
	/**
71
    /**
84
	 * Common base class for {@link ContextLoaderListener} listeners.
85
	 * 
86
	 * @author Costin Leau
87
	 */
88
	private abstract class BaseListener implements SynchronousBundleListener {
89
90
		static final int LAZY_ACTIVATION_EVENT_TYPE = 0x00000200;
91
92
		protected final Log log = LogFactory.getLog(getClass());
93
94
		/**
95
		 * common cache used for tracking down bundles started lazily so they don't get processed twice (once when
96
		 * started lazy, once when started fully)
97
		 */
98
		protected Map<Bundle, Object> lazyBundleCache = new WeakHashMap<Bundle, Object>();
99
		/** dummy value for the bundle cache */
100
		private final Object VALUE = new Object();
101
102
		// caches the bundle
103
		protected void push(Bundle bundle) {
104
			synchronized (lazyBundleCache) {
105
				lazyBundleCache.put(bundle, VALUE);
106
			}
107
		}
108
109
		// checks the presence of the bundle as well as removing it
110
		protected boolean pop(Bundle bundle) {
111
			synchronized (lazyBundleCache) {
112
				return (lazyBundleCache.remove(bundle) != null);
113
			}
114
		}
115
116
		/**
117
		 * A bundle has been started, stopped, resolved, or unresolved. This method is a synchronous callback, do not do
118
		 * any long-running work in this thread.
119
		 * 
120
		 * @see org.osgi.framework.SynchronousBundleListener#bundleChanged
121
		 */
122
		public void bundleChanged(BundleEvent event) {
123
124
			boolean trace = log.isTraceEnabled();
125
126
			// check if the listener is still alive
127
			if (isClosed) {
128
				if (trace)
129
					log.trace("Listener is closed; events are being ignored");
130
				return;
131
			}
132
			if (trace) {
133
				log.trace("Processing bundle event [" + OsgiStringUtils.nullSafeToString(event) + "] for bundle ["
134
						+ OsgiStringUtils.nullSafeSymbolicName(event.getBundle()) + "]");
135
			}
136
			try {
137
				handleEvent(event);
138
			} catch (Exception ex) {
139
				/* log exceptions before swallowing */
140
				log.warn("Got exception while handling event " + event, ex);
141
			}
142
		}
143
144
		protected abstract void handleEvent(BundleEvent event);
145
	}
146
147
	/**
148
	 * Bundle listener used for detecting namespace handler/resolvers. Exists as a separate listener so that it can be
149
	 * registered early to avoid race conditions with bundles in INSTALLING state but still to avoid premature context
150
	 * creation before the Spring {@link ContextLoaderListener} is not fully initialized.
151
	 * 
152
	 * @author Costin Leau
153
	 */
154
	private class NamespaceBundleLister extends BaseListener {
155
156
		private final boolean resolved;
157
158
		NamespaceBundleLister(boolean resolvedBundles) {
159
			this.resolved = resolvedBundles;
160
		}
161
162
		protected void handleEvent(BundleEvent event) {
163
			Bundle bundle = event.getBundle();
164
165
			switch (event.getType()) {
166
167
			case BundleEvent.RESOLVED:
168
				if (resolved) {
169
					maybeAddNamespaceHandlerFor(bundle, false);
170
				}
171
				break;
172
173
			case LAZY_ACTIVATION_EVENT_TYPE: {
174
				if (!resolved) {
175
					push(bundle);
176
					maybeAddNamespaceHandlerFor(bundle, true);
177
				}
178
				break;
179
			}
180
			case BundleEvent.STARTED: {
181
				if (!resolved) {
182
					if (!pop(bundle)) {
183
						maybeAddNamespaceHandlerFor(bundle, false);
184
					}
185
				}
186
				break;
187
			}
188
			case BundleEvent.STOPPED: {
189
				pop(bundle);
190
				maybeRemoveNameSpaceHandlerFor(bundle);
191
				break;
192
			}
193
			default:
194
				break;
195
			}
196
		}
197
	}
198
199
	/**
200
	 * Bundle listener used for context creation/destruction.
72
	 * Bundle listener used for context creation/destruction.
201
	 */
73
	 */
202
	private class ContextBundleListener extends BaseListener {
74
	private class ContextBundleListener extends BaseListener {
Lines 205-218 public class ContextLoaderListener implements BundleActivator { Link Here
205
77
206
			Bundle bundle = event.getBundle();
78
			Bundle bundle = event.getBundle();
207
79
208
			// ignore current bundle for context creation
80
			// ignore current bundle for context creation
209
			if (bundle.getBundleId() == bundleId) {
81
			if (bundle.getBundleId() == bundleId) {
210
				return;
82
				return;
211
			}
83
			}
212
84
213
			switch (event.getType()) {
85
			switch (event.getType()) {
214
			case LAZY_ACTIVATION_EVENT_TYPE: {
86
			case LAZY_ACTIVATION_EVENT_TYPE: {
215
				// activate bundle
87
				// activate bundle
216
				try {
88
				try {
217
					bundle.loadClass("org.osgi.service.blueprint.container.BlueprintContainer");
89
					bundle.loadClass("org.osgi.service.blueprint.container.BlueprintContainer");
218
				} catch (Exception ex) {
90
				} catch (Exception ex) {
Lines 228-235 public class ContextLoaderListener implements BundleActivator { Link Here
228
					if (log.isDebugEnabled()) {
100
					if (log.isDebugEnabled()) {
229
						log.debug("System bundle stopping");
101
						log.debug("System bundle stopping");
230
					}
102
					}
231
					// System bundle is shutting down; Special handling for
103
					// System bundle is shutting down; Special handling for
232
					// framework shutdown
104
					// framework shutdown
233
					shutdown();
105
					shutdown();
234
				} else {
106
				} else {
235
					lifecycleManager.maybeCloseApplicationContextFor(bundle);
107
					lifecycleManager.maybeCloseApplicationContextFor(bundle);
Lines 244-266 public class ContextLoaderListener implements BundleActivator { Link Here
244
116
245
	protected final Log log = LogFactory.getLog(getClass());
117
	protected final Log log = LogFactory.getLog(getClass());
246
118
247
	/** extender bundle id */
119
    private ExtenderConfiguration extenderConfiguration;
248
	private long bundleId;
120
    private VersionMatcher versionMatcher;
249
121
    private Version extenderVersion;
250
	/** extender configuration */
251
	private ExtenderConfiguration extenderConfiguration;
252
122
253
	/** Spring namespace/resolver manager */
123
    /** extender bundle id */
254
	private NamespaceManager nsManager;
124
	private long bundleId;
255
125
256
	/** The bundle's context */
126
	/** The bundle's context */
257
	private BundleContext bundleContext;
127
	private BundleContext bundleContext;
258
128
259
	/** Bundle listener interested in context creation */
129
	/** Bundle listener interested in context creation */
260
	private SynchronousBundleListener contextListener;
130
	private BaseListener contextListener;
261
262
	/** Bundle listener interested in namespace resolvers/parsers discovery */
263
	private SynchronousBundleListener nsListener;
264
131
265
	/**
132
	/**
266
	 * Monitor used for dealing with the bundle activator and synchronous bundle threads
133
	 * Monitor used for dealing with the bundle activator and synchronous bundle threads
Lines 272-331 public class ContextLoaderListener implements BundleActivator { Link Here
272
	 */
139
	 */
273
	private volatile boolean isClosed = false;
140
	private volatile boolean isClosed = false;
274
141
275
	/** This extender version */
276
	private Version extenderVersion;
277
278
	private volatile OsgiBundleApplicationContextEventMulticaster multicaster;
279
280
	private volatile LifecycleManager lifecycleManager;
142
	private volatile LifecycleManager lifecycleManager;
281
	private volatile VersionMatcher versionMatcher;
282
	private volatile OsgiContextProcessor processor;
143
	private volatile OsgiContextProcessor processor;
283
	private volatile ListListenerAdapter osgiListeners;
284
144
285
	/**
145
    public ContextLoaderListener(ExtenderConfiguration extenderConfiguration) {
146
        this.extenderConfiguration = extenderConfiguration;
147
    }
148
149
    /**
286
	 * <p/> Called by OSGi when this bundle is started. Finds all previously resolved bundles and adds namespace
150
	 * <p/> Called by OSGi when this bundle is started. Finds all previously resolved bundles and adds namespace
287
	 * handlers for them if necessary. </p> <p/> Creates application contexts for bundles started before the extender
151
	 * handlers for them if necessary. </p> <p/> Creates application contexts for bundles started before the extender
288
	 * was started. </p> <p/> Registers a namespace/entity resolving service for use by web app contexts. </p>
152
	 * was started. </p> <p/> Registers a namespace/entity resolving service for use by web app contexts. </p>
289
	 * 
153
	 * 
290
	 * @see org.osgi.framework.BundleActivator#start
154
	 * @see org.osgi.framework.BundleActivator#start
291
	 */
155
	 */
292
	public void start(BundleContext context) throws Exception {
156
	public void start(BundleContext extenderBundleContext) throws Exception {
293
157
294
		this.bundleContext = context;
158
		this.bundleContext = extenderBundleContext;
295
		this.bundleId = context.getBundle().getBundleId();
159
		this.bundleId = extenderBundleContext.getBundle().getBundleId();
296
160
        this.extenderVersion = OsgiBundleUtils.getBundleVersion(extenderBundleContext.getBundle());
297
		this.extenderVersion = OsgiBundleUtils.getBundleVersion(context.getBundle());
161
        this.versionMatcher = new DefaultVersionMatcher(getManagedBundleExtenderVersionHeader(), extenderVersion);
298
		log.info("Starting [" + bundleContext.getBundle().getSymbolicName() + "] bundle v.[" + extenderVersion + "]");
162
        this.processor = createContextProcessor();
299
		versionMatcher = new DefaultVersionMatcher(getManagedBundleExtenderVersionHeader(), extenderVersion);
163
300
		processor = createContextProcessor();
164
		// initialize the configuration once namespace handlers have been detected
301
165
		this.lifecycleManager =
302
		// init cache (to prevent ad-hoc Java Bean discovery on lazy bundles)
166
				new LifecycleManager(
303
		initJavaBeansCache();
167
                        this.extenderConfiguration,
304
168
                        getVersionMatcher(),
305
		// Step 1 : discover existing namespaces (in case there are fragments with custom XML definitions)
169
                        createContextConfigFactory(),
306
		nsManager = new NamespaceManager(context);
170
                        getOsgiApplicationContextCreator(),
307
		initNamespaceHandlers(bundleContext);
171
						this.processor,
308
172
                        getTypeCompatibilityChecker(),
309
		// Step 2: initialize the extender configuration
173
                        bundleContext);
310
		extenderConfiguration = initExtenderConfiguration(bundleContext);
174
311
175
		// Step 3: discover the bundles that are started
312
		// init the OSGi event dispatch/listening system
176
		// and require context creation
313
		initListenerService();
314
315
		// initialize the configuration once namespace handlers have been detected
316
		lifecycleManager =
317
				new LifecycleManager(extenderConfiguration, versionMatcher, createContextConfigFactory(),
318
						this.processor, getTypeCompatibilityChecker(), bundleContext);
319
320
		// Step 3: discover the bundles that are started
321
		// and require context creation
322
		initStartedBundles(bundleContext);
177
		initStartedBundles(bundleContext);
323
	}
178
	}
324
179
325
	protected ExtenderConfiguration initExtenderConfiguration(BundleContext bundleContext) {
326
		return new ExtenderConfiguration(bundleContext, log);
327
	}
328
329
	protected OsgiContextProcessor createContextProcessor() {
180
	protected OsgiContextProcessor createContextProcessor() {
330
		return new NoOpOsgiContextProcessor();
181
		return new NoOpOsgiContextProcessor();
331
	}
182
	}
Lines 334-379 public class ContextLoaderListener implements BundleActivator { Link Here
334
		return null;
185
		return null;
335
	}
186
	}
336
187
337
	protected String getManagedBundleExtenderVersionHeader() {
338
		return ConfigUtils.EXTENDER_VERSION;
339
	}
340
341
	protected void initNamespaceHandlers(BundleContext context) {
342
		nsManager = new NamespaceManager(context);
343
344
		// register listener first to make sure any bundles in INSTALLED state
345
		// are not lost
346
		
347
		// if the property is defined and true, consider bundles in STARTED/LAZY-INIT state, otherwise use RESOLVED
348
		boolean nsResolved = !Boolean.getBoolean("org.eclipse.gemini.blueprint.ns.bundles.started");
349
		nsListener = new NamespaceBundleLister(nsResolved);
350
		context.addBundleListener(nsListener);
351
352
		Bundle[] previousBundles = context.getBundles();
353
354
		for (Bundle bundle : previousBundles) {
355
			// special handling for uber bundle being restarted
356
			if ((nsResolved && OsgiBundleUtils.isBundleResolved(bundle)) || (!nsResolved && OsgiBundleUtils.isBundleActive(bundle)) || bundleId == bundle.getBundleId()) {
357
				maybeAddNamespaceHandlerFor(bundle, false);
358
			} else if (OsgiBundleUtils.isBundleLazyActivated(bundle)) {
359
				maybeAddNamespaceHandlerFor(bundle, true);
360
			}
361
		}
362
363
		// discovery finished, publish the resolvers/parsers in the OSGi space
364
		nsManager.afterPropertiesSet();
365
	}
366
367
	protected void initStartedBundles(BundleContext bundleContext) {
188
	protected void initStartedBundles(BundleContext bundleContext) {
368
		// register the context creation listener
189
		// register the context creation listener
369
		contextListener = new ContextBundleListener();
190
		contextListener = new ContextBundleListener();
370
		// listen to any changes in bundles
191
		// listen to any changes in bundles
371
		bundleContext.addBundleListener(contextListener);
192
		bundleContext.addBundleListener(contextListener);
372
		// get the bundles again to get an updated view
193
		// get the bundles again to get an updated view
373
		Bundle[] previousBundles = bundleContext.getBundles();
194
		Bundle[] previousBundles = bundleContext.getBundles();
374
195
375
		// Instantiate all previously resolved bundles which are Spring
196
		// Instantiate all previously resolved bundles which are Spring
376
		// powered
197
		// powered
377
		for (int i = 0; i < previousBundles.length; i++) {
198
		for (int i = 0; i < previousBundles.length; i++) {
378
			if (OsgiBundleUtils.isBundleActive(previousBundles[i])) {
199
			if (OsgiBundleUtils.isBundleActive(previousBundles[i])) {
379
				try {
200
				try {
Lines 403-507 public class ContextLoaderListener implements BundleActivator { Link Here
403
	 */
224
	 */
404
	protected void shutdown() {
225
	protected void shutdown() {
405
		synchronized (monitor) {
226
		synchronized (monitor) {
406
			// if already closed, bail out
227
			// if already closed, bail out
407
			if (isClosed)
228
			if (isClosed)
408
				return;
229
				return;
409
			else
230
			else
410
				isClosed = true;
231
				isClosed = true;
411
		}
232
		}
412
		log.info("Stopping [" + bundleContext.getBundle().getSymbolicName() + "] bundle v.[" + extenderVersion + "]");
413
233
414
		destroyJavaBeansCache();
234
        this.contextListener.close();
415
235
416
		// remove the bundle listeners (we are closing down)
236
		// remove the bundle listeners (we are closing down)
417
		if (contextListener != null) {
237
		if (contextListener != null) {
418
			bundleContext.removeBundleListener(contextListener);
238
			bundleContext.removeBundleListener(contextListener);
419
			contextListener = null;
239
			contextListener = null;
420
		}
240
		}
421
241
422
		if (nsListener != null) {
242
		// close managed bundles
423
			bundleContext.removeBundleListener(nsListener);
424
			nsListener = null;
425
		}
426
427
		// close managed bundles
428
		lifecycleManager.destroy();
243
		lifecycleManager.destroy();
429
		// clear the namespace registry
430
		nsManager.destroy();
431
432
		// release multicaster
433
		if (multicaster != null) {
434
			multicaster.removeAllListeners();
435
			multicaster = null;
436
		}
437
		// release listeners
438
		osgiListeners.destroy();
439
		osgiListeners = null;
440
441
		extenderConfiguration.destroy();
442
	}
443
444
	private void initJavaBeansCache() {
445
		Class<?>[] classes =
446
				new Class<?>[] { OsgiServiceFactoryBean.class, OsgiServiceProxyFactoryBean.class,
447
						OsgiServiceCollectionProxyFactoryBean.class };
448
449
		CachedIntrospectionResults.acceptClassLoader(OsgiStringUtils.class.getClassLoader());
450
451
		for (Class<?> clazz : classes) {
452
			BeanUtils.getPropertyDescriptors(clazz);
453
		}
454
	}
455
456
	private void destroyJavaBeansCache() {
457
		CachedIntrospectionResults.clearClassLoader(OsgiStringUtils.class.getClassLoader());
458
	}
459
460
	protected void maybeAddNamespaceHandlerFor(Bundle bundle, boolean isLazy) {
461
		if (handlerBundleMatchesExtenderVersion(bundle))
462
			nsManager.maybeAddNamespaceHandlerFor(bundle, isLazy);
463
	}
464
465
	protected void maybeRemoveNameSpaceHandlerFor(Bundle bundle) {
466
		if (handlerBundleMatchesExtenderVersion(bundle))
467
			nsManager.maybeRemoveNameSpaceHandlerFor(bundle);
468
	}
469
470
	/**
471
	 * Utility method that does extender range versioning and approapriate
472
	 * 
473
	 * logging.
474
	 * 
475
	 * @param bundle
476
	 */
477
	private boolean handlerBundleMatchesExtenderVersion(Bundle bundle) {
478
		if (!versionMatcher.matchVersion(bundle)) {
479
			if (log.isDebugEnabled())
480
				log.debug("Ignoring handler bundle " + OsgiStringUtils.nullSafeNameAndSymName(bundle)
481
						+ "] due to mismatch in expected extender version");
482
			return false;
483
		}
484
		return true;
485
	}
244
	}
486
245
487
	protected ApplicationContextConfigurationFactory createContextConfigFactory() {
246
	protected ApplicationContextConfigurationFactory createContextConfigFactory() {
488
		return new DefaultApplicationContextConfigurationFactory();
247
		return new DefaultApplicationContextConfigurationFactory();
489
	}
248
	}
490
249
491
	protected void initListenerService() {
250
    public VersionMatcher getVersionMatcher() {
492
		multicaster = extenderConfiguration.getEventMulticaster();
251
        return versionMatcher;
493
252
    }
494
		addApplicationListener(multicaster);
253
495
		multicaster.addApplicationListener(extenderConfiguration.getContextEventListener());
254
    protected String getManagedBundleExtenderVersionHeader() {
496
255
        return ConfigUtils.EXTENDER_VERSION;
497
		if (log.isDebugEnabled())
256
    }
498
			log.debug("Initialization of OSGi listeners service completed...");
257
499
	}
258
    protected OsgiApplicationContextCreator getOsgiApplicationContextCreator() {
500
259
        OsgiApplicationContextCreator creator = this.extenderConfiguration.getContextCreator();
501
	protected void addApplicationListener(OsgiBundleApplicationContextEventMulticaster multicaster) {
260
        if (creator == null) {
502
		osgiListeners = new ListListenerAdapter(bundleContext);
261
            creator = createDefaultOsgiApplicationContextCreator();
503
		osgiListeners.afterPropertiesSet();
262
        }
504
		// register the listener that does the dispatching
263
        return creator;
505
		multicaster.addApplicationListener(osgiListeners);
264
    }
506
	}
265
266
    protected OsgiApplicationContextCreator createDefaultOsgiApplicationContextCreator() {
267
        return new DefaultOsgiApplicationContextCreator();
268
    }
507
}
269
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/JavaBeansCacheActivator.java (+60 lines)
Added Link Here
1
package org.eclipse.gemini.blueprint.extender.internal.activator;
2
3
import org.eclipse.gemini.blueprint.service.exporter.support.OsgiServiceFactoryBean;
4
import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceCollectionProxyFactoryBean;
5
import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceProxyFactoryBean;
6
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
7
import org.osgi.framework.BundleActivator;
8
import org.osgi.framework.BundleContext;
9
import org.springframework.beans.BeanUtils;
10
import org.springframework.beans.CachedIntrospectionResults;
11
12
/**
13
 * Used to prevent ad-hoc Java Bean discovery on lazy bundles.
14
 *
15
 * @author Bill Gallagher
16
 * @author Andy Piper
17
 * @author Hal Hildebrand
18
 * @author Adrian Colyer
19
 * @author Costin Leau
20
 * @author Olaf Otto
21
 */
22
public class JavaBeansCacheActivator implements BundleActivator {
23
    /**
24
     * Monitor used for dealing with the bundle activator and synchronous bundle threads
25
     */
26
    private final Object monitor = new Object();
27
    private boolean stopped = false;
28
29
    public void start(BundleContext extenderBundleContext) {
30
        initJavaBeansCache();
31
    }
32
33
    public void stop(BundleContext extenderBundleContext) {
34
        synchronized (monitor) {
35
            if (stopped) {
36
                return;
37
            }
38
            stopped = true;
39
        }
40
        destroyJavaBeansCache();
41
    }
42
43
    private void initJavaBeansCache() {
44
        Class<?>[] classes =
45
                new Class<?>[] { OsgiServiceFactoryBean.class, OsgiServiceProxyFactoryBean.class,
46
                        OsgiServiceCollectionProxyFactoryBean.class };
47
48
        CachedIntrospectionResults.acceptClassLoader(OsgiStringUtils.class.getClassLoader());
49
50
        for (Class<?> clazz : classes) {
51
            BeanUtils.getPropertyDescriptors(clazz);
52
        }
53
    }
54
55
    private void destroyJavaBeansCache() {
56
        CachedIntrospectionResults.clearClassLoader(OsgiStringUtils.class.getClassLoader());
57
    }
58
}
59
60
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java (-12 / +6 lines)
Lines 14-27 Link Here
14
14
15
package org.eclipse.gemini.blueprint.extender.internal.activator;
15
package org.eclipse.gemini.blueprint.extender.internal.activator;
16
16
17
import java.util.ArrayList;
18
import java.util.Collection;
19
import java.util.Collections;
20
import java.util.List;
21
import java.util.Map;
22
import java.util.Timer;
23
import java.util.concurrent.ConcurrentHashMap;
24
25
import org.apache.commons.logging.Log;
17
import org.apache.commons.logging.Log;
26
import org.apache.commons.logging.LogFactory;
18
import org.apache.commons.logging.LogFactory;
27
import org.eclipse.gemini.blueprint.context.ConfigurableOsgiBundleApplicationContext;
19
import org.eclipse.gemini.blueprint.context.ConfigurableOsgiBundleApplicationContext;
Lines 45-50 import org.springframework.beans.factory.config.BeanFactoryPostProcessor; Link Here
45
import org.springframework.core.task.SyncTaskExecutor;
37
import org.springframework.core.task.SyncTaskExecutor;
46
import org.springframework.core.task.TaskExecutor;
38
import org.springframework.core.task.TaskExecutor;
47
39
40
import java.util.*;
41
import java.util.concurrent.ConcurrentHashMap;
42
48
/**
43
/**
49
 * Manager handling the startup/shutdown threading issues regarding OSGi contexts. Used by {@link ContextLoaderListener}
44
 * Manager handling the startup/shutdown threading issues regarding OSGi contexts. Used by {@link ContextLoaderListener}
50
 * .
45
 * .
Lines 100-112 class LifecycleManager implements DisposableBean { Link Here
100
	private final TypeCompatibilityChecker typeChecker;
95
	private final TypeCompatibilityChecker typeChecker;
101
96
102
	LifecycleManager(ExtenderConfiguration extenderConfiguration, VersionMatcher versionMatcher,
97
	LifecycleManager(ExtenderConfiguration extenderConfiguration, VersionMatcher versionMatcher,
103
			ApplicationContextConfigurationFactory appCtxCfgFactory, OsgiContextProcessor processor,
98
                     ApplicationContextConfigurationFactory appCtxCfgFactory, OsgiApplicationContextCreator osgiApplicationContextCreator, OsgiContextProcessor processor,
104
			TypeCompatibilityChecker checker, BundleContext context) {
99
                     TypeCompatibilityChecker checker, BundleContext context) {
105
100
106
		this.versionMatcher = versionMatcher;
101
		this.versionMatcher = versionMatcher;
107
		this.extenderConfiguration = extenderConfiguration;
102
		this.extenderConfiguration = extenderConfiguration;
108
		this.contextConfigurationFactory = appCtxCfgFactory;
103
		this.contextConfigurationFactory = appCtxCfgFactory;
109
104
        this.contextCreator = osgiApplicationContextCreator;
110
		this.processor = processor;
105
		this.processor = processor;
111
106
112
		this.taskExecutor = extenderConfiguration.getTaskExecutor();
107
		this.taskExecutor = extenderConfiguration.getTaskExecutor();
Lines 114-120 class LifecycleManager implements DisposableBean { Link Here
114
109
115
		this.multicaster = extenderConfiguration.getEventMulticaster();
110
		this.multicaster = extenderConfiguration.getEventMulticaster();
116
111
117
		this.contextCreator = extenderConfiguration.getContextCreator();
118
		this.postProcessors = extenderConfiguration.getPostProcessors();
112
		this.postProcessors = extenderConfiguration.getPostProcessors();
119
		this.typeChecker = checker;
113
		this.typeChecker = checker;
120
114
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ListListenerAdapter.java (-10 / +5 lines)
Lines 14-32 Link Here
14
14
15
package org.eclipse.gemini.blueprint.extender.internal.activator;
15
package org.eclipse.gemini.blueprint.extender.internal.activator;
16
16
17
import java.lang.reflect.ParameterizedType;
17
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEvent;
18
import java.lang.reflect.Type;
18
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener;
19
import java.lang.reflect.TypeVariable;
20
import java.util.Map;
21
import java.util.WeakHashMap;
22
23
import org.osgi.framework.BundleContext;
19
import org.osgi.framework.BundleContext;
24
import org.osgi.util.tracker.ServiceTracker;
20
import org.osgi.util.tracker.ServiceTracker;
25
import org.springframework.beans.factory.DisposableBean;
21
import org.springframework.beans.factory.DisposableBean;
26
import org.springframework.beans.factory.InitializingBean;
22
import org.springframework.beans.factory.InitializingBean;
27
import org.springframework.core.GenericTypeResolver;
23
import org.springframework.core.GenericTypeResolver;
28
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEvent;
24
29
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener;
25
import java.util.Map;
26
import java.util.WeakHashMap;
30
27
31
/**
28
/**
32
 * Listener interface that delegates to a list of listener. This is useful in OSGi environments when dealing with
29
 * Listener interface that delegates to a list of listener. This is useful in OSGi environments when dealing with
Lines 45-52 class ListListenerAdapter implements OsgiBundleApplicationContextListener<OsgiBu Link Here
45
42
46
	/**
43
	/**
47
	 * Constructs a new <code>ListListenerAdapter</code> instance.
44
	 * Constructs a new <code>ListListenerAdapter</code> instance.
48
	 * 
49
	 * @param listeners
50
	 */
45
	 */
51
	public ListListenerAdapter(BundleContext bundleContext) {
46
	public ListListenerAdapter(BundleContext bundleContext) {
52
		this.tracker = new ServiceTracker(bundleContext, OsgiBundleApplicationContextListener.class.getName(), null);
47
		this.tracker = new ServiceTracker(bundleContext, OsgiBundleApplicationContextListener.class.getName(), null);
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ListenerServiceActivator.java (+79 lines)
Added Link Here
1
package org.eclipse.gemini.blueprint.extender.internal.activator;
2
3
import org.apache.commons.logging.Log;
4
import org.apache.commons.logging.LogFactory;
5
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;
6
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
7
import org.osgi.framework.BundleActivator;
8
import org.osgi.framework.BundleContext;
9
10
/**
11
 * Initializes the event multicaster infrastructure.
12
 *
13
 * @author Bill Gallagher
14
 * @author Andy Piper
15
 * @author Hal Hildebrand
16
 * @author Adrian Colyer
17
 * @author Costin Leau
18
 * @author Olaf Otto
19
 */
20
public class ListenerServiceActivator implements BundleActivator {
21
    /**
22
     * Monitor used for dealing with the bundle activator and synchronous bundle threads
23
     */
24
    private final Object monitor = new Object();
25
    private boolean stopped = false;
26
    private OsgiBundleApplicationContextEventMulticaster multicaster;
27
    private volatile ListListenerAdapter osgiListeners;
28
    private final Log log = LogFactory.getLog(getClass());
29
    private final ExtenderConfiguration extenderConfiguration;
30
    private BundleContext extenderBundleContext;
31
32
    public ListenerServiceActivator(ExtenderConfiguration extenderConfiguration) {
33
        this.extenderConfiguration = extenderConfiguration;
34
    }
35
36
    public void start(BundleContext extenderBundleContext) throws Exception {
37
        this.extenderBundleContext = extenderBundleContext;
38
        initListenerService();
39
    }
40
41
    public void stop(BundleContext extenderBundleContext) throws Exception {
42
        synchronized (monitor) {
43
            if (stopped) {
44
                return;
45
            }
46
            stopped = true;
47
        }
48
49
        // release multicaster
50
        if (multicaster != null) {
51
            multicaster.removeAllListeners();
52
            multicaster = null;
53
        }
54
        // release listeners
55
        osgiListeners.destroy();
56
        osgiListeners = null;
57
    }
58
59
    protected void initListenerService() {
60
        this.multicaster = extenderConfiguration.getEventMulticaster();
61
62
        addApplicationListener(multicaster);
63
        multicaster.addApplicationListener(extenderConfiguration.getContextEventListener());
64
65
        if (log.isDebugEnabled())
66
            log.debug("Initialization of OSGi listeners service completed...");
67
    }
68
69
    protected void addApplicationListener(OsgiBundleApplicationContextEventMulticaster multicaster) {
70
        osgiListeners = new ListListenerAdapter(this.extenderBundleContext);
71
        osgiListeners.afterPropertiesSet();
72
        // register the listener that does the dispatching
73
        multicaster.addApplicationListener(osgiListeners);
74
    }
75
76
    public OsgiBundleApplicationContextEventMulticaster getMulticaster() {
77
        return multicaster;
78
    }
79
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LoggingActivator.java (+27 lines)
Added Link Here
1
package org.eclipse.gemini.blueprint.extender.internal.activator;
2
3
import org.apache.commons.logging.Log;
4
import org.apache.commons.logging.LogFactory;
5
import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
6
import org.osgi.framework.BundleActivator;
7
import org.osgi.framework.BundleContext;
8
import org.osgi.framework.Version;
9
10
/**
11
 * Simply writes status convenient status information to the log.
12
 *
13
 * @author Olaf Otto
14
 */
15
public class LoggingActivator implements BundleActivator {
16
    private final Log log = LogFactory.getLog(getClass());
17
18
    public void start(BundleContext extenderBundleContext) throws Exception {
19
        Version extenderVersion = OsgiBundleUtils.getBundleVersion(extenderBundleContext.getBundle());
20
        log.info("Starting [" + extenderBundleContext.getBundle().getSymbolicName() + "] bundle v.[" + extenderVersion + "]");
21
    }
22
23
    public void stop(BundleContext extenderBundleContext) throws Exception {
24
        Version extenderVersion = OsgiBundleUtils.getBundleVersion(extenderBundleContext.getBundle());
25
        log.info("Stopping [" + extenderBundleContext.getBundle().getSymbolicName() + "] bundle v.[" + extenderVersion + "]");
26
    }
27
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/NamespaceHandlerActivator.java (+115 lines)
Added Link Here
1
package org.eclipse.gemini.blueprint.extender.internal.activator;
2
3
import org.apache.commons.logging.Log;
4
import org.apache.commons.logging.LogFactory;
5
import org.eclipse.gemini.blueprint.extender.internal.activator.listeners.BaseListener;
6
import org.eclipse.gemini.blueprint.extender.internal.activator.listeners.NamespaceBundleLister;
7
import org.eclipse.gemini.blueprint.extender.internal.support.NamespaceManager;
8
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
9
import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
10
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
11
import org.osgi.framework.Bundle;
12
import org.osgi.framework.BundleActivator;
13
import org.osgi.framework.BundleContext;
14
import org.osgi.framework.Version;
15
16
/**
17
 * @author Bill Gallagher
18
 * @author Andy Piper
19
 * @author Hal Hildebrand
20
 * @author Adrian Colyer
21
 * @author Costin Leau
22
 * @author Olaf Otto
23
 */
24
public class NamespaceHandlerActivator implements BundleActivator {
25
    /**
26
     * Monitor used for dealing with the bundle activator and synchronous bundle threads
27
     */
28
    private final Object monitor = new Object();
29
    private boolean stopped = false;
30
    private final Log log = LogFactory.getLog(getClass());
31
    private NamespaceManager nsManager;
32
    private BaseListener nsListener;
33
    private long bundleId;
34
    private BundleContext extenderBundleContext;
35
    private DefaultVersionMatcher versionMatcher;
36
37
    public void start(BundleContext extenderBundleContext) {
38
        this.extenderBundleContext = extenderBundleContext;
39
        this.nsManager = new NamespaceManager(extenderBundleContext);
40
        this.bundleId = extenderBundleContext.getBundle().getBundleId();
41
        Version extenderVersion = OsgiBundleUtils.getBundleVersion(extenderBundleContext.getBundle());
42
        this.versionMatcher = new DefaultVersionMatcher(getManagedBundleExtenderVersionHeader(), extenderVersion);
43
44
        initNamespaceHandlers(extenderBundleContext);
45
    }
46
47
    public void stop(BundleContext context) throws Exception {
48
        synchronized (monitor) {
49
            if (stopped) {
50
                return;
51
            }
52
            stopped = true;
53
        }
54
55
        this.nsListener.close();
56
        this.extenderBundleContext.removeBundleListener(this.nsListener);
57
        this.nsListener = null;
58
        this.nsManager.destroy();
59
    }
60
61
    protected String getManagedBundleExtenderVersionHeader() {
62
        return ConfigUtils.EXTENDER_VERSION;
63
    }
64
65
    protected void initNamespaceHandlers(BundleContext extenderBundleContext) {
66
        nsManager = new NamespaceManager(extenderBundleContext);
67
68
        // register listener first to make sure any bundles in INSTALLED state
69
        // are not lost
70
71
        // if the property is defined and true, consider bundles in STARTED/LAZY-INIT state, otherwise use RESOLVED
72
        boolean nsResolved = !Boolean.getBoolean("org.eclipse.gemini.blueprint.ns.bundles.started");
73
        nsListener = new NamespaceBundleLister(nsResolved, this);
74
        extenderBundleContext.addBundleListener(nsListener);
75
76
        Bundle[] previousBundles = extenderBundleContext.getBundles();
77
78
        for (Bundle bundle : previousBundles) {
79
            // special handling for uber bundle being restarted
80
            if ((nsResolved && OsgiBundleUtils.isBundleResolved(bundle)) || (!nsResolved && OsgiBundleUtils.isBundleActive(bundle)) || bundleId == bundle.getBundleId()) {
81
                maybeAddNamespaceHandlerFor(bundle, false);
82
            } else if (OsgiBundleUtils.isBundleLazyActivated(bundle)) {
83
                maybeAddNamespaceHandlerFor(bundle, true);
84
            }
85
        }
86
87
        // discovery finished, publish the resolvers/parsers in the OSGi space
88
        nsManager.afterPropertiesSet();
89
    }
90
91
92
    public void maybeAddNamespaceHandlerFor(Bundle bundle, boolean isLazy) {
93
        if (handlerBundleMatchesExtenderVersion(bundle)) {
94
            nsManager.maybeAddNamespaceHandlerFor(bundle, isLazy);
95
        }
96
    }
97
98
    public void maybeRemoveNameSpaceHandlerFor(Bundle bundle) {
99
        if (handlerBundleMatchesExtenderVersion(bundle))
100
            nsManager.maybeRemoveNameSpaceHandlerFor(bundle);
101
    }
102
103
    /**
104
     * Utility method that does extender range version check and appropriate logging.
105
     */
106
    protected boolean handlerBundleMatchesExtenderVersion(Bundle bundle) {
107
        if (!versionMatcher.matchVersion(bundle)) {
108
            if (log.isDebugEnabled())
109
                log.debug("Ignoring handler bundle " + OsgiStringUtils.nullSafeNameAndSymName(bundle)
110
                        + "] due to mismatch in expected extender version");
111
            return false;
112
        }
113
        return true;
114
    }
115
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/listeners/BaseListener.java (+85 lines)
Added Link Here
1
package org.eclipse.gemini.blueprint.extender.internal.activator.listeners;
2
3
import org.apache.commons.logging.Log;
4
import org.apache.commons.logging.LogFactory;
5
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
6
import org.osgi.framework.Bundle;
7
import org.osgi.framework.BundleEvent;
8
import org.osgi.framework.SynchronousBundleListener;
9
10
import java.util.Map;
11
import java.util.WeakHashMap;
12
13
/**
14
 * Common base class for {@link org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener} listeners.
15
 *
16
 * @author Costin Leau
17
 */
18
public abstract class BaseListener implements SynchronousBundleListener {
19
    public static final int LAZY_ACTIVATION_EVENT_TYPE = 0x00000200;
20
21
    protected final Log log = LogFactory.getLog(getClass());
22
23
    /**
24
     * flag indicating whether the context is down or not - useful during shutdown
25
     */
26
    private volatile boolean isClosed = false;
27
28
    /**
29
     * common cache used for tracking down bundles started lazily so they don't get processed twice (once when
30
     * started lazy, once when started fully)
31
     */
32
    protected final Map<Bundle, Object> lazyBundleCache = new WeakHashMap<Bundle, Object>();
33
    /**
34
     * dummy value for the bundle cache
35
     */
36
    private final Object VALUE = new Object();
37
38
    // caches the bundle
39
    protected void push(Bundle bundle) {
40
        synchronized (lazyBundleCache) {
41
            lazyBundleCache.put(bundle, VALUE);
42
        }
43
    }
44
45
    // checks the presence of the bundle as well as removing it
46
    protected boolean pop(Bundle bundle) {
47
        synchronized (lazyBundleCache) {
48
            return (lazyBundleCache.remove(bundle) != null);
49
        }
50
    }
51
52
    /**
53
     * A bundle has been started, stopped, resolved, or unresolved. This method is a synchronous callback, do not do
54
     * any long-running work in this thread.
55
     *
56
     * @see org.osgi.framework.SynchronousBundleListener#bundleChanged
57
     */
58
    public void bundleChanged(BundleEvent event) {
59
60
        boolean trace = log.isTraceEnabled();
61
62
        // check if the listener is still alive
63
        if (isClosed) {
64
            if (trace)
65
                log.trace("Listener is closed; events are being ignored");
66
            return;
67
        }
68
        if (trace) {
69
            log.trace("Processing bundle event [" + OsgiStringUtils.nullSafeToString(event) + "] for bundle ["
70
                    + OsgiStringUtils.nullSafeSymbolicName(event.getBundle()) + "]");
71
        }
72
        try {
73
            handleEvent(event);
74
        } catch (Exception ex) {
75
            /* log exceptions before swallowing */
76
            log.warn("Got exception while handling event " + event, ex);
77
        }
78
    }
79
80
    protected abstract void handleEvent(BundleEvent event);
81
82
    public void close() {
83
        this.isClosed = true;
84
    }
85
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/listeners/NamespaceBundleLister.java (+59 lines)
Added Link Here
1
package org.eclipse.gemini.blueprint.extender.internal.activator.listeners;
2
3
import org.eclipse.gemini.blueprint.extender.internal.activator.NamespaceHandlerActivator;
4
import org.osgi.framework.Bundle;
5
import org.osgi.framework.BundleEvent;
6
7
/**
8
 * Bundle listener used for detecting namespace handler/resolvers. Exists as a separate listener so that it can be
9
 * registered early to avoid race conditions with bundles in INSTALLING state but still to avoid premature context
10
 * creation before the Spring {@link org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener} is not fully initialized.
11
 *
12
 * @author Costin Leau
13
 */
14
public class NamespaceBundleLister extends BaseListener {
15
16
    private final boolean resolved;
17
    private final NamespaceHandlerActivator namespaceHandlerActivator;
18
19
    public NamespaceBundleLister(boolean resolvedBundles, NamespaceHandlerActivator namespaceHandlerActivator) {
20
        this.resolved = resolvedBundles;
21
        this.namespaceHandlerActivator = namespaceHandlerActivator;
22
    }
23
24
    protected void handleEvent(BundleEvent event) {
25
        Bundle bundle = event.getBundle();
26
27
        switch (event.getType()) {
28
29
            case BundleEvent.RESOLVED:
30
                if (resolved) {
31
                    this.namespaceHandlerActivator.maybeAddNamespaceHandlerFor(bundle, false);
32
                }
33
                break;
34
35
            case LAZY_ACTIVATION_EVENT_TYPE: {
36
                if (!resolved) {
37
                    push(bundle);
38
                    this.namespaceHandlerActivator.maybeAddNamespaceHandlerFor(bundle, true);
39
                }
40
                break;
41
            }
42
            case BundleEvent.STARTED: {
43
                if (!resolved) {
44
                    if (!pop(bundle)) {
45
                        this.namespaceHandlerActivator.maybeAddNamespaceHandlerFor(bundle, false);
46
                    }
47
                }
48
                break;
49
            }
50
            case BundleEvent.STOPPED: {
51
                pop(bundle);
52
                this.namespaceHandlerActivator.maybeRemoveNameSpaceHandlerFor(bundle);
53
                break;
54
            }
55
            default:
56
                break;
57
        }
58
    }
59
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/BlueprintLoaderListener.java (-34 / +29 lines)
Lines 14-32 Link Here
14
14
15
package org.eclipse.gemini.blueprint.extender.internal.blueprint.activator;
15
package org.eclipse.gemini.blueprint.extender.internal.blueprint.activator;
16
16
17
import org.osgi.framework.Bundle;
17
import org.eclipse.gemini.blueprint.extender.OsgiApplicationContextCreator;
18
import org.osgi.framework.BundleContext;
18
import org.eclipse.gemini.blueprint.extender.internal.activator.*;
19
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;
20
import org.eclipse.gemini.blueprint.extender.internal.activator.ApplicationContextConfigurationFactory;
21
import org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener;
22
import org.eclipse.gemini.blueprint.extender.internal.activator.OsgiContextProcessor;
23
import org.eclipse.gemini.blueprint.extender.internal.activator.TypeCompatibilityChecker;
24
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintConfigUtils;
19
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintConfigUtils;
25
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintContainerConfig;
20
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintContainerConfig;
26
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintExtenderConfiguration;
21
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintContainerCreator;
27
import org.eclipse.gemini.blueprint.extender.internal.blueprint.event.EventAdminDispatcher;
22
import org.eclipse.gemini.blueprint.extender.internal.blueprint.event.EventAdminDispatcher;
28
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
23
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
29
import org.eclipse.gemini.blueprint.extender.support.ApplicationContextConfiguration;
24
import org.eclipse.gemini.blueprint.extender.support.ApplicationContextConfiguration;
25
import org.osgi.framework.Bundle;
26
import org.osgi.framework.BundleContext;
30
27
31
/**
28
/**
32
 * RFC124 extension to the Spring DM extender.
29
 * RFC124 extension to the Spring DM extender.
Lines 34-54 import org.eclipse.gemini.blueprint.extender.support.ApplicationContextConfigura Link Here
34
 * @author Costin Leau
31
 * @author Costin Leau
35
 */
32
 */
36
public class BlueprintLoaderListener extends ContextLoaderListener {
33
public class BlueprintLoaderListener extends ContextLoaderListener {
37
34
    private volatile BlueprintListenerManager listenerManager;
38
	private volatile EventAdminDispatcher dispatcher;
35
    private volatile BlueprintContainerProcessor contextProcessor;
39
	private volatile BlueprintListenerManager listenerManager;
40
	private volatile Bundle bundle;
41
	private volatile BlueprintContainerProcessor contextProcessor;
42
	private volatile TypeCompatibilityChecker typeChecker;
36
	private volatile TypeCompatibilityChecker typeChecker;
37
    private ListenerServiceActivator listenerServiceActivator;
43
38
44
	@Override
39
    public BlueprintLoaderListener(ExtenderConfiguration extenderConfiguration, ListenerServiceActivator listenerServiceActivator) {
40
        super(extenderConfiguration);
41
        this.listenerServiceActivator = listenerServiceActivator;
42
    }
43
44
    @Override
45
	public void start(BundleContext context) throws Exception {
45
	public void start(BundleContext context) throws Exception {
46
		this.listenerManager = new BlueprintListenerManager(context);
46
		this.listenerManager = new BlueprintListenerManager(context);
47
		this.dispatcher = new EventAdminDispatcher(context);
47
        EventAdminDispatcher dispatcher = new EventAdminDispatcher(context);
48
		this.bundle = context.getBundle();
48
        Bundle bundle = context.getBundle();
49
		this.contextProcessor = new BlueprintContainerProcessor(dispatcher, listenerManager, bundle);
49
		this.contextProcessor = new BlueprintContainerProcessor(dispatcher, listenerManager, bundle);
50
		this.typeChecker = new BlueprintTypeCompatibilityChecker(bundle);
50
		this.typeChecker = new BlueprintTypeCompatibilityChecker(bundle);
51
51
        this.listenerServiceActivator.getMulticaster().addApplicationListener(this.contextProcessor);
52
		super.start(context);
52
		super.start(context);
53
	}
53
	}
54
54
Lines 59-69 public class BlueprintLoaderListener extends ContextLoaderListener { Link Here
59
	}
59
	}
60
60
61
	@Override
61
	@Override
62
	protected ExtenderConfiguration initExtenderConfiguration(BundleContext bundleContext) {
63
		return new BlueprintExtenderConfiguration(bundleContext, log);
64
	}
65
66
	@Override
67
	protected ApplicationContextConfigurationFactory createContextConfigFactory() {
62
	protected ApplicationContextConfigurationFactory createContextConfigFactory() {
68
		return new ApplicationContextConfigurationFactory() {
63
		return new ApplicationContextConfigurationFactory() {
69
64
Lines 73-79 public class BlueprintLoaderListener extends ContextLoaderListener { Link Here
73
		};
68
		};
74
	}
69
	}
75
70
76
	@Override
71
    /**
72
     * Always use the {@link BlueprintContainerCreator}, never the configured creator.
73
     * Rationale: Backwards compatibility. Both DM and Blueprint extenders are available simultaneously,
74
     * however Blueprint extender support is new and must not be broken by existing configurations. Otherwise, existing
75
     * users would have to make their creators aware of the difference between blueprint and dm containers.
76
     */
77
    @Override
78
    protected OsgiApplicationContextCreator getOsgiApplicationContextCreator() {
79
        return new BlueprintContainerCreator();
80
    }
81
82
    @Override
77
	protected OsgiContextProcessor createContextProcessor() {
83
	protected OsgiContextProcessor createContextProcessor() {
78
		return contextProcessor;
84
		return contextProcessor;
79
	}
85
	}
Lines 87-101 public class BlueprintLoaderListener extends ContextLoaderListener { Link Here
87
	protected String getManagedBundleExtenderVersionHeader() {
93
	protected String getManagedBundleExtenderVersionHeader() {
88
		return BlueprintConfigUtils.EXTENDER_VERSION;
94
		return BlueprintConfigUtils.EXTENDER_VERSION;
89
	}
95
	}
90
91
	@Override
92
	protected void addApplicationListener(OsgiBundleApplicationContextEventMulticaster multicaster) {
93
		super.addApplicationListener(multicaster);
94
		// monitor bootstrapping events
95
		multicaster.addApplicationListener(contextProcessor);
96
	}
97
98
	protected ApplicationContextConfiguration createContextConfig(Bundle bundle) {
99
		return new BlueprintContainerConfig(bundle);
100
	}
101
}
96
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintExtenderConfiguration.java (-44 lines)
Lines 1-44 Link Here
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution. 
6
 * The Eclipse Public License is available at 
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
8
 * is available at http://www.opensource.org/licenses/apache2.0.php.
9
 * You may elect to redistribute this code under either of these licenses. 
10
 * 
11
 * Contributors:
12
 *   VMware Inc.
13
 *****************************************************************************/
14
15
package org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support;
16
17
import org.apache.commons.logging.Log;
18
import org.eclipse.gemini.blueprint.extender.OsgiApplicationContextCreator;
19
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
20
import org.osgi.framework.BundleContext;
21
22
/**
23
 * Extension of the default extender configuration for handling RFC 124 extender semantics.
24
 * 
25
 * @author Costin Leau
26
 * 
27
 */
28
public class BlueprintExtenderConfiguration extends ExtenderConfiguration {
29
30
	private final OsgiApplicationContextCreator contextCreator = new BlueprintContainerCreator();
31
32
	/**
33
	 * Constructs a new <code>BlueprintExtenderConfiguration</code> instance.
34
	 * 
35
	 * @param bundleContext
36
	 */
37
	public BlueprintExtenderConfiguration(BundleContext bundleContext, Log log) {
38
		super(bundleContext, log);
39
	}
40
41
	public OsgiApplicationContextCreator getContextCreator() {
42
		return contextCreator;
43
	}
44
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/boot/ChainActivator.java (-8 / +41 lines)
Lines 16-33 package org.eclipse.gemini.blueprint.extender.internal.boot; Link Here
16
16
17
import org.apache.commons.logging.Log;
17
import org.apache.commons.logging.Log;
18
import org.apache.commons.logging.LogFactory;
18
import org.apache.commons.logging.LogFactory;
19
import org.eclipse.gemini.blueprint.extender.internal.activator.*;
20
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
19
import org.osgi.framework.BundleActivator;
21
import org.osgi.framework.BundleActivator;
20
import org.osgi.framework.BundleContext;
22
import org.osgi.framework.BundleContext;
21
import org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener;
22
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.BlueprintLoaderListener;
23
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.BlueprintLoaderListener;
23
import org.eclipse.gemini.blueprint.util.OsgiPlatformDetector;
24
import org.eclipse.gemini.blueprint.util.OsgiPlatformDetector;
24
import org.springframework.util.ClassUtils;
25
import org.springframework.util.ClassUtils;
25
26
26
/**
27
/**
27
 * Bundle activator that simply the lifecycle callbacks to other activators.
28
 * Bundle activator that simply the lifecycle callbacks to other activators.
28
 * 
29
 *
29
 * @author Costin Leau
30
 * @author Costin Leau
30
 * 
31
 *
31
 */
32
 */
32
public class ChainActivator implements BundleActivator {
33
public class ChainActivator implements BundleActivator {
33
34
Lines 40-58 public class ChainActivator implements BundleActivator { Link Here
40
	private final BundleActivator[] CHAIN;
41
	private final BundleActivator[] CHAIN;
41
42
42
	public ChainActivator() {
43
	public ChainActivator() {
43
		if (OsgiPlatformDetector.isR42()) {
44
        final LoggingActivator logStatus = new LoggingActivator();
45
        final JavaBeansCacheActivator activateJavaBeansCache = new JavaBeansCacheActivator();
46
        final NamespaceHandlerActivator activateCustomNamespaceHandling = new NamespaceHandlerActivator();
47
        final NamespaceHandlerActivator activateBlueprintspecificNamespaceHandling = new BlueprintNamespaceHandlerActivator();
48
        final ExtenderConfiguration initializeExtenderConfiguration = new ExtenderConfiguration();
49
        final ListenerServiceActivator activateListeners = new ListenerServiceActivator(initializeExtenderConfiguration);
50
        final ContextLoaderListener listenForSpringDmBundles = new ContextLoaderListener(initializeExtenderConfiguration);
51
        final BlueprintLoaderListener listenForBlueprintBundles = new BlueprintLoaderListener(initializeExtenderConfiguration, activateListeners);
52
53
        if (OsgiPlatformDetector.isR42()) {
44
			if (BLUEPRINT_AVAILABLE) {
54
			if (BLUEPRINT_AVAILABLE) {
45
				log.info("Blueprint API detected; enabling Blueprint Container functionality");
55
				log.info("Blueprint API detected; enabling Blueprint Container functionality");
46
				CHAIN = new BundleActivator[] { new ContextLoaderListener(), new BlueprintLoaderListener() };
56
				CHAIN = new BundleActivator[] {
57
                        logStatus,
58
                        activateJavaBeansCache,
59
                        activateCustomNamespaceHandling,
60
                        activateBlueprintspecificNamespaceHandling,
61
                        initializeExtenderConfiguration,
62
                        activateListeners,
63
                        listenForSpringDmBundles,
64
                        listenForBlueprintBundles
65
                };
47
			}
66
			}
48
			else {
67
			else {
49
				log.warn("Blueprint API not found; disabling Blueprint Container functionality");
68
				log.warn("Blueprint API not found; disabling Blueprint Container functionality");
50
				CHAIN = new BundleActivator[] { new ContextLoaderListener() };	
69
				CHAIN = new BundleActivator[] {
70
                        logStatus,
71
                        activateJavaBeansCache,
72
                        activateCustomNamespaceHandling,
73
                        initializeExtenderConfiguration,
74
                        activateListeners,
75
                        listenForSpringDmBundles
76
                };
51
			}
77
			}
52
		} else {
78
		} else {
53
			log.warn("Pre-4.2 OSGi platform detected; disabling Blueprint Container functionality");
79
			log.warn("Pre-4.2 OSGi platform detected; disabling Blueprint Container functionality");
54
			CHAIN = new BundleActivator[] { new ContextLoaderListener() };
80
            CHAIN = new BundleActivator[] {
55
		}
81
                    logStatus,
82
                    activateJavaBeansCache,
83
                    activateCustomNamespaceHandling,
84
                    initializeExtenderConfiguration,
85
                    activateListeners,
86
                    listenForSpringDmBundles
87
            };
88
        }
56
	}
89
	}
57
90
58
	public void start(BundleContext context) throws Exception {
91
	public void start(BundleContext context) throws Exception {
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/support/DefaultOsgiBundleApplicationContextListener.java (-2 / +1 lines)
Lines 21-30 import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextLi Link Here
21
import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextClosedEvent;
21
import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextClosedEvent;
22
import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextFailedEvent;
22
import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextFailedEvent;
23
import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextRefreshedEvent;
23
import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextRefreshedEvent;
24
import org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener;
25
24
26
/**
25
/**
27
 * Default application context event logger. Logs (using the {@link ContextLoaderListener} logger, the events received.
26
 * Default application context event logger. Logs (using the {@link org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener} logger, the events received.
28
 * 
27
 * 
29
 * @author Costin Leau
28
 * @author Costin Leau
30
 * @author Andy Piper
29
 * @author Andy Piper
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfiguration.java (-37 / +25 lines)
Lines 14-37 Link Here
14
14
15
package org.eclipse.gemini.blueprint.extender.internal.support;
15
package org.eclipse.gemini.blueprint.extender.internal.support;
16
16
17
import java.io.UnsupportedEncodingException;
18
import java.net.URL;
19
import java.net.URLDecoder;
20
import java.util.ArrayList;
21
import java.util.Collections;
22
import java.util.Enumeration;
23
import java.util.List;
24
import java.util.Properties;
25
import java.util.Timer;
26
27
import org.apache.commons.logging.Log;
17
import org.apache.commons.logging.Log;
28
import org.osgi.framework.Bundle;
18
import org.apache.commons.logging.LogFactory;
29
import org.osgi.framework.BundleContext;
30
import org.springframework.beans.BeanUtils;
31
import org.springframework.beans.factory.DisposableBean;
32
import org.springframework.context.event.SimpleApplicationEventMulticaster;
33
import org.springframework.core.task.SimpleAsyncTaskExecutor;
34
import org.springframework.core.task.TaskExecutor;
35
import org.eclipse.gemini.blueprint.context.ConfigurableOsgiBundleApplicationContext;
19
import org.eclipse.gemini.blueprint.context.ConfigurableOsgiBundleApplicationContext;
36
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;
20
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;
37
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;
21
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;
Lines 41-65 import org.eclipse.gemini.blueprint.extender.OsgiApplicationContextCreator; Link Here
41
import org.eclipse.gemini.blueprint.extender.OsgiBeanFactoryPostProcessor;
25
import org.eclipse.gemini.blueprint.extender.OsgiBeanFactoryPostProcessor;
42
import org.eclipse.gemini.blueprint.extender.OsgiServiceDependencyFactory;
26
import org.eclipse.gemini.blueprint.extender.OsgiServiceDependencyFactory;
43
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;
27
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;
44
import org.eclipse.gemini.blueprint.extender.support.DefaultOsgiApplicationContextCreator;
45
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
28
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
46
import org.eclipse.gemini.blueprint.util.BundleDelegatingClassLoader;
29
import org.eclipse.gemini.blueprint.util.BundleDelegatingClassLoader;
30
import org.osgi.framework.Bundle;
31
import org.osgi.framework.BundleActivator;
32
import org.osgi.framework.BundleContext;
33
import org.springframework.beans.BeanUtils;
34
import org.springframework.beans.factory.DisposableBean;
35
import org.springframework.context.event.SimpleApplicationEventMulticaster;
36
import org.springframework.core.task.SimpleAsyncTaskExecutor;
37
import org.springframework.core.task.TaskExecutor;
47
import org.springframework.scheduling.timer.TimerTaskExecutor;
38
import org.springframework.scheduling.timer.TimerTaskExecutor;
48
import org.springframework.util.Assert;
39
import org.springframework.util.Assert;
49
import org.springframework.util.ObjectUtils;
40
import org.springframework.util.ObjectUtils;
50
41
42
import java.io.UnsupportedEncodingException;
43
import java.net.URL;
44
import java.net.URLDecoder;
45
import java.util.*;
46
51
/**
47
/**
52
 * Configuration class for the extender. Takes care of locating the extender specific configurations and merging the
48
 * Configuration class for the extender. Takes care of locating the extender specific configurations and merging the
53
 * results with the defaults.
49
 * results with the defaults.
54
 * 
50
 * 
55
 * @author Costin Leau
51
 * @author Costin Leau
56
 */
52
 */
57
public class ExtenderConfiguration implements DisposableBean {
53
public class ExtenderConfiguration implements BundleActivator {
58
54
59
	/** logger */
55
	/** logger */
60
	private final Log log;
56
    protected final Log log = LogFactory.getLog(getClass());
61
57
62
	private static final String TASK_EXECUTOR_NAME = "taskExecutor";
58
    private static final String TASK_EXECUTOR_NAME = "taskExecutor";
63
59
64
	private static final String SHUTDOWN_TASK_EXECUTOR_NAME = "shutdownTaskExecutor";
60
	private static final String SHUTDOWN_TASK_EXECUTOR_NAME = "shutdownTaskExecutor";
65
61
Lines 118-127 public class ExtenderConfiguration implements DisposableBean { Link Here
118
114
119
	private boolean forceThreadShutdown;
115
	private boolean forceThreadShutdown;
120
116
121
	private OsgiApplicationContextCreator contextCreator;
117
	private OsgiApplicationContextCreator contextCreator = null;
122
118
123
	/** bundle wrapped class loader */
119
	/** bundle wrapped class loader */
124
	private final ClassLoader classLoader;
120
	private ClassLoader classLoader;
125
	/** List of context post processors */
121
	/** List of context post processors */
126
	private final List<OsgiBeanFactoryPostProcessor> postProcessors =
122
	private final List<OsgiBeanFactoryPostProcessor> postProcessors =
127
			Collections.synchronizedList(new ArrayList<OsgiBeanFactoryPostProcessor>(0));
123
			Collections.synchronizedList(new ArrayList<OsgiBeanFactoryPostProcessor>(0));
Lines 136-160 public class ExtenderConfiguration implements DisposableBean { Link Here
136
	 * Constructs a new <code>ExtenderConfiguration</code> instance. Locates the extender configuration, creates an
132
	 * Constructs a new <code>ExtenderConfiguration</code> instance. Locates the extender configuration, creates an
137
	 * application context which will returned the extender items.
133
	 * application context which will returned the extender items.
138
	 * 
134
	 * 
139
	 * @param bundleContext extender OSGi bundle context
135
	 * @param extenderBundleContext extender OSGi bundle context
140
	 */
136
	 */
141
	public ExtenderConfiguration(BundleContext bundleContext, Log log) {
137
	public void start(BundleContext extenderBundleContext) {
142
		this.log = log;
138
		Bundle bundle = extenderBundleContext.getBundle();
143
		Bundle bundle = bundleContext.getBundle();
144
		Properties properties = new Properties(createDefaultProperties());
139
		Properties properties = new Properties(createDefaultProperties());
145
140
146
		Enumeration<?> enm = bundle.findEntries(EXTENDER_CFG_LOCATION, XML_PATTERN, false);
141
		Enumeration<?> enm = bundle.findEntries(EXTENDER_CFG_LOCATION, XML_PATTERN, false);
147
142
148
		if (enm == null) {
143
		if (enm == null) {
149
			log.info("No custom extender configuration detected; using defaults...");
144
			log.info("No custom extender configuration detected; using defaults...");
150
151
			synchronized (lock) {
145
			synchronized (lock) {
152
				taskExecutor = createDefaultTaskExecutor();
146
				taskExecutor = createDefaultTaskExecutor();
153
				shutdownTaskExecutor = createDefaultShutdownTaskExecutor();
147
				shutdownTaskExecutor = createDefaultShutdownTaskExecutor();
154
				eventMulticaster = createDefaultEventMulticaster();
148
				eventMulticaster = createDefaultEventMulticaster();
155
				contextCreator = createDefaultApplicationContextCreator();
156
				contextEventListener = createDefaultApplicationContextListener();
149
				contextEventListener = createDefaultApplicationContextListener();
157
158
			}
150
			}
159
			classLoader = BundleDelegatingClassLoader.createBundleClassLoaderFor(bundle);
151
			classLoader = BundleDelegatingClassLoader.createBundleClassLoaderFor(bundle);
160
		} else {
152
		} else {
Lines 163-169 public class ExtenderConfiguration implements DisposableBean { Link Here
163
			log.info("Detected extender custom configurations at " + ObjectUtils.nullSafeToString(configs));
155
			log.info("Detected extender custom configurations at " + ObjectUtils.nullSafeToString(configs));
164
			// create OSGi specific XML context
156
			// create OSGi specific XML context
165
			ConfigurableOsgiBundleApplicationContext extenderAppCtx = new OsgiBundleXmlApplicationContext(configs);
157
			ConfigurableOsgiBundleApplicationContext extenderAppCtx = new OsgiBundleXmlApplicationContext(configs);
166
			extenderAppCtx.setBundleContext(bundleContext);
158
			extenderAppCtx.setBundleContext(extenderBundleContext);
167
			extenderAppCtx.refresh();
159
			extenderAppCtx.refresh();
168
160
169
			synchronized (lock) {
161
			synchronized (lock) {
Lines 187-193 public class ExtenderConfiguration implements DisposableBean { Link Here
187
				contextCreator =
179
				contextCreator =
188
						extenderConfiguration.containsBean(CONTEXT_CREATOR_NAME) ? (OsgiApplicationContextCreator) extenderConfiguration
180
						extenderConfiguration.containsBean(CONTEXT_CREATOR_NAME) ? (OsgiApplicationContextCreator) extenderConfiguration
189
								.getBean(CONTEXT_CREATOR_NAME, OsgiApplicationContextCreator.class)
181
								.getBean(CONTEXT_CREATOR_NAME, OsgiApplicationContextCreator.class)
190
								: createDefaultApplicationContextCreator();
182
								: null;
191
183
192
				contextEventListener =
184
				contextEventListener =
193
						extenderConfiguration.containsBean(CONTEXT_LISTENER_NAME) ? (OsgiBundleApplicationContextListener) extenderConfiguration
185
						extenderConfiguration.containsBean(CONTEXT_LISTENER_NAME) ? (OsgiBundleApplicationContextListener) extenderConfiguration
Lines 243-249 public class ExtenderConfiguration implements DisposableBean { Link Here
243
	 * 
235
	 * 
244
	 * Cleanup the configuration items.
236
	 * Cleanup the configuration items.
245
	 */
237
	 */
246
	public void destroy() {
238
	public void stop(BundleContext extenderBundleContext) {
247
239
248
		synchronized (lock) {
240
		synchronized (lock) {
249
			if (isMulticasterManagedInternally) {
241
			if (isMulticasterManagedInternally) {
Lines 388-397 public class ExtenderConfiguration implements DisposableBean { Link Here
388
		return new OsgiBundleApplicationContextEventMulticasterAdapter(new SimpleApplicationEventMulticaster());
380
		return new OsgiBundleApplicationContextEventMulticasterAdapter(new SimpleApplicationEventMulticaster());
389
	}
381
	}
390
382
391
	private OsgiApplicationContextCreator createDefaultApplicationContextCreator() {
392
		return new DefaultOsgiApplicationContextCreator();
393
	}
394
395
	private OsgiBundleApplicationContextListener createDefaultApplicationContextListener() {
383
	private OsgiBundleApplicationContextListener createDefaultApplicationContextListener() {
396
		return new DefaultOsgiBundleApplicationContextListener(log);
384
		return new DefaultOsgiBundleApplicationContextListener(log);
397
	}
385
	}
(-)a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/ContextLoaderListenerTest.java (-102 / +103 lines)
Lines 12-123 Link Here
12
 *   VMware Inc.
12
 *   VMware Inc.
13
 *****************************************************************************/
13
 *****************************************************************************/
14
14
15
package org.eclipse.gemini.blueprint.extender.internal;
15
package org.eclipse.gemini.blueprint.extender.internal;
16
16
17
import java.util.Dictionary;
17
import java.util.Dictionary;
18
import java.util.Hashtable;
18
import java.util.Hashtable;
19
import java.util.Properties;
19
import java.util.Properties;
20
20
21
import junit.framework.TestCase;
21
import junit.framework.TestCase;
22
22
23
import org.easymock.MockControl;
23
import org.easymock.MockControl;
24
import org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener;
24
import org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener;
25
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
25
import org.eclipse.gemini.blueprint.extender.internal.support.TestTaskExecutor;
26
import org.eclipse.gemini.blueprint.extender.internal.support.TestTaskExecutor;
26
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
27
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
27
import org.eclipse.gemini.blueprint.mock.EntryLookupControllingMockBundle;
28
import org.eclipse.gemini.blueprint.mock.EntryLookupControllingMockBundle;
28
import org.eclipse.gemini.blueprint.mock.MockBundle;
29
import org.eclipse.gemini.blueprint.mock.MockBundle;
29
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
30
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
30
import org.eclipse.gemini.blueprint.mock.MockServiceRegistration;
31
import org.eclipse.gemini.blueprint.mock.MockServiceRegistration;
31
import org.osgi.framework.Bundle;
32
import org.osgi.framework.Bundle;
32
import org.osgi.framework.BundleContext;
33
import org.osgi.framework.BundleContext;
33
import org.osgi.framework.BundleEvent;
34
import org.osgi.framework.BundleEvent;
34
import org.osgi.framework.BundleListener;
35
import org.osgi.framework.BundleListener;
35
import org.osgi.framework.Constants;
36
import org.osgi.framework.Constants;
36
import org.springframework.core.io.ClassPathResource;
37
import org.springframework.core.io.ClassPathResource;
37
38
38
/**
39
/**
39
 * @author Adrian Colyer
40
 * @author Adrian Colyer
40
 * 
41
 * 
41
 */
42
 */
42
public abstract class ContextLoaderListenerTest extends TestCase {
43
public abstract class ContextLoaderListenerTest extends TestCase {
43
44
	private ContextLoaderListener listener;
44
	private ContextLoaderListener listener;
45
    // TODO: mock & train once there are any applications of this base class.
45
46
    private ExtenderConfiguration configuration;
46
47
47
	protected void setUp() throws Exception {
48
    protected void setUp() throws Exception {
48
		super.setUp();
49
		super.setUp();
49
		this.listener = new ContextLoaderListener();
50
		this.listener = new ContextLoaderListener(this.configuration);
50
	}
51
	}
51
52
52
	public void testStart() throws Exception {
53
	public void testStart() throws Exception {
53
		MockControl bundleContextControl = MockControl.createControl(BundleContext.class);
54
		MockControl bundleContextControl = MockControl.createControl(BundleContext.class);
54
		BundleContext context = (BundleContext) bundleContextControl.getMock();
55
		BundleContext context = (BundleContext) bundleContextControl.getMock();
55
		// platform determination
56
		// platform determination
56
57
57
		// extracting bundle id from bundle
58
		// extracting bundle id from bundle
58
		bundleContextControl.expectAndReturn(context.getBundle(), new MockBundle());
59
		bundleContextControl.expectAndReturn(context.getBundle(), new MockBundle());
59
60
60
		// look for existing resolved bundles
61
		// look for existing resolved bundles
61
		bundleContextControl.expectAndReturn(context.getBundles(), new Bundle[0], 2);
62
		bundleContextControl.expectAndReturn(context.getBundles(), new Bundle[0], 2);
62
63
63
		// register namespace and entity resolving service
64
		// register namespace and entity resolving service
64
		// context.registerService((String[]) null, null, null);
65
		// context.registerService((String[]) null, null, null);
65
		// bundleContextControl.setMatcher(MockControl.ALWAYS_MATCHER);
66
		// bundleContextControl.setMatcher(MockControl.ALWAYS_MATCHER);
66
		// bundleContextControl.setReturnValue(null);
67
		// bundleContextControl.setReturnValue(null);
67
68
68
		// register context service
69
		// register context service
69
		context.registerService((String[]) null, null, null);
70
		context.registerService((String[]) null, null, null);
70
		bundleContextControl.setMatcher(MockControl.ALWAYS_MATCHER);
71
		bundleContextControl.setMatcher(MockControl.ALWAYS_MATCHER);
71
		bundleContextControl.setReturnValue(null, MockControl.ONE_OR_MORE);
72
		bundleContextControl.setReturnValue(null, MockControl.ONE_OR_MORE);
72
73
73
		// create task executor
74
		// create task executor
74
		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(null);
75
		EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(null);
75
		aBundle.setEntryReturnOnNextCallToGetEntry(null);
76
		aBundle.setEntryReturnOnNextCallToGetEntry(null);
76
		bundleContextControl.expectAndReturn(context.getBundle(), aBundle, MockControl.ONE_OR_MORE);
77
		bundleContextControl.expectAndReturn(context.getBundle(), aBundle, MockControl.ONE_OR_MORE);
77
78
78
		// listen for bundle events
79
		// listen for bundle events
79
		context.addBundleListener(null);
80
		context.addBundleListener(null);
80
		bundleContextControl.setMatcher(MockControl.ALWAYS_MATCHER);
81
		bundleContextControl.setMatcher(MockControl.ALWAYS_MATCHER);
81
		bundleContextControl.setVoidCallable(2);
82
		bundleContextControl.setVoidCallable(2);
82
83
83
		bundleContextControl.expectAndReturn(context.registerService(new String[0], null, new Properties()),
84
		bundleContextControl.expectAndReturn(context.registerService(new String[0], null, new Properties()),
84
			new MockServiceRegistration(), MockControl.ONE_OR_MORE);
85
			new MockServiceRegistration(), MockControl.ONE_OR_MORE);
85
		bundleContextControl.setMatcher(MockControl.ALWAYS_MATCHER);
86
		bundleContextControl.setMatcher(MockControl.ALWAYS_MATCHER);
86
87
87
		bundleContextControl.replay();
88
		bundleContextControl.replay();
88
89
89
		this.listener.start(context);
90
		this.listener.start(context);
90
		bundleContextControl.verify();
91
		bundleContextControl.verify();
91
	}
92
	}
92
93
93
	public void tstTaskExecutor() throws Exception {
94
	public void tstTaskExecutor() throws Exception {
94
		Dictionary headers = new Hashtable();
95
		Dictionary headers = new Hashtable();
95
		headers.put(Constants.BUNDLE_NAME, "Extender mock bundle");
96
		headers.put(Constants.BUNDLE_NAME, "Extender mock bundle");
96
		final EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
97
		final EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);
97
		aBundle.setEntryReturnOnNextCallToGetEntry(new ClassPathResource("META-INF/spring/moved-extender.xml").getURL());
98
		aBundle.setEntryReturnOnNextCallToGetEntry(new ClassPathResource("META-INF/spring/moved-extender.xml").getURL());
98
99
99
		MockBundleContext ctx = new MockBundleContext() {
100
		MockBundleContext ctx = new MockBundleContext() {
100
101
101
			public Bundle getBundle() {
102
			public Bundle getBundle() {
102
				return aBundle;
103
				return aBundle;
103
			}
104
			}
104
		};
105
		};
105
106
106
		this.listener.start(ctx);
107
		this.listener.start(ctx);
107
108
108
		Dictionary hdrs = new Hashtable();
109
		Dictionary hdrs = new Hashtable();
109
		hdrs.put(ConfigUtils.SPRING_CONTEXT_HEADER, "bla bla");
110
		hdrs.put(ConfigUtils.SPRING_CONTEXT_HEADER, "bla bla");
110
		MockBundle anotherBundle = new MockBundle(hdrs);
111
		MockBundle anotherBundle = new MockBundle(hdrs);
111
		anotherBundle.setBundleId(1);
112
		anotherBundle.setBundleId(1);
112
113
113
		BundleEvent event = new BundleEvent(BundleEvent.STARTED, anotherBundle);
114
		BundleEvent event = new BundleEvent(BundleEvent.STARTED, anotherBundle);
114
115
115
		BundleListener listener = (BundleListener) ctx.getBundleListeners().iterator().next();
116
		BundleListener listener = (BundleListener) ctx.getBundleListeners().iterator().next();
116
117
117
		TestTaskExecutor.called = false;
118
		TestTaskExecutor.called = false;
118
119
119
		listener.bundleChanged(event);
120
		listener.bundleChanged(event);
120
		assertTrue("task executor should have been called if configured properly", TestTaskExecutor.called);
121
		assertTrue("task executor should have been called if configured properly", TestTaskExecutor.called);
121
	}
122
	}
122
123
123
}
124
}
(-)a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationCustomSettingsTest.java (-13 / +11 lines)
Lines 14-36 Link Here
14
14
15
package org.eclipse.gemini.blueprint.extender.internal.support;
15
package org.eclipse.gemini.blueprint.extender.internal.support;
16
16
17
import java.net.URL;
18
import java.util.Enumeration;
19
import java.util.List;
20
21
import junit.framework.TestCase;
17
import junit.framework.TestCase;
22
23
import org.apache.commons.logging.LogFactory;
24
import org.osgi.framework.Bundle;
25
import org.osgi.framework.BundleContext;
26
import org.springframework.core.task.SimpleAsyncTaskExecutor;
27
import org.springframework.core.task.TaskExecutor;
28
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;
18
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;
29
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;
19
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;
30
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
31
import org.eclipse.gemini.blueprint.mock.ArrayEnumerator;
20
import org.eclipse.gemini.blueprint.mock.ArrayEnumerator;
32
import org.eclipse.gemini.blueprint.mock.MockBundle;
21
import org.eclipse.gemini.blueprint.mock.MockBundle;
33
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
22
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
23
import org.osgi.framework.Bundle;
24
import org.osgi.framework.BundleContext;
25
import org.springframework.core.task.SimpleAsyncTaskExecutor;
26
import org.springframework.core.task.TaskExecutor;
27
28
import java.net.URL;
29
import java.util.Enumeration;
30
import java.util.List;
34
31
35
/**
32
/**
36
 * @author Costin Leau
33
 * @author Costin Leau
Lines 51-61 public class ExtenderConfigurationCustomSettingsTest extends TestCase { Link Here
51
		};
48
		};
52
49
53
		bundleContext = new MockBundleContext(bundle);
50
		bundleContext = new MockBundleContext(bundle);
54
		config = new ExtenderConfiguration(bundleContext, LogFactory.getLog(ExtenderConfiguration.class));
51
		config = new ExtenderConfiguration();
52
        config.start(this.bundleContext);
55
	}
53
	}
56
54
57
	protected void tearDown() throws Exception {
55
	protected void tearDown() throws Exception {
58
		config.destroy();
56
		config.stop(this.bundleContext);
59
		config = null;
57
		config = null;
60
	}
58
	}
61
59
(-)a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationDefaultSettingsTest.java (-13 / +9 lines)
Lines 14-34 Link Here
14
14
15
package org.eclipse.gemini.blueprint.extender.internal.support;
15
package org.eclipse.gemini.blueprint.extender.internal.support;
16
16
17
import java.util.List;
18
19
import junit.framework.TestCase;
17
import junit.framework.TestCase;
20
21
import org.apache.commons.logging.LogFactory;
22
import org.osgi.framework.BundleContext;
23
import org.springframework.core.task.SimpleAsyncTaskExecutor;
24
import org.springframework.core.task.TaskExecutor;
25
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;
18
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;
26
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;
19
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;
27
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
28
import org.eclipse.gemini.blueprint.extender.support.DefaultOsgiApplicationContextCreator;
29
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
20
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
21
import org.osgi.framework.BundleContext;
22
import org.springframework.core.task.SimpleAsyncTaskExecutor;
23
import org.springframework.core.task.TaskExecutor;
30
import org.springframework.scheduling.timer.TimerTaskExecutor;
24
import org.springframework.scheduling.timer.TimerTaskExecutor;
31
25
26
import java.util.List;
27
32
/**
28
/**
33
 * @author Costin Leau
29
 * @author Costin Leau
34
 */
30
 */
Lines 39-49 public class ExtenderConfigurationDefaultSettingsTest extends TestCase { Link Here
39
35
40
	protected void setUp() throws Exception {
36
	protected void setUp() throws Exception {
41
		bundleContext = new MockBundleContext();
37
		bundleContext = new MockBundleContext();
42
		config = new ExtenderConfiguration(bundleContext, LogFactory.getLog(ExtenderConfiguration.class));
38
		config = new ExtenderConfiguration();
39
        this.config.start(this.bundleContext);
43
	}
40
	}
44
41
45
	protected void tearDown() throws Exception {
42
	protected void tearDown() throws Exception {
46
		config.destroy();
43
		config.start(this.bundleContext);
47
		config = null;
44
		config = null;
48
	}
45
	}
49
46
Lines 61-67 public class ExtenderConfigurationDefaultSettingsTest extends TestCase { Link Here
61
	}
58
	}
62
59
63
	public void testApplicationContextCreator() throws Exception {
60
	public void testApplicationContextCreator() throws Exception {
64
		assertTrue(config.getContextCreator() instanceof DefaultOsgiApplicationContextCreator);
61
        assertNull(config.getContextCreator());
65
	}
62
	}
66
63
67
	public void testShutdownWaitTime() throws Exception {
64
	public void testShutdownWaitTime() throws Exception {
68
- 

Return to bug 356683