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

(-)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
}
(-)extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ContextLoaderListener.java (-289 / +51 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 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 244-267 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;
120
    private VersionMatcher versionMatcher;
121
    private Version extenderVersion;
122
123
    /** extender bundle id */
248
	private long bundleId;
124
	private long bundleId;
249
125
250
	/** extender configuration */
251
	private ExtenderConfiguration extenderConfiguration;
252
253
	/** Spring namespace/resolver manager */
254
	private NamespaceManager nsManager;
255
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
131
262
	/** Bundle listener interested in namespace resolvers/parsers discovery */
263
	private SynchronousBundleListener nsListener;
264
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
267
	 */
134
	 */
Lines 272-331 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();
160
        this.extenderVersion = OsgiBundleUtils.getBundleVersion(extenderBundleContext.getBundle());
161
        this.versionMatcher = new DefaultVersionMatcher(getManagedBundleExtenderVersionHeader(), extenderVersion);
162
        this.processor = createContextProcessor();
296
163
297
		this.extenderVersion = OsgiBundleUtils.getBundleVersion(context.getBundle());
298
		log.info("Starting [" + bundleContext.getBundle().getSymbolicName() + "] bundle v.[" + extenderVersion + "]");
299
		versionMatcher = new DefaultVersionMatcher(getManagedBundleExtenderVersionHeader(), extenderVersion);
300
		processor = createContextProcessor();
301
302
		// init cache (to prevent ad-hoc Java Bean discovery on lazy bundles)
303
		initJavaBeansCache();
304
305
		// Step 1 : discover existing namespaces (in case there are fragments with custom XML definitions)
306
		nsManager = new NamespaceManager(context);
307
		initNamespaceHandlers(bundleContext);
308
309
		// Step 2: initialize the extender configuration
310
		extenderConfiguration = initExtenderConfiguration(bundleContext);
311
312
		// init the OSGi event dispatch/listening system
313
		initListenerService();
314
315
		// initialize the configuration once namespace handlers have been detected
164
		// initialize the configuration once namespace handlers have been detected
316
		lifecycleManager =
165
		this.lifecycleManager =
317
				new LifecycleManager(extenderConfiguration, versionMatcher, createContextConfigFactory(),
166
				new LifecycleManager(
318
						this.processor, getTypeCompatibilityChecker(), bundleContext);
167
                        this.extenderConfiguration,
168
                        getVersionMatcher(),
169
                        createContextConfigFactory(),
170
                        getOsgiApplicationContextCreator(),
171
						this.processor,
172
                        getTypeCompatibilityChecker(),
173
                        bundleContext);
319
174
320
		// Step 3: discover the bundles that are started
175
		// Step 3: discover the bundles that are started
321
		// and require context creation
176
		// 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-369 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();
Lines 409-417 Link Here
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) {
Lines 419-507 Link Here
419
			contextListener = null;
239
			contextListener = null;
420
		}
240
		}
421
241
422
		if (nsListener != null) {
423
			bundleContext.removeBundleListener(nsListener);
424
			nsListener = null;
425
		}
426
427
		// close managed bundles
242
		// close managed bundles
428
		lifecycleManager.destroy();
243
		lifecycleManager.destroy();
429
		// clear the namespace registry
244
	}
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
245
441
		extenderConfiguration.destroy();
246
	protected ApplicationContextConfigurationFactory createContextConfigFactory() {
247
		return new DefaultApplicationContextConfigurationFactory();
442
	}
248
	}
443
249
444
	private void initJavaBeansCache() {
250
    public VersionMatcher getVersionMatcher() {
445
		Class<?>[] classes =
251
        return versionMatcher;
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
		}
252
    }
454
	}
455
253
456
	private void destroyJavaBeansCache() {
254
    protected String getManagedBundleExtenderVersionHeader() {
457
		CachedIntrospectionResults.clearClassLoader(OsgiStringUtils.class.getClassLoader());
255
        return ConfigUtils.EXTENDER_VERSION;
458
	}
256
    }
459
257
460
	protected void maybeAddNamespaceHandlerFor(Bundle bundle, boolean isLazy) {
258
    private OsgiApplicationContextCreator getOsgiApplicationContextCreator() {
461
		if (handlerBundleMatchesExtenderVersion(bundle))
259
        OsgiApplicationContextCreator creator = this.extenderConfiguration.getContextCreator();
462
			nsManager.maybeAddNamespaceHandlerFor(bundle, isLazy);
260
        if (creator == null) {
261
            creator = createDefaultOsgiApplicationContextCreator();
463
	}
262
        }
464
263
        return creator;
465
	protected void maybeRemoveNameSpaceHandlerFor(Bundle bundle) {
466
		if (handlerBundleMatchesExtenderVersion(bundle))
467
			nsManager.maybeRemoveNameSpaceHandlerFor(bundle);
468
	}
264
    }
469
265
470
	/**
266
    protected OsgiApplicationContextCreator createDefaultOsgiApplicationContextCreator() {
471
	 * Utility method that does extender range versioning and approapriate
267
        return new DefaultOsgiApplicationContextCreator();
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
	}
486
487
	protected ApplicationContextConfigurationFactory createContextConfigFactory() {
488
		return new DefaultApplicationContextConfigurationFactory();
489
	}
490
491
	protected void initListenerService() {
492
		multicaster = extenderConfiguration.getEventMulticaster();
493
494
		addApplicationListener(multicaster);
495
		multicaster.addApplicationListener(extenderConfiguration.getContextEventListener());
496
497
		if (log.isDebugEnabled())
498
			log.debug("Initialization of OSGi listeners service completed...");
499
	}
500
501
	protected void addApplicationListener(OsgiBundleApplicationContextEventMulticaster multicaster) {
502
		osgiListeners = new ListListenerAdapter(bundleContext);
503
		osgiListeners.afterPropertiesSet();
504
		// register the listener that does the dispatching
505
		multicaster.addApplicationListener(osgiListeners);
506
	}
268
    }
507
}
269
}
(-)extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationCustomSettingsTest.java (-2 / +3 lines)
Lines 51-61 Link Here
51
		};
51
		};
52
52
53
		bundleContext = new MockBundleContext(bundle);
53
		bundleContext = new MockBundleContext(bundle);
54
		config = new ExtenderConfiguration(bundleContext, LogFactory.getLog(ExtenderConfiguration.class));
54
		config = new ExtenderConfiguration();
55
        config.start(this.bundleContext);
55
	}
56
	}
56
57
57
	protected void tearDown() throws Exception {
58
	protected void tearDown() throws Exception {
58
		config.destroy();
59
		config.stop(this.bundleContext);
59
		config = null;
60
		config = null;
60
	}
61
	}
61
62
(-)extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/boot/ChainActivator.java (-8 / +41 lines)
Lines 16-33 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 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[] {
81
                    logStatus,
82
                    activateJavaBeansCache,
83
                    activateCustomNamespaceHandling,
84
                    initializeExtenderConfiguration,
85
                    activateListeners,
86
                    listenForSpringDmBundles
87
            };
55
		}
88
        }
56
	}
89
	}
57
90
58
	public void start(BundleContext context) throws Exception {
91
	public void start(BundleContext context) throws Exception {
(-)extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ListenerServiceActivator.java (+79 lines)
Line 0 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
}
(-)extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationDefaultSettingsTest.java (-3 / +4 lines)
Lines 39-49 Link Here
39
39
40
	protected void setUp() throws Exception {
40
	protected void setUp() throws Exception {
41
		bundleContext = new MockBundleContext();
41
		bundleContext = new MockBundleContext();
42
		config = new ExtenderConfiguration(bundleContext, LogFactory.getLog(ExtenderConfiguration.class));
42
		config = new ExtenderConfiguration();
43
        this.config.start(this.bundleContext);
43
	}
44
	}
44
45
45
	protected void tearDown() throws Exception {
46
	protected void tearDown() throws Exception {
46
		config.destroy();
47
		config.start(this.bundleContext);
47
		config = null;
48
		config = null;
48
	}
49
	}
49
50
Lines 61-67 Link Here
61
	}
62
	}
62
63
63
	public void testApplicationContextCreator() throws Exception {
64
	public void testApplicationContextCreator() throws Exception {
64
		assertTrue(config.getContextCreator() instanceof DefaultOsgiApplicationContextCreator);
65
        assertNull(config.getContextCreator());
65
	}
66
	}
66
67
67
	public void testShutdownWaitTime() throws Exception {
68
	public void testShutdownWaitTime() throws Exception {
(-)extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/BlueprintLoaderListener.java (-34 / +23 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 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;
39
	private volatile BlueprintListenerManager listenerManager;
40
	private volatile Bundle bundle;
35
    private volatile BlueprintContainerProcessor contextProcessor;
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 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 Link Here
73
		};
68
		};
74
	}
69
	}
75
70
76
	@Override
71
    @Override
72
    protected OsgiApplicationContextCreator createDefaultOsgiApplicationContextCreator() {
73
        return new BlueprintContainerCreator();
74
    }
75
76
    @Override
77
	protected OsgiContextProcessor createContextProcessor() {
77
	protected OsgiContextProcessor createContextProcessor() {
78
		return contextProcessor;
78
		return contextProcessor;
79
	}
79
	}
Lines 86-101 Link Here
86
	@Override
86
	@Override
87
	protected String getManagedBundleExtenderVersionHeader() {
87
	protected String getManagedBundleExtenderVersionHeader() {
88
		return BlueprintConfigUtils.EXTENDER_VERSION;
88
		return BlueprintConfigUtils.EXTENDER_VERSION;
89
	}
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
	}
89
	}
101
}
90
}
(-)extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/support/DefaultOsgiBundleApplicationContextListener.java (-2 / +1 lines)
Lines 21-30 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
(-)extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/ContextLoaderListenerTest.java (-4 / +5 lines)
Lines 22-27 Link Here
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;
Lines 40-52 Link Here
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.
46
    private ExtenderConfiguration configuration;
45
47
46
48
    protected void setUp() throws Exception {
47
	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 {
(-)extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LoggingActivator.java (+27 lines)
Line 0 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
}
(-)core/src/test/java/org/eclipse/gemini/blueprint/context/support/ConfigLocationsTest.java (-1 lines)
Lines 44-50 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
(-)extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/listeners/NamespaceBundleLister.java (+59 lines)
Line 0 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
}
(-)extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/JavaBeansCacheActivator.java (+60 lines)
Line 0 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
(-)extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ListListenerAdapter.java (-10 / +5 lines)
Lines 14-33 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;
29
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener;
30
24
25
import java.util.Map;
26
import java.util.WeakHashMap;
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
33
 * dynamic collections which can be updated during iteration.
30
 * dynamic collections which can be updated during iteration.
Lines 45-52 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);
(-)core/src/test/java/org/eclipse/gemini/blueprint/context/internal/classloader/ChainedClassLoaderTest.java (-1 lines)
Lines 96-102 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"));
(-)extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/BlueprintNamespaceHandlerActivator.java (+14 lines)
Line 0 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
}
(-)extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/NamespaceHandlerActivator.java (+115 lines)
Line 0 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
}
(-)extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/listeners/BaseListener.java (+85 lines)
Line 0 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 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
}
(-)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 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 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 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

Return to bug 356683