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 (-128 / +127 lines)
Lines 1-129 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc.
2
 * Copyright (c) 2006, 2010 VMware Inc.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution. 
5
 * and Apache License v2.0 which accompanies this distribution. 
6
 * The Eclipse Public License is available at 
6
 * The Eclipse Public License is available at 
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
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.
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. 
9
 * You may elect to redistribute this code under either of these licenses. 
10
 * 
10
 * 
11
 * Contributors:
11
 * Contributors:
12
 *   VMware Inc.
12
 *   VMware Inc.
13
 *****************************************************************************/
13
 *****************************************************************************/
14
14
15
package org.eclipse.gemini.blueprint.context.internal.classloader;
15
package org.eclipse.gemini.blueprint.context.internal.classloader;
16
16
17
import java.net.URL;
17
import java.net.URL;
18
import java.net.URLClassLoader;
18
import java.net.URLClassLoader;
19
import java.util.List;
19
import java.util.List;
20
20
21
import junit.framework.TestCase;
21
import junit.framework.TestCase;
22
22
23
import org.eclipse.gemini.blueprint.TestUtils;
23
import org.eclipse.gemini.blueprint.TestUtils;
24
import org.eclipse.gemini.blueprint.context.support.internal.classloader.ChainedClassLoader;
24
import org.eclipse.gemini.blueprint.context.support.internal.classloader.ChainedClassLoader;
25
import org.osgi.framework.Bundle;
25
import org.osgi.framework.Bundle;
26
26
27
/**
27
/**
28
 * @author Costin Leau
28
 * @author Costin Leau
29
 */
29
 */
30
public class ChainedClassLoaderTest extends TestCase {
30
public class ChainedClassLoaderTest extends TestCase {
31
31
32
	private ChainedClassLoader chainedLoader;
32
	private ChainedClassLoader chainedLoader;
33
	private ClassLoader emptyCL;
33
	private ClassLoader emptyCL;
34
34
35
35
36
	protected void setUp() throws Exception {
36
	protected void setUp() throws Exception {
37
		emptyCL = new URLClassLoader(new URL[0], null) {
37
		emptyCL = new URLClassLoader(new URL[0], null) {
38
38
39
			public Class<?> loadClass(String name) throws ClassNotFoundException {
39
			public Class<?> loadClass(String name) throws ClassNotFoundException {
40
				throw new ClassNotFoundException(name);
40
				throw new ClassNotFoundException(name);
41
			}
41
			}
42
42
43
			public URL getResource(String name) {
43
			public URL getResource(String name) {
44
				return null;
44
				return null;
45
			}
45
			}
46
		};
46
		};
47
47
48
		chainedLoader = new ChainedClassLoader(new ClassLoader[] { emptyCL }, emptyCL);
48
		chainedLoader = new ChainedClassLoader(new ClassLoader[] { emptyCL }, emptyCL);
49
	}
49
	}
50
50
51
	protected void tearDown() throws Exception {
51
	protected void tearDown() throws Exception {
52
		chainedLoader = null;
52
		chainedLoader = null;
53
		emptyCL = null;
53
		emptyCL = null;
54
	}
54
	}
55
55
56
	public void testChainedClassLoaderClassLoaderArray() throws Exception {
56
	public void testChainedClassLoaderClassLoaderArray() throws Exception {
57
		String className = "java.lang.Object";
57
		String className = "java.lang.Object";
58
		try {
58
		try {
59
			emptyCL.loadClass(className);
59
			emptyCL.loadClass(className);
60
			fail("should not be able to load classes");
60
			fail("should not be able to load classes");
61
		}
61
		}
62
		catch (ClassNotFoundException cnfe) {
62
		catch (ClassNotFoundException cnfe) {
63
			// expected
63
			// expected
64
		}
64
		}
65
65
66
		chainedLoader = new ChainedClassLoader(new ClassLoader[] { emptyCL });
66
		chainedLoader = new ChainedClassLoader(new ClassLoader[] { emptyCL });
67
		chainedLoader.loadClass(className);
67
		chainedLoader.loadClass(className);
68
	}
68
	}
69
69
70
	public void testParentClassLoader() throws Exception {
70
	public void testParentClassLoader() throws Exception {
71
		chainedLoader = new ChainedClassLoader(new ClassLoader[] { emptyCL });
71
		chainedLoader = new ChainedClassLoader(new ClassLoader[] { emptyCL });
72
		ClassLoader parent = chainedLoader.getParent();
72
		ClassLoader parent = chainedLoader.getParent();
73
		assertNotNull(parent);
73
		assertNotNull(parent);
74
		// fragile check (might fail on non SUN VMs)
74
		// fragile check (might fail on non SUN VMs)
75
		assertTrue("does the test run on a SUN VM or is it embedded?", parent.getClass().getName().indexOf("App") >= 0);
75
		assertTrue("does the test run on a SUN VM or is it embedded?", parent.getClass().getName().indexOf("App") >= 0);
76
	}
76
	}
77
77
78
	public void testChainedClassLoaderClassLoaderArrayClassLoader() throws Exception {
78
	public void testChainedClassLoaderClassLoaderArrayClassLoader() throws Exception {
79
		String className = "java.lang.Object";
79
		String className = "java.lang.Object";
80
80
81
		try {
81
		try {
82
			emptyCL.loadClass(className);
82
			emptyCL.loadClass(className);
83
			fail("should not be able to load classes");
83
			fail("should not be able to load classes");
84
		}
84
		}
85
		catch (ClassNotFoundException cnfe) {
85
		catch (ClassNotFoundException cnfe) {
86
			// expected
86
			// expected
87
		}
87
		}
88
88
89
		try {
89
		try {
90
			chainedLoader.loadClass(className);
90
			chainedLoader.loadClass(className);
91
			fail("should not be able to load classes");
91
			fail("should not be able to load classes");
92
		}
92
		}
93
		catch (ClassNotFoundException cnfe) {
93
		catch (ClassNotFoundException cnfe) {
94
			// expected
94
			// expected
95
		}
95
		}
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"));
99
		assertNull(chainedLoader.getResource("java/lang/Object.class"));
100
		assertNull(chainedLoader.getResource("java/lang/Object.class"));
100
		chainedLoader.addClassLoader(Object.class);
101
		chainedLoader.addClassLoader(Object.class);
101
		assertNotNull(chainedLoader.getResource("java/lang/Object.class"));
102
		assertNotNull(chainedLoader.getResource("java/lang/Object.class"));
102
	}
103
	}
103
104
104
	public void testAddClassLoaderClass() throws Exception {
105
	public void testAddClassLoaderClass() throws Exception {
105
		chainedLoader.addClassLoader(Object.class);
106
		chainedLoader.addClassLoader(Object.class);
106
		chainedLoader.loadClass("java.lang.Object");
107
		chainedLoader.loadClass("java.lang.Object");
107
	}
108
	}
108
109
109
	public void testAddClassLoaderClassLoader() throws Exception {
110
	public void testAddClassLoaderClassLoader() throws Exception {
110
		chainedLoader.addClassLoader(Bundle.class.getClassLoader());
111
		chainedLoader.addClassLoader(Bundle.class.getClassLoader());
111
		chainedLoader.loadClass("org.osgi.framework.Bundle");
112
		chainedLoader.loadClass("org.osgi.framework.Bundle");
112
	}
113
	}
113
114
114
	public void testNonOSGiClassLoaderInsertOrder() throws Exception {
115
	public void testNonOSGiClassLoaderInsertOrder() throws Exception {
115
		ClassLoader appLoader = ClassLoader.getSystemClassLoader();
116
		ClassLoader appLoader = ClassLoader.getSystemClassLoader();
116
		ClassLoader extLoader = appLoader.getParent();
117
		ClassLoader extLoader = appLoader.getParent();
117
118
118
		chainedLoader.addClassLoader(extLoader);
119
		chainedLoader.addClassLoader(extLoader);
119
		chainedLoader.addClassLoader(appLoader);
120
		chainedLoader.addClassLoader(appLoader);
120
121
121
		// read the internal array
122
		// read the internal array
122
		List list = (List) TestUtils.getFieldValue(chainedLoader, "nonOsgiLoaders");
123
		List list = (List) TestUtils.getFieldValue(chainedLoader, "nonOsgiLoaders");
123
124
124
		// the loaders should be inserted based on their inheritance
125
		// the loaders should be inserted based on their inheritance
125
		assertSame(appLoader, list.get(0));
126
		assertSame(appLoader, list.get(0));
126
		assertSame(extLoader, list.get(1));
127
		assertSame(extLoader, list.get(1));
127
	}
128
	}
129
}
128
}
(-)a/core/src/test/java/org/eclipse/gemini/blueprint/context/support/ConfigLocationsTest.java (-60 / +59 lines)
Lines 1-60 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc.
2
 * Copyright (c) 2006, 2010 VMware Inc.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution. 
5
 * and Apache License v2.0 which accompanies this distribution. 
6
 * The Eclipse Public License is available at 
6
 * The Eclipse Public License is available at 
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
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.
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. 
9
 * You may elect to redistribute this code under either of these licenses. 
10
 * 
10
 * 
11
 * Contributors:
11
 * Contributors:
12
 *   VMware Inc.
12
 *   VMware Inc.
13
 *****************************************************************************/
13
 *****************************************************************************/
14
14
15
package org.eclipse.gemini.blueprint.context.support;
15
package org.eclipse.gemini.blueprint.context.support;
16
16
17
import java.lang.reflect.Method;
17
import java.lang.reflect.Method;
18
import java.util.Arrays;
18
import java.util.Arrays;
19
19
20
import junit.framework.TestCase;
20
import junit.framework.TestCase;
21
21
22
import org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext;
22
import org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext;
23
23
24
/**
24
/**
25
 * 
25
 * 
26
 * @author Costin Leau
26
 * @author Costin Leau
27
 */
27
 */
28
public class ConfigLocationsTest extends TestCase {
28
public class ConfigLocationsTest extends TestCase {
29
29
30
	private OsgiBundleXmlApplicationContext context;
30
	private OsgiBundleXmlApplicationContext context;
31
31
32
	@Override
32
	@Override
33
	protected void setUp() throws Exception {
33
	protected void setUp() throws Exception {
34
		context = new OsgiBundleXmlApplicationContext();
34
		context = new OsgiBundleXmlApplicationContext();
35
	}
35
	}
36
36
37
	@Override
37
	@Override
38
	protected void tearDown() throws Exception {
38
	protected void tearDown() throws Exception {
39
		context = null;
39
		context = null;
40
	}
40
	}
41
41
42
	public void testExpandConfigFolders() throws Exception {
42
	public void testExpandConfigFolders() throws Exception {
43
		String[] cfgs = new String[] { "cnf/", "/cnf/" };
43
		String[] cfgs = new String[] { "cnf/", "/cnf/" };
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));
47
		assertTrue(Arrays.equals(new String[] { "cnf/*.xml", "/cnf/*.xml" }, returned));
48
		assertTrue(Arrays.equals(new String[] { "cnf/*.xml", "/cnf/*.xml" }, returned));
48
	}
49
	}
49
50
50
	private Object invokeMethod(String name, Class[] types, Object[] args) {
51
	private Object invokeMethod(String name, Class[] types, Object[] args) {
51
		try {
52
		try {
52
			Method mt = context.getClass().getDeclaredMethod(name, types);
53
			Method mt = context.getClass().getDeclaredMethod(name, types);
53
			mt.setAccessible(true);
54
			mt.setAccessible(true);
54
			return mt.invoke(context, args);
55
			return mt.invoke(context, args);
55
		} catch (Exception ex) {
56
		} catch (Exception ex) {
56
			throw new RuntimeException(ex);
57
			throw new RuntimeException(ex);
57
		}
58
		}
58
	}
59
	}
59
}
60
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/BlueprintNamespaceHandlerActivator.java (+28 lines)
Added 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.activator;
16
17
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintConfigUtils;
18
19
/**
20
 * @author Olaf Otto
21
 */
22
public class BlueprintNamespaceHandlerActivator extends NamespaceHandlerActivator {
23
24
    @Override
25
    protected String getManagedBundleExtenderVersionHeader() {
26
        return BlueprintConfigUtils.EXTENDER_VERSION;
27
    }
28
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ContextLoaderListener.java (-491 / +253 lines)
Lines 1-507 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc., Oracle Inc.
2
 * Copyright (c) 2006, 2010 VMware Inc., Oracle Inc.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution. 
5
 * and Apache License v2.0 which accompanies this distribution. 
6
 * The Eclipse Public License is available at 
6
 * The Eclipse Public License is available at 
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
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.
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. 
9
 * You may elect to redistribute this code under either of these licenses. 
10
 * 
10
 * 
11
 * Contributors:
11
 * Contributors:
12
 *   VMware Inc.
12
 *   VMware Inc.
13
 *   Oracle Inc.
13
 *   Oracle Inc.
14
 *****************************************************************************/
14
 *****************************************************************************/
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;
18
import org.apache.commons.logging.Log;
19
import java.util.WeakHashMap;
19
import org.apache.commons.logging.LogFactory;
20
20
import org.eclipse.gemini.blueprint.extender.OsgiApplicationContextCreator;
21
import org.apache.commons.logging.Log;
21
import org.eclipse.gemini.blueprint.extender.internal.activator.listeners.BaseListener;
22
import org.apache.commons.logging.LogFactory;
22
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
23
import org.osgi.framework.Bundle;
23
import org.eclipse.gemini.blueprint.extender.support.DefaultOsgiApplicationContextCreator;
24
import org.osgi.framework.BundleActivator;
24
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
25
import org.osgi.framework.BundleContext;
25
import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
26
import org.osgi.framework.BundleEvent;
26
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
27
import org.osgi.framework.SynchronousBundleListener;
27
import org.osgi.framework.*;
28
import org.osgi.framework.Version;
28
29
import org.springframework.beans.BeanUtils;
29
/**
30
import org.springframework.beans.CachedIntrospectionResults;
30
 * Osgi Extender that bootstraps 'Spring powered bundles'.
31
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;
31
 * 
32
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
32
 * <p/> The class listens to bundle events and manages the creation and destruction of application contexts for bundles
33
import org.eclipse.gemini.blueprint.extender.internal.support.NamespaceManager;
33
 * that have one or both of: <ul> <li>A manifest header entry Spring-Context <li>XML files in META-INF/spring folder
34
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
34
 * </ul>
35
import org.eclipse.gemini.blueprint.service.exporter.support.OsgiServiceFactoryBean;
35
 * 
36
import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceCollectionProxyFactoryBean;
36
 * <p/> The extender also discovers any Spring namespace/schema handlers in resolved bundles and makes them available
37
import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceProxyFactoryBean;
37
 * through a dedicated OSGi service.
38
import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
38
 * 
39
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
39
 * <p/> The extender behaviour can be customized by attaching fragments to the extender bundle. On startup, the extender
40
40
 * will look for <code>META-INF/spring/*.xml</code> files and merge them into an application context. From the resulting
41
/**
41
 * context, the context will look for beans with predefined names to determine its configuration. The current version
42
 * Osgi Extender that bootstraps 'Spring powered bundles'.
42
 * recognises the following bean names:
43
 * 
43
 * 
44
 * <p/> The class listens to bundle events and manages the creation and destruction of application contexts for bundles
44
 * <table border="1"> <tr> <th>Bean Name</th> <th>Bean Type</th> <th>Description</th> </tr> <tr>
45
 * that have one or both of: <ul> <li>A manifest header entry Spring-Context <li>XML files in META-INF/spring folder
45
 * <td><code>taskExecutor</code></td> <td><code>org.springframework.core.task.TaskExecutor</code></td> <td>Task executor
46
 * </ul>
46
 * used for creating the discovered application contexts.</td> </tr> <tr> <td><code>shutdownTaskExecutor</code></td>
47
 * 
47
 * <td><code>org.springframework.core.task.TaskExecutor</code></td> <td>Task executor used for shutting down various
48
 * <p/> The extender also discovers any Spring namespace/schema handlers in resolved bundles and makes them available
48
 * application contexts.</td> </tr> <tr> <td><code>extenderProperties</code></td>
49
 * through a dedicated OSGi service.
49
 * <td><code>java.util.Properties</code></td> <td>Various properties for configuring the extender behaviour (see
50
 * 
50
 * below)</td> </tr> </table>
51
 * <p/> The extender behaviour can be customized by attaching fragments to the extender bundle. On startup, the extender
51
 * 
52
 * will look for <code>META-INF/spring/*.xml</code> files and merge them into an application context. From the resulting
52
 * <p/> <code>extenderProperties</code> recognises the following properties:
53
 * context, the context will look for beans with predefined names to determine its configuration. The current version
53
 * 
54
 * recognises the following bean names:
54
 * <table border="1"> <tr> <th>Name</th> <th>Type</th> <th>Description</th> </tr> <tr>
55
 * 
55
 * <td><code>shutdown.wait.time</code></td> <td>Number</td> <td>The amount of time the extender will wait for each
56
 * <table border="1"> <tr> <th>Bean Name</th> <th>Bean Type</th> <th>Description</th> </tr> <tr>
56
 * application context to shutdown gracefully. Expressed in milliseconds.</td> </tr> <tr>
57
 * <td><code>taskExecutor</code></td> <td><code>org.springframework.core.task.TaskExecutor</code></td> <td>Task executor
57
 * <td><code>process.annotations</code></td> <td>Boolean</td> <td>Whether or not, the extender will process SpringOSGi
58
 * used for creating the discovered application contexts.</td> </tr> <tr> <td><code>shutdownTaskExecutor</code></td>
58
 * annotations.</td> </tr> </table>
59
 * <td><code>org.springframework.core.task.TaskExecutor</code></td> <td>Task executor used for shutting down various
59
 * 
60
 * application contexts.</td> </tr> <tr> <td><code>extenderProperties</code></td>
60
 * <p/> Note: The extender configuration context is created during the bundle activation (a synchronous OSGi lifecycle
61
 * <td><code>java.util.Properties</code></td> <td>Various properties for configuring the extender behaviour (see
61
 * callback) and should contain only simple bean definitions that will not delay context initialisation. </p>
62
 * below)</td> </tr> </table>
62
 * 
63
 * 
63
 * @author Bill Gallagher
64
 * <p/> <code>extenderProperties</code> recognises the following properties:
64
 * @author Andy Piper
65
 * 
65
 * @author Hal Hildebrand
66
 * <table border="1"> <tr> <th>Name</th> <th>Type</th> <th>Description</th> </tr> <tr>
66
 * @author Adrian Colyer
67
 * <td><code>shutdown.wait.time</code></td> <td>Number</td> <td>The amount of time the extender will wait for each
67
 * @author Costin Leau
68
 * application context to shutdown gracefully. Expressed in milliseconds.</td> </tr> <tr>
68
 */
69
 * <td><code>process.annotations</code></td> <td>Boolean</td> <td>Whether or not, the extender will process SpringOSGi
69
public class ContextLoaderListener implements BundleActivator {
70
 * annotations.</td> </tr> </table>
70
71
 * 
71
    /**
72
 * <p/> Note: The extender configuration context is created during the bundle activation (a synchronous OSGi lifecycle
72
	 * Bundle listener used for context creation/destruction.
73
 * callback) and should contain only simple bean definitions that will not delay context initialisation. </p>
73
	 */
74
 * 
74
	private class ContextBundleListener extends BaseListener {
75
 * @author Bill Gallagher
75
76
 * @author Andy Piper
76
		protected void handleEvent(BundleEvent event) {
77
 * @author Hal Hildebrand
77
78
 * @author Adrian Colyer
78
			Bundle bundle = event.getBundle();
79
 * @author Costin Leau
79
80
 */
81
public class ContextLoaderListener implements BundleActivator {
82
83
	/**
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.
201
	 */
202
	private class ContextBundleListener extends BaseListener {
203
204
		protected void handleEvent(BundleEvent event) {
205
206
			Bundle bundle = event.getBundle();
207
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) {
219
				}
91
				}
220
				break;
92
				break;
221
			}
93
			}
222
			case BundleEvent.STARTED: {
94
			case BundleEvent.STARTED: {
223
				lifecycleManager.maybeCreateApplicationContextFor(bundle);
95
				lifecycleManager.maybeCreateApplicationContextFor(bundle);
224
				break;
96
				break;
225
			}
97
			}
226
			case BundleEvent.STOPPING: {
98
			case BundleEvent.STOPPING: {
227
				if (OsgiBundleUtils.isSystemBundle(bundle)) {
99
				if (OsgiBundleUtils.isSystemBundle(bundle)) {
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);
236
				}
108
				}
237
				break;
109
				break;
238
			}
110
			}
239
			default:
111
			default:
240
				break;
112
				break;
241
			}
113
			}
242
		}
114
		}
243
	}
115
	}
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 */
122
251
	private ExtenderConfiguration extenderConfiguration;
123
    /** extender bundle id */
252
124
	private long bundleId;
253
	/** Spring namespace/resolver manager */
125
254
	private NamespaceManager nsManager;
126
	/** The bundle's context */
255
127
	private BundleContext bundleContext;
256
	/** The bundle's context */
128
257
	private BundleContext bundleContext;
129
	/** Bundle listener interested in context creation */
258
130
	private BaseListener contextListener;
259
	/** Bundle listener interested in context creation */
131
260
	private SynchronousBundleListener contextListener;
132
	/**
261
133
	 * Monitor used for dealing with the bundle activator and synchronous bundle threads
262
	/** Bundle listener interested in namespace resolvers/parsers discovery */
134
	 */
263
	private SynchronousBundleListener nsListener;
135
	private final Object monitor = new Object();
264
136
265
	/**
137
	/**
266
	 * Monitor used for dealing with the bundle activator and synchronous bundle threads
138
	 * flag indicating whether the context is down or not - useful during shutdown
267
	 */
139
	 */
268
	private final Object monitor = new Object();
140
	private volatile boolean isClosed = false;
269
141
270
	/**
142
	private volatile LifecycleManager lifecycleManager;
271
	 * flag indicating whether the context is down or not - useful during shutdown
143
	private volatile OsgiContextProcessor processor;
272
	 */
144
273
	private volatile boolean isClosed = false;
145
    public ContextLoaderListener(ExtenderConfiguration extenderConfiguration) {
274
146
        this.extenderConfiguration = extenderConfiguration;
275
	/** This extender version */
147
    }
276
	private Version extenderVersion;
148
277
149
    /**
278
	private volatile OsgiBundleApplicationContextEventMulticaster multicaster;
150
	 * <p/> Called by OSGi when this bundle is started. Finds all previously resolved bundles and adds namespace
279
151
	 * handlers for them if necessary. </p> <p/> Creates application contexts for bundles started before the extender
280
	private volatile LifecycleManager lifecycleManager;
152
	 * was started. </p> <p/> Registers a namespace/entity resolving service for use by web app contexts. </p>
281
	private volatile VersionMatcher versionMatcher;
153
	 * 
282
	private volatile OsgiContextProcessor processor;
154
	 * @see org.osgi.framework.BundleActivator#start
283
	private volatile ListListenerAdapter osgiListeners;
155
	 */
284
156
	public void start(BundleContext extenderBundleContext) throws Exception {
285
	/**
157
286
	 * <p/> Called by OSGi when this bundle is started. Finds all previously resolved bundles and adds namespace
158
		this.bundleContext = extenderBundleContext;
287
	 * handlers for them if necessary. </p> <p/> Creates application contexts for bundles started before the extender
159
		this.bundleId = extenderBundleContext.getBundle().getBundleId();
288
	 * was started. </p> <p/> Registers a namespace/entity resolving service for use by web app contexts. </p>
160
        this.extenderVersion = OsgiBundleUtils.getBundleVersion(extenderBundleContext.getBundle());
289
	 * 
161
        this.versionMatcher = new DefaultVersionMatcher(getManagedBundleExtenderVersionHeader(), extenderVersion);
290
	 * @see org.osgi.framework.BundleActivator#start
162
        this.processor = createContextProcessor();
291
	 */
163
292
	public void start(BundleContext context) throws Exception {
293
294
		this.bundleContext = context;
295
		this.bundleId = context.getBundle().getBundleId();
296
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,
319
168
                        getVersionMatcher(),
169
                        createContextConfigFactory(),
170
                        getOsgiApplicationContextCreator(),
171
						this.processor,
172
                        getTypeCompatibilityChecker(),
173
                        bundleContext);
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) {
180
	protected OsgiContextProcessor createContextProcessor() {
326
		return new ExtenderConfiguration(bundleContext, log);
181
		return new NoOpOsgiContextProcessor();
327
	}
182
	}
328
183
329
	protected OsgiContextProcessor createContextProcessor() {
184
	protected TypeCompatibilityChecker getTypeCompatibilityChecker() {
330
		return new NoOpOsgiContextProcessor();
185
		return null;
331
	}
186
	}
332
187
333
	protected TypeCompatibilityChecker getTypeCompatibilityChecker() {
188
	protected void initStartedBundles(BundleContext bundleContext) {
334
		return null;
335
	}
336
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) {
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 {
380
					lifecycleManager.maybeCreateApplicationContextFor(previousBundles[i]);
201
					lifecycleManager.maybeCreateApplicationContextFor(previousBundles[i]);
381
				} catch (Throwable e) {
202
				} catch (Throwable e) {
382
					log.warn("Cannot start bundle " + OsgiStringUtils.nullSafeSymbolicName(previousBundles[i])
203
					log.warn("Cannot start bundle " + OsgiStringUtils.nullSafeSymbolicName(previousBundles[i])
383
							+ " due to", e);
204
							+ " due to", e);
384
				}
205
				}
385
			}
206
			}
386
		}
207
		}
387
	}
208
	}
388
209
389
	/**
210
	/**
390
	 * Called by OSGi when this bundled is stopped. Unregister the namespace/entity resolving service and clear all
211
	 * Called by OSGi when this bundled is stopped. Unregister the namespace/entity resolving service and clear all
391
	 * state. No further management of application contexts created by this extender prior to stopping the bundle occurs
212
	 * state. No further management of application contexts created by this extender prior to stopping the bundle occurs
392
	 * after this point (even if the extender bundle is subsequently restarted).
213
	 * after this point (even if the extender bundle is subsequently restarted).
393
	 * 
214
	 * 
394
	 * @see org.osgi.framework.BundleActivator#stop
215
	 * @see org.osgi.framework.BundleActivator#stop
395
	 */
216
	 */
396
	public void stop(BundleContext context) throws Exception {
217
	public void stop(BundleContext context) throws Exception {
397
		shutdown();
218
		shutdown();
398
	}
219
	}
399
220
400
	/**
221
	/**
401
	 * Shutdown the extender and all bundled managed by it. Shutdown of contexts is in the topological order of the
222
	 * Shutdown the extender and all bundled managed by it. Shutdown of contexts is in the topological order of the
402
	 * dependency graph formed by the service references.
223
	 * dependency graph formed by the service references.
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 + "]");
233
413
234
        this.contextListener.close();
414
		destroyJavaBeansCache();
235
415
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) {
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();
245
431
246
	protected ApplicationContextConfigurationFactory createContextConfigFactory() {
432
		// release multicaster
247
		return new DefaultApplicationContextConfigurationFactory();
433
		if (multicaster != null) {
248
	}
434
			multicaster.removeAllListeners();
249
435
			multicaster = null;
250
    public VersionMatcher getVersionMatcher() {
436
		}
251
        return versionMatcher;
437
		// release listeners
252
    }
438
		osgiListeners.destroy();
253
439
		osgiListeners = null;
254
    protected String getManagedBundleExtenderVersionHeader() {
440
255
        return ConfigUtils.EXTENDER_VERSION;
441
		extenderConfiguration.destroy();
256
    }
442
	}
257
443
258
    protected OsgiApplicationContextCreator getOsgiApplicationContextCreator() {
444
	private void initJavaBeansCache() {
259
        OsgiApplicationContextCreator creator = this.extenderConfiguration.getContextCreator();
445
		Class<?>[] classes =
260
        if (creator == null) {
446
				new Class<?>[] { OsgiServiceFactoryBean.class, OsgiServiceProxyFactoryBean.class,
261
            creator = createDefaultOsgiApplicationContextCreator();
447
						OsgiServiceCollectionProxyFactoryBean.class };
262
        }
448
263
        return creator;
449
		CachedIntrospectionResults.acceptClassLoader(OsgiStringUtils.class.getClassLoader());
264
    }
450
265
451
		for (Class<?> clazz : classes) {
266
    protected OsgiApplicationContextCreator createDefaultOsgiApplicationContextCreator() {
452
			BeanUtils.getPropertyDescriptors(clazz);
267
        return new DefaultOsgiApplicationContextCreator();
453
		}
268
    }
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
	}
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
	}
507
}
269
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/JavaBeansCacheActivator.java (+74 lines)
Added 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.activator;
16
17
import org.eclipse.gemini.blueprint.service.exporter.support.OsgiServiceFactoryBean;
18
import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceCollectionProxyFactoryBean;
19
import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceProxyFactoryBean;
20
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
21
import org.osgi.framework.BundleActivator;
22
import org.osgi.framework.BundleContext;
23
import org.springframework.beans.BeanUtils;
24
import org.springframework.beans.CachedIntrospectionResults;
25
26
/**
27
 * Used to prevent ad-hoc Java Bean discovery on lazy bundles.
28
 *
29
 * @author Bill Gallagher
30
 * @author Andy Piper
31
 * @author Hal Hildebrand
32
 * @author Adrian Colyer
33
 * @author Costin Leau
34
 * @author Olaf Otto
35
 */
36
public class JavaBeansCacheActivator implements BundleActivator {
37
    /**
38
     * Monitor used for dealing with the bundle activator and synchronous bundle threads
39
     */
40
    private final Object monitor = new Object();
41
    private boolean stopped = false;
42
43
    public void start(BundleContext extenderBundleContext) {
44
        initJavaBeansCache();
45
    }
46
47
    public void stop(BundleContext extenderBundleContext) {
48
        synchronized (monitor) {
49
            if (stopped) {
50
                return;
51
            }
52
            stopped = true;
53
        }
54
        destroyJavaBeansCache();
55
    }
56
57
    private void initJavaBeansCache() {
58
        Class<?>[] classes =
59
                new Class<?>[] { OsgiServiceFactoryBean.class, OsgiServiceProxyFactoryBean.class,
60
                        OsgiServiceCollectionProxyFactoryBean.class };
61
62
        CachedIntrospectionResults.acceptClassLoader(OsgiStringUtils.class.getClassLoader());
63
64
        for (Class<?> clazz : classes) {
65
            BeanUtils.getPropertyDescriptors(clazz);
66
        }
67
    }
68
69
    private void destroyJavaBeansCache() {
70
        CachedIntrospectionResults.clearClassLoader(OsgiStringUtils.class.getClassLoader());
71
    }
72
}
73
74
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java (-435 / +429 lines)
Lines 1-436 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc.
2
 * Copyright (c) 2006, 2010 VMware Inc.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution. 
5
 * and Apache License v2.0 which accompanies this distribution. 
6
 * The Eclipse Public License is available at 
6
 * The Eclipse Public License is available at 
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
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.
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. 
9
 * You may elect to redistribute this code under either of these licenses. 
10
 * 
10
 * 
11
 * Contributors:
11
 * Contributors:
12
 *   VMware Inc.
12
 *   VMware Inc.
13
 *****************************************************************************/
13
 *****************************************************************************/
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;
17
import org.apache.commons.logging.Log;
18
import java.util.Collection;
18
import org.apache.commons.logging.LogFactory;
19
import java.util.Collections;
19
import org.eclipse.gemini.blueprint.context.ConfigurableOsgiBundleApplicationContext;
20
import java.util.List;
20
import org.eclipse.gemini.blueprint.context.DelegatedExecutionOsgiBundleApplicationContext;
21
import java.util.Map;
21
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;
22
import java.util.Timer;
22
import org.eclipse.gemini.blueprint.extender.OsgiApplicationContextCreator;
23
import java.util.concurrent.ConcurrentHashMap;
23
import org.eclipse.gemini.blueprint.extender.OsgiBeanFactoryPostProcessor;
24
24
import org.eclipse.gemini.blueprint.extender.internal.dependencies.shutdown.ShutdownSorter;
25
import org.apache.commons.logging.Log;
25
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor;
26
import org.apache.commons.logging.LogFactory;
26
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
27
import org.eclipse.gemini.blueprint.context.ConfigurableOsgiBundleApplicationContext;
27
import org.eclipse.gemini.blueprint.extender.internal.support.OsgiBeanFactoryPostProcessorAdapter;
28
import org.eclipse.gemini.blueprint.context.DelegatedExecutionOsgiBundleApplicationContext;
28
import org.eclipse.gemini.blueprint.extender.internal.util.concurrent.Counter;
29
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;
29
import org.eclipse.gemini.blueprint.extender.internal.util.concurrent.RunnableTimedExecution;
30
import org.eclipse.gemini.blueprint.extender.OsgiApplicationContextCreator;
30
import org.eclipse.gemini.blueprint.extender.support.ApplicationContextConfiguration;
31
import org.eclipse.gemini.blueprint.extender.OsgiBeanFactoryPostProcessor;
31
import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
32
import org.eclipse.gemini.blueprint.extender.internal.dependencies.shutdown.ShutdownSorter;
32
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
33
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor;
33
import org.osgi.framework.Bundle;
34
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
34
import org.osgi.framework.BundleContext;
35
import org.eclipse.gemini.blueprint.extender.internal.support.OsgiBeanFactoryPostProcessorAdapter;
35
import org.springframework.beans.factory.DisposableBean;
36
import org.eclipse.gemini.blueprint.extender.internal.util.concurrent.Counter;
36
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
37
import org.eclipse.gemini.blueprint.extender.internal.util.concurrent.RunnableTimedExecution;
37
import org.springframework.core.task.SyncTaskExecutor;
38
import org.eclipse.gemini.blueprint.extender.support.ApplicationContextConfiguration;
38
import org.springframework.core.task.TaskExecutor;
39
import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
39
40
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
40
import java.util.*;
41
import org.osgi.framework.Bundle;
41
import java.util.concurrent.ConcurrentHashMap;
42
import org.osgi.framework.BundleContext;
42
43
import org.springframework.beans.factory.DisposableBean;
43
/**
44
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
44
 * Manager handling the startup/shutdown threading issues regarding OSGi contexts. Used by {@link ContextLoaderListener}
45
import org.springframework.core.task.SyncTaskExecutor;
45
 * .
46
import org.springframework.core.task.TaskExecutor;
46
 * 
47
47
 * @author Costin Leau
48
/**
48
 */
49
 * Manager handling the startup/shutdown threading issues regarding OSGi contexts. Used by {@link ContextLoaderListener}
49
class LifecycleManager implements DisposableBean {
50
 * .
50
51
 * 
51
	/** logger */
52
 * @author Costin Leau
52
	private static final Log log = LogFactory.getLog(LifecycleManager.class);
53
 */
53
54
class LifecycleManager implements DisposableBean {
54
	/**
55
55
	 * The contexts we are currently managing. Keys are bundle ids, values are ServiceDependentOsgiApplicationContexts
56
	/** logger */
56
	 * for the application context
57
	private static final Log log = LogFactory.getLog(LifecycleManager.class);
57
	 */
58
58
	private final Map<Long, ConfigurableOsgiBundleApplicationContext> managedContexts =
59
	/**
59
			new ConcurrentHashMap<Long, ConfigurableOsgiBundleApplicationContext>(16);
60
	 * The contexts we are currently managing. Keys are bundle ids, values are ServiceDependentOsgiApplicationContexts
60
61
	 * for the application context
61
	/** listener counter - used to properly synchronize shutdown */
62
	 */
62
	private Counter contextsStarted = new Counter("contextsStarted");
63
	private final Map<Long, ConfigurableOsgiBundleApplicationContext> managedContexts =
63
64
			new ConcurrentHashMap<Long, ConfigurableOsgiBundleApplicationContext>(16);
64
	// "Spring Application Context Creation Timer"
65
65
	private final Timer timer = new Timer("Spring DM Context Creation Timer", true);
66
	/** listener counter - used to properly synchronize shutdown */
66
67
	private Counter contextsStarted = new Counter("contextsStarted");
67
	/** Task executor used for bootstraping the Spring contexts in async mode */
68
68
	private final TaskExecutor taskExecutor;
69
	// "Spring Application Context Creation Timer"
69
70
	private final Timer timer = new Timer("Spring DM Context Creation Timer", true);
70
	/** ApplicationContext Creator */
71
71
	private final OsgiApplicationContextCreator contextCreator;
72
	/** Task executor used for bootstraping the Spring contexts in async mode */
72
73
	private final TaskExecutor taskExecutor;
73
	/** BFPP list */
74
74
	private final List<OsgiBeanFactoryPostProcessor> postProcessors;
75
	/** ApplicationContext Creator */
75
76
	private final OsgiApplicationContextCreator contextCreator;
76
	/** shutdown task executor */
77
77
	private final TaskExecutor shutdownTaskExecutor;
78
	/** BFPP list */
78
79
	private final List<OsgiBeanFactoryPostProcessor> postProcessors;
79
	/**
80
80
	 * Task executor which uses the same thread for running tasks. Used when doing a synchronous wait-for-dependencies.
81
	/** shutdown task executor */
81
	 */
82
	private final TaskExecutor shutdownTaskExecutor;
82
	private final TaskExecutor sameThreadTaskExecutor = new SyncTaskExecutor();
83
83
84
	/**
84
	private final OsgiBundleApplicationContextEventMulticaster multicaster;
85
	 * Task executor which uses the same thread for running tasks. Used when doing a synchronous wait-for-dependencies.
85
86
	 */
86
	private final ExtenderConfiguration extenderConfiguration;
87
	private final TaskExecutor sameThreadTaskExecutor = new SyncTaskExecutor();
87
88
88
	private final BundleContext bundleContext;
89
	private final OsgiBundleApplicationContextEventMulticaster multicaster;
89
90
90
	private final OsgiContextProcessor processor;
91
	private final ExtenderConfiguration extenderConfiguration;
91
92
92
	private final ApplicationContextConfigurationFactory contextConfigurationFactory;
93
	private final BundleContext bundleContext;
93
94
94
	private final VersionMatcher versionMatcher;
95
	private final OsgiContextProcessor processor;
95
	private final TypeCompatibilityChecker typeChecker;
96
96
97
	private final ApplicationContextConfigurationFactory contextConfigurationFactory;
97
	LifecycleManager(ExtenderConfiguration extenderConfiguration, VersionMatcher versionMatcher,
98
98
                     ApplicationContextConfigurationFactory appCtxCfgFactory, OsgiApplicationContextCreator osgiApplicationContextCreator, OsgiContextProcessor processor,
99
	private final VersionMatcher versionMatcher;
99
                     TypeCompatibilityChecker checker, BundleContext context) {
100
	private final TypeCompatibilityChecker typeChecker;
100
101
101
		this.versionMatcher = versionMatcher;
102
	LifecycleManager(ExtenderConfiguration extenderConfiguration, VersionMatcher versionMatcher,
102
		this.extenderConfiguration = extenderConfiguration;
103
			ApplicationContextConfigurationFactory appCtxCfgFactory, OsgiContextProcessor processor,
103
		this.contextConfigurationFactory = appCtxCfgFactory;
104
			TypeCompatibilityChecker checker, BundleContext context) {
104
        this.contextCreator = osgiApplicationContextCreator;
105
105
		this.processor = processor;
106
		this.versionMatcher = versionMatcher;
106
107
		this.extenderConfiguration = extenderConfiguration;
107
		this.taskExecutor = extenderConfiguration.getTaskExecutor();
108
		this.contextConfigurationFactory = appCtxCfgFactory;
108
		this.shutdownTaskExecutor = extenderConfiguration.getShutdownTaskExecutor();
109
109
110
		this.processor = processor;
110
		this.multicaster = extenderConfiguration.getEventMulticaster();
111
111
112
		this.taskExecutor = extenderConfiguration.getTaskExecutor();
112
		this.postProcessors = extenderConfiguration.getPostProcessors();
113
		this.shutdownTaskExecutor = extenderConfiguration.getShutdownTaskExecutor();
113
		this.typeChecker = checker;
114
114
115
		this.multicaster = extenderConfiguration.getEventMulticaster();
115
		this.bundleContext = context;
116
116
	}
117
		this.contextCreator = extenderConfiguration.getContextCreator();
117
118
		this.postProcessors = extenderConfiguration.getPostProcessors();
118
	/**
119
		this.typeChecker = checker;
119
	 * Context creation is a potentially long-running activity (certainly more than we want to do on the synchronous
120
120
	 * event callback).
121
		this.bundleContext = context;
121
	 * 
122
	}
122
	 * <p/> Based on our configuration, the context can be started on the same thread or on a different one.
123
123
	 * 
124
	/**
124
	 * <p/> Kick off a background activity to create an application context for the given bundle if needed.
125
	 * Context creation is a potentially long-running activity (certainly more than we want to do on the synchronous
125
	 * 
126
	 * event callback).
126
	 * <b>Note:</b> Make sure to do the fastest filtering first to avoid slow-downs on platforms with a big number of
127
	 * 
127
	 * plugins and wiring (i.e. Eclipse platform).
128
	 * <p/> Based on our configuration, the context can be started on the same thread or on a different one.
128
	 * 
129
	 * 
129
	 * @param bundle
130
	 * <p/> Kick off a background activity to create an application context for the given bundle if needed.
130
	 */
131
	 * 
131
	protected void maybeCreateApplicationContextFor(Bundle bundle) {
132
	 * <b>Note:</b> Make sure to do the fastest filtering first to avoid slow-downs on platforms with a big number of
132
133
	 * plugins and wiring (i.e. Eclipse platform).
133
		boolean debug = log.isDebugEnabled();
134
	 * 
134
		String bundleString = "[" + OsgiStringUtils.nullSafeNameAndSymName(bundle) + "]";
135
	 * @param bundle
135
136
	 */
136
		final Long bundleId = new Long(bundle.getBundleId());
137
	protected void maybeCreateApplicationContextFor(Bundle bundle) {
137
138
138
		if (managedContexts.containsKey(bundleId)) {
139
		boolean debug = log.isDebugEnabled();
139
			if (debug) {
140
		String bundleString = "[" + OsgiStringUtils.nullSafeNameAndSymName(bundle) + "]";
140
				log.debug("Bundle " + bundleString + " is already managed; ignoring...");
141
141
			}
142
		final Long bundleId = new Long(bundle.getBundleId());
142
			return;
143
143
		}
144
		if (managedContexts.containsKey(bundleId)) {
144
145
			if (debug) {
145
		if (!versionMatcher.matchVersion(bundle)) {
146
				log.debug("Bundle " + bundleString + " is already managed; ignoring...");
146
			return;
147
			}
147
		}
148
			return;
148
149
		}
149
		BundleContext localBundleContext = OsgiBundleUtils.getBundleContext(bundle);
150
150
151
		if (!versionMatcher.matchVersion(bundle)) {
151
		// initialize context
152
			return;
152
		final DelegatedExecutionOsgiBundleApplicationContext localApplicationContext;
153
		}
153
154
154
		if (debug)
155
		BundleContext localBundleContext = OsgiBundleUtils.getBundleContext(bundle);
155
			log.debug("Inspecting bundle " + bundleString);
156
156
157
		// initialize context
157
		try {
158
		final DelegatedExecutionOsgiBundleApplicationContext localApplicationContext;
158
			localApplicationContext = contextCreator.createApplicationContext(localBundleContext);
159
159
		} catch (Exception ex) {
160
		if (debug)
160
			log.error("Cannot create application context for bundle " + bundleString, ex);
161
			log.debug("Inspecting bundle " + bundleString);
161
			return;
162
162
		}
163
		try {
163
164
			localApplicationContext = contextCreator.createApplicationContext(localBundleContext);
164
		if (localApplicationContext == null) {
165
		} catch (Exception ex) {
165
			log.debug("No application context created for bundle " + bundleString);
166
			log.error("Cannot create application context for bundle " + bundleString, ex);
166
			return;
167
			return;
167
		}
168
		}
168
169
169
		if (typeChecker != null) {
170
		if (localApplicationContext == null) {
170
			if (!typeChecker.isTypeCompatible(localBundleContext)) {
171
			log.debug("No application context created for bundle " + bundleString);
171
				log.info("Bundle " + OsgiStringUtils.nullSafeName(bundle) + " is not type compatible with extender "
172
			return;
172
						+ OsgiStringUtils.nullSafeName(bundleContext.getBundle()) + "; ignoring bundle...");
173
		}
173
				return;
174
174
			}
175
		if (typeChecker != null) {
175
		}
176
			if (!typeChecker.isTypeCompatible(localBundleContext)) {
176
177
				log.info("Bundle " + OsgiStringUtils.nullSafeName(bundle) + " is not type compatible with extender "
177
		log.debug("Bundle " + OsgiStringUtils.nullSafeName(bundle) + " is type compatible with extender "
178
						+ OsgiStringUtils.nullSafeName(bundleContext.getBundle()) + "; ignoring bundle...");
178
				+ OsgiStringUtils.nullSafeName(bundleContext.getBundle()) + "; processing bundle...");
179
				return;
179
180
			}
180
		// create a dedicated hook for this application context
181
		}
181
		BeanFactoryPostProcessor processingHook =
182
182
				new OsgiBeanFactoryPostProcessorAdapter(localBundleContext, postProcessors);
183
		log.debug("Bundle " + OsgiStringUtils.nullSafeName(bundle) + " is type compatible with extender "
183
184
				+ OsgiStringUtils.nullSafeName(bundleContext.getBundle()) + "; processing bundle...");
184
		// add in the post processors
185
185
		localApplicationContext.addBeanFactoryPostProcessor(processingHook);
186
		// create a dedicated hook for this application context
186
187
		BeanFactoryPostProcessor processingHook =
187
		// add the context to the tracker
188
				new OsgiBeanFactoryPostProcessorAdapter(localBundleContext, postProcessors);
188
		managedContexts.put(bundleId, localApplicationContext);
189
189
190
		// add in the post processors
190
		localApplicationContext.setDelegatedEventMulticaster(multicaster);
191
		localApplicationContext.addBeanFactoryPostProcessor(processingHook);
191
192
192
		ApplicationContextConfiguration config = contextConfigurationFactory.createConfiguration(bundle);
193
		// add the context to the tracker
193
194
		managedContexts.put(bundleId, localApplicationContext);
194
		final boolean asynch = config.isCreateAsynchronously();
195
195
196
		localApplicationContext.setDelegatedEventMulticaster(multicaster);
196
		// create refresh runnable
197
197
		Runnable contextRefresh = new Runnable() {
198
		ApplicationContextConfiguration config = contextConfigurationFactory.createConfiguration(bundle);
198
199
199
			public void run() {
200
		final boolean asynch = config.isCreateAsynchronously();
200
				// post refresh events are caught through events
201
201
				if (log.isTraceEnabled()) {
202
		// create refresh runnable
202
					log.trace("Calling pre-refresh on processor " + processor);
203
		Runnable contextRefresh = new Runnable() {
203
				}
204
204
				processor.preProcessRefresh(localApplicationContext);
205
			public void run() {
205
				localApplicationContext.refresh();
206
				// post refresh events are caught through events
206
			}
207
				if (log.isTraceEnabled()) {
207
		};
208
					log.trace("Calling pre-refresh on processor " + processor);
208
209
				}
209
		// executor used for creating the appCtx
210
				processor.preProcessRefresh(localApplicationContext);
210
		// chosen based on the sync/async configuration
211
				localApplicationContext.refresh();
211
		TaskExecutor executor = null;
212
			}
212
213
		};
213
		String creationType;
214
214
215
		// executor used for creating the appCtx
215
		// synch/asynch context creation
216
		// chosen based on the sync/async configuration
216
		if (asynch) {
217
		TaskExecutor executor = null;
217
			// for the async stuff use the executor
218
218
			executor = taskExecutor;
219
		String creationType;
219
			creationType = "Asynchronous";
220
220
		} else {
221
		// synch/asynch context creation
221
			// for the sync stuff, use this thread
222
		if (asynch) {
222
			executor = sameThreadTaskExecutor;
223
			// for the async stuff use the executor
223
			creationType = "Synchronous";
224
			executor = taskExecutor;
224
		}
225
			creationType = "Asynchronous";
225
226
		} else {
226
		if (debug) {
227
			// for the sync stuff, use this thread
227
			log.debug(creationType + " context creation for bundle " + bundleString);
228
			executor = sameThreadTaskExecutor;
228
		}
229
			creationType = "Synchronous";
229
230
		}
230
		// wait/no wait for dependencies behaviour
231
231
		if (config.isWaitForDependencies()) {
232
		if (debug) {
232
			DependencyWaiterApplicationContextExecutor appCtxExecutor =
233
			log.debug(creationType + " context creation for bundle " + bundleString);
233
					new DependencyWaiterApplicationContextExecutor(localApplicationContext, !asynch,
234
		}
234
							extenderConfiguration.getDependencyFactories());
235
235
236
		// wait/no wait for dependencies behaviour
236
			long timeout;
237
		if (config.isWaitForDependencies()) {
237
			// check whether a timeout has been defined
238
			DependencyWaiterApplicationContextExecutor appCtxExecutor =
238
239
					new DependencyWaiterApplicationContextExecutor(localApplicationContext, !asynch,
239
			if (config.isTimeoutDeclared()) {
240
							extenderConfiguration.getDependencyFactories());
240
				timeout = config.getTimeout();
241
241
				if (debug)
242
			long timeout;
242
					log.debug("Setting bundle-defined, wait-for-dependencies/graceperiod timeout value=" + timeout
243
			// check whether a timeout has been defined
243
							+ " ms, for bundle " + bundleString);
244
244
245
			if (config.isTimeoutDeclared()) {
245
			} else {
246
				timeout = config.getTimeout();
246
				timeout = extenderConfiguration.getDependencyWaitTime();
247
				if (debug)
247
				if (debug)
248
					log.debug("Setting bundle-defined, wait-for-dependencies/graceperiod timeout value=" + timeout
248
					log.debug("Setting globally defined wait-for-dependencies/graceperiod timeout value=" + timeout
249
							+ " ms, for bundle " + bundleString);
249
							+ " ms, for bundle " + bundleString);
250
250
			}
251
			} else {
251
252
				timeout = extenderConfiguration.getDependencyWaitTime();
252
			appCtxExecutor.setTimeout(timeout);
253
				if (debug)
253
			appCtxExecutor.setWatchdog(timer);
254
					log.debug("Setting globally defined wait-for-dependencies/graceperiod timeout value=" + timeout
254
			appCtxExecutor.setTaskExecutor(executor);
255
							+ " ms, for bundle " + bundleString);
255
			appCtxExecutor.setMonitoringCounter(contextsStarted);
256
			}
256
			// set events publisher
257
257
			appCtxExecutor.setDelegatedMulticaster(this.multicaster);
258
			appCtxExecutor.setTimeout(timeout);
258
259
			appCtxExecutor.setWatchdog(timer);
259
			contextsStarted.increment();
260
			appCtxExecutor.setTaskExecutor(executor);
260
		} else {
261
			appCtxExecutor.setMonitoringCounter(contextsStarted);
261
			// do nothing; by default contexts do not wait for services.
262
			// set events publisher
262
		}
263
			appCtxExecutor.setDelegatedMulticaster(this.multicaster);
263
264
264
		executor.execute(contextRefresh);
265
			contextsStarted.increment();
265
	}
266
		} else {
266
267
			// do nothing; by default contexts do not wait for services.
267
	/**
268
		}
268
	 * Closing an application context is a potentially long-running activity, however, we *have* to do it synchronously
269
269
	 * during the event process as the BundleContext object is not valid once we return from this method.
270
		executor.execute(contextRefresh);
270
	 * 
271
	}
271
	 * @param bundle
272
272
	 */
273
	/**
273
	protected void maybeCloseApplicationContextFor(Bundle bundle) {
274
	 * Closing an application context is a potentially long-running activity, however, we *have* to do it synchronously
274
		final ConfigurableOsgiBundleApplicationContext context =
275
	 * during the event process as the BundleContext object is not valid once we return from this method.
275
				(ConfigurableOsgiBundleApplicationContext) managedContexts.remove(Long.valueOf(bundle.getBundleId()));
276
	 * 
276
		if (context == null) {
277
	 * @param bundle
277
			return;
278
	 */
278
		}
279
	protected void maybeCloseApplicationContextFor(Bundle bundle) {
279
280
		final ConfigurableOsgiBundleApplicationContext context =
280
		RunnableTimedExecution.execute(new Runnable() {
281
				(ConfigurableOsgiBundleApplicationContext) managedContexts.remove(Long.valueOf(bundle.getBundleId()));
281
282
		if (context == null) {
282
			private final String toString = "Closing runnable for context " + context.getDisplayName();
283
			return;
283
284
		}
284
			public void run() {
285
285
				closeApplicationContext(context);
286
		RunnableTimedExecution.execute(new Runnable() {
286
			}
287
287
288
			private final String toString = "Closing runnable for context " + context.getDisplayName();
288
			public String toString() {
289
289
				return toString;
290
			public void run() {
290
			}
291
				closeApplicationContext(context);
291
292
			}
292
		}, extenderConfiguration.getShutdownWaitTime(), shutdownTaskExecutor);
293
293
	}
294
			public String toString() {
294
295
				return toString;
295
	/**
296
			}
296
	 * Closes an application context. This is a convenience methods that invokes the event notification as well.
297
297
	 * 
298
		}, extenderConfiguration.getShutdownWaitTime(), shutdownTaskExecutor);
298
	 * @param ctx
299
	}
299
	 */
300
300
	private void closeApplicationContext(ConfigurableOsgiBundleApplicationContext ctx) {
301
	/**
301
		if (log.isDebugEnabled()) {
302
	 * Closes an application context. This is a convenience methods that invokes the event notification as well.
302
			log.debug("Closing application context " + ctx.getDisplayName());
303
	 * 
303
		}
304
	 * @param ctx
304
305
	 */
305
		if (log.isTraceEnabled()) {
306
	private void closeApplicationContext(ConfigurableOsgiBundleApplicationContext ctx) {
306
			log.trace("Calling pre-close on processor " + processor);
307
		if (log.isDebugEnabled()) {
307
		}
308
			log.debug("Closing application context " + ctx.getDisplayName());
308
		processor.preProcessClose(ctx);
309
		}
309
		try {
310
310
			ctx.close();
311
		if (log.isTraceEnabled()) {
311
		} finally {
312
			log.trace("Calling pre-close on processor " + processor);
312
			if (log.isTraceEnabled()) {
313
		}
313
				log.trace("Calling post close on processor " + processor);
314
		processor.preProcessClose(ctx);
314
			}
315
		try {
315
			processor.postProcessClose(ctx);
316
			ctx.close();
316
		}
317
		} finally {
317
	}
318
			if (log.isTraceEnabled()) {
318
319
				log.trace("Calling post close on processor " + processor);
319
	public void destroy() {
320
			}
320
		// first stop the watchdog
321
			processor.postProcessClose(ctx);
321
		stopTimer();
322
		}
322
323
	}
323
		// get hold of the needed bundles
324
324
		List<Bundle> bundles = new ArrayList<Bundle>(managedContexts.size());
325
	public void destroy() {
325
326
		// first stop the watchdog
326
		for (ConfigurableOsgiBundleApplicationContext context : managedContexts.values()) {
327
		stopTimer();
327
			bundles.add(context.getBundle());
328
328
		}
329
		// get hold of the needed bundles
329
330
		List<Bundle> bundles = new ArrayList<Bundle>(managedContexts.size());
330
		boolean debug = log.isDebugEnabled();
331
331
332
		for (ConfigurableOsgiBundleApplicationContext context : managedContexts.values()) {
332
		if (debug) {
333
			bundles.add(context.getBundle());
333
			log.debug("Starting shutdown procedure for bundles " + bundles);
334
		}
334
		}
335
335
		while (!bundles.isEmpty()) {
336
		boolean debug = log.isDebugEnabled();
336
			Collection<Bundle> candidates = ShutdownSorter.getBundles(bundles);
337
337
			if (debug)
338
		if (debug) {
338
				log.debug("Staging shutdown for bundles " + candidates);
339
			log.debug("Starting shutdown procedure for bundles " + bundles);
339
340
		}
340
			final List<Runnable> taskList = new ArrayList<Runnable>(candidates.size());
341
		while (!bundles.isEmpty()) {
341
			final List<ConfigurableOsgiBundleApplicationContext> closedContexts =
342
			Collection<Bundle> candidates = ShutdownSorter.getBundles(bundles);
342
					Collections.synchronizedList(new ArrayList<ConfigurableOsgiBundleApplicationContext>());
343
			if (debug)
343
			final Object[] contextClosingDown = new Object[1];
344
				log.debug("Staging shutdown for bundles " + candidates);
344
345
345
			for (Bundle shutdownBundle : candidates) {
346
			final List<Runnable> taskList = new ArrayList<Runnable>(candidates.size());
346
				final ConfigurableOsgiBundleApplicationContext context = getManagedContext(shutdownBundle);
347
			final List<ConfigurableOsgiBundleApplicationContext> closedContexts =
347
				if (context != null) {
348
					Collections.synchronizedList(new ArrayList<ConfigurableOsgiBundleApplicationContext>());
348
					closedContexts.add(context);
349
			final Object[] contextClosingDown = new Object[1];
349
					// add a new runnable
350
350
					taskList.add(new Runnable() {
351
			for (Bundle shutdownBundle : candidates) {
351
352
				final ConfigurableOsgiBundleApplicationContext context = getManagedContext(shutdownBundle);
352
						private final String toString = "Closing runnable for context " + context.getDisplayName();
353
				if (context != null) {
353
354
					closedContexts.add(context);
354
						public void run() {
355
					// add a new runnable
355
							contextClosingDown[0] = context;
356
					taskList.add(new Runnable() {
356
							// eliminate context
357
357
							closedContexts.remove(context);
358
						private final String toString = "Closing runnable for context " + context.getDisplayName();
358
							closeApplicationContext(context);
359
359
						}
360
						public void run() {
360
361
							contextClosingDown[0] = context;
361
						public String toString() {
362
							// eliminate context
362
							return toString;
363
							closedContexts.remove(context);
363
						}
364
							closeApplicationContext(context);
364
					});
365
						}
365
				}
366
366
			}
367
						public String toString() {
367
368
							return toString;
368
			// tasks
369
						}
369
			final Runnable[] tasks = (Runnable[]) taskList.toArray(new Runnable[taskList.size()]);
370
					});
370
371
				}
371
			// start the ripper >:)
372
			}
372
			for (int j = 0; j < tasks.length; j++) {
373
373
				if (RunnableTimedExecution.execute(tasks[j], extenderConfiguration.getShutdownWaitTime(),
374
			// tasks
374
						shutdownTaskExecutor)) {
375
			final Runnable[] tasks = (Runnable[]) taskList.toArray(new Runnable[taskList.size()]);
375
					if (debug) {
376
376
						log.debug(contextClosingDown[0] + " context did not close successfully; forcing shutdown...");
377
			// start the ripper >:)
377
					}
378
			for (int j = 0; j < tasks.length; j++) {
378
				}
379
				if (RunnableTimedExecution.execute(tasks[j], extenderConfiguration.getShutdownWaitTime(),
379
			}
380
						shutdownTaskExecutor)) {
380
		}
381
					if (debug) {
381
382
						log.debug(contextClosingDown[0] + " context did not close successfully; forcing shutdown...");
382
		this.managedContexts.clear();
383
					}
383
384
				}
384
		// before bailing out; wait for the threads that might be left by
385
			}
385
		// the task executor
386
		}
386
		stopTaskExecutor();
387
387
	}
388
		this.managedContexts.clear();
388
389
389
    public ConfigurableOsgiBundleApplicationContext getManagedContext(Bundle bundle) {
390
		// before bailing out; wait for the threads that might be left by
390
        ConfigurableOsgiBundleApplicationContext context = null;
391
		// the task executor
391
        try {
392
		stopTaskExecutor();
392
            Long id = new Long(bundle.getBundleId());
393
	}
393
            context = (ConfigurableOsgiBundleApplicationContext) managedContexts.get(id);
394
394
        } catch (IllegalStateException _) {
395
    public ConfigurableOsgiBundleApplicationContext getManagedContext(Bundle bundle) {
395
            // ignore
396
        ConfigurableOsgiBundleApplicationContext context = null;
396
        }
397
        try {
397
        return context;
398
            Long id = new Long(bundle.getBundleId());
398
    }
399
            context = (ConfigurableOsgiBundleApplicationContext) managedContexts.get(id);
399
400
        } catch (IllegalStateException _) {
400
	/**
401
            // ignore
401
	 * Do some additional waiting so the service dependency listeners detect the shutdown.
402
        }
402
	 */
403
        return context;
403
	private void stopTaskExecutor() {
404
    }
404
		boolean debug = log.isDebugEnabled();
405
405
406
	/**
406
		if (debug)
407
	 * Do some additional waiting so the service dependency listeners detect the shutdown.
407
			log.debug("Waiting for " + contextsStarted + " service dependency listener(s) to stop...");
408
	 */
408
409
	private void stopTaskExecutor() {
409
		contextsStarted.waitForZero(extenderConfiguration.getShutdownWaitTime());
410
		boolean debug = log.isDebugEnabled();
410
411
411
		if (!contextsStarted.isZero()) {
412
		if (debug)
412
			if (debug)
413
			log.debug("Waiting for " + contextsStarted + " service dependency listener(s) to stop...");
413
				log.debug(contextsStarted.getValue()
414
414
						+ " service dependency listener(s) did not responded in time; forcing them to shutdown...");
415
		contextsStarted.waitForZero(extenderConfiguration.getShutdownWaitTime());
415
			extenderConfiguration.setForceThreadShutdown(true);
416
416
		}
417
		if (!contextsStarted.isZero()) {
417
418
			if (debug)
418
		else
419
				log.debug(contextsStarted.getValue()
419
			log.debug("All listeners closed");
420
						+ " service dependency listener(s) did not responded in time; forcing them to shutdown...");
420
	}
421
			extenderConfiguration.setForceThreadShutdown(true);
421
422
		}
422
	/**
423
423
	 * Cancel any tasks scheduled for the timer.
424
		else
424
	 */
425
			log.debug("All listeners closed");
425
	private void stopTimer() {
426
	}
426
		if (log.isDebugEnabled())
427
427
			log.debug("Canceling timer tasks");
428
	/**
428
		timer.cancel();
429
	 * Cancel any tasks scheduled for the timer.
429
	}
430
	 */
431
	private void stopTimer() {
432
		if (log.isDebugEnabled())
433
			log.debug("Canceling timer tasks");
434
		timer.cancel();
435
	}
436
}
430
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ListListenerAdapter.java (-93 / +88 lines)
Lines 1-94 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc.
2
 * Copyright (c) 2006, 2010 VMware Inc.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution. 
5
 * and Apache License v2.0 which accompanies this distribution. 
6
 * The Eclipse Public License is available at 
6
 * The Eclipse Public License is available at 
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
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.
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. 
9
 * You may elect to redistribute this code under either of these licenses. 
10
 * 
10
 * 
11
 * Contributors:
11
 * Contributors:
12
 *   VMware Inc.
12
 *   VMware Inc.
13
 *****************************************************************************/
13
 *****************************************************************************/
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;
19
import org.osgi.framework.BundleContext;
20
import java.util.Map;
20
import org.osgi.util.tracker.ServiceTracker;
21
import java.util.WeakHashMap;
21
import org.springframework.beans.factory.DisposableBean;
22
22
import org.springframework.beans.factory.InitializingBean;
23
import org.osgi.framework.BundleContext;
23
import org.springframework.core.GenericTypeResolver;
24
import org.osgi.util.tracker.ServiceTracker;
24
25
import org.springframework.beans.factory.DisposableBean;
25
import java.util.Map;
26
import org.springframework.beans.factory.InitializingBean;
26
import java.util.WeakHashMap;
27
import org.springframework.core.GenericTypeResolver;
27
28
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEvent;
28
/**
29
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener;
29
 * Listener interface that delegates to a list of listener. This is useful in OSGi environments when dealing with
30
30
 * dynamic collections which can be updated during iteration.
31
/**
31
 * 
32
 * Listener interface that delegates to a list of listener. This is useful in OSGi environments when dealing with
32
 * @author Costin Leau
33
 * dynamic collections which can be updated during iteration.
33
 * 
34
 * 
34
 */
35
 * @author Costin Leau
35
@SuppressWarnings("unchecked")
36
 * 
36
class ListListenerAdapter implements OsgiBundleApplicationContextListener<OsgiBundleApplicationContextEvent>,
37
 */
37
		InitializingBean, DisposableBean {
38
@SuppressWarnings("unchecked")
38
39
class ListListenerAdapter implements OsgiBundleApplicationContextListener<OsgiBundleApplicationContextEvent>,
39
	private final ServiceTracker tracker;
40
		InitializingBean, DisposableBean {
40
	private final Map<Class<? extends OsgiBundleApplicationContextListener>, Class<? extends OsgiBundleApplicationContextEvent>> eventCache =
41
41
			new WeakHashMap<Class<? extends OsgiBundleApplicationContextListener>, Class<? extends OsgiBundleApplicationContextEvent>>();
42
	private final ServiceTracker tracker;
42
43
	private final Map<Class<? extends OsgiBundleApplicationContextListener>, Class<? extends OsgiBundleApplicationContextEvent>> eventCache =
43
	/**
44
			new WeakHashMap<Class<? extends OsgiBundleApplicationContextListener>, Class<? extends OsgiBundleApplicationContextEvent>>();
44
	 * Constructs a new <code>ListListenerAdapter</code> instance.
45
45
	 */
46
	/**
46
	public ListListenerAdapter(BundleContext bundleContext) {
47
	 * Constructs a new <code>ListListenerAdapter</code> instance.
47
		this.tracker = new ServiceTracker(bundleContext, OsgiBundleApplicationContextListener.class.getName(), null);
48
	 * 
48
	}
49
	 * @param listeners
49
50
	 */
50
	public void afterPropertiesSet() {
51
	public ListListenerAdapter(BundleContext bundleContext) {
51
		this.tracker.open();
52
		this.tracker = new ServiceTracker(bundleContext, OsgiBundleApplicationContextListener.class.getName(), null);
52
	}
53
	}
53
54
54
	public void destroy() {
55
	public void afterPropertiesSet() {
55
		this.tracker.close();
56
		this.tracker.open();
56
		eventCache.clear();
57
	}
57
	}
58
58
59
	public void destroy() {
59
	public void onOsgiApplicationEvent(OsgiBundleApplicationContextEvent event) {
60
		this.tracker.close();
60
		Object[] listeners = tracker.getServices();
61
		eventCache.clear();
61
62
	}
62
		if (listeners != null) {
63
63
			synchronized (eventCache) {
64
	public void onOsgiApplicationEvent(OsgiBundleApplicationContextEvent event) {
64
				for (Object listnr : listeners) {
65
		Object[] listeners = tracker.getServices();
65
					OsgiBundleApplicationContextListener listener = (OsgiBundleApplicationContextListener) listnr;
66
66
					Class<? extends OsgiBundleApplicationContextListener> listenerClass = listener.getClass();
67
		if (listeners != null) {
67
					Class<? extends OsgiBundleApplicationContextEvent> eventType = eventCache.get(listenerClass);
68
			synchronized (eventCache) {
68
					if (eventType == null) {
69
				for (Object listnr : listeners) {
69
						Class<?> evtType =
70
					OsgiBundleApplicationContextListener listener = (OsgiBundleApplicationContextListener) listnr;
70
								GenericTypeResolver.resolveTypeArgument(listenerClass,
71
					Class<? extends OsgiBundleApplicationContextListener> listenerClass = listener.getClass();
71
										OsgiBundleApplicationContextListener.class);
72
					Class<? extends OsgiBundleApplicationContextEvent> eventType = eventCache.get(listenerClass);
72
						if (evtType == null) {
73
					if (eventType == null) {
73
							evtType = OsgiBundleApplicationContextEvent.class;
74
						Class<?> evtType =
74
						}
75
								GenericTypeResolver.resolveTypeArgument(listenerClass,
75
						if (evtType != null && evtType.isAssignableFrom(OsgiBundleApplicationContextEvent.class)) {
76
										OsgiBundleApplicationContextListener.class);
76
							eventType = (Class<? extends OsgiBundleApplicationContextEvent>) evtType;
77
						if (evtType == null) {
77
						} else {
78
							evtType = OsgiBundleApplicationContextEvent.class;
78
							eventType = OsgiBundleApplicationContextEvent.class;
79
						}
79
						}
80
						if (evtType != null && evtType.isAssignableFrom(OsgiBundleApplicationContextEvent.class)) {
80
						eventCache.put(listenerClass, eventType);
81
							eventType = (Class<? extends OsgiBundleApplicationContextEvent>) evtType;
81
					}
82
						} else {
82
					if (eventType.isInstance(event)) {
83
							eventType = OsgiBundleApplicationContextEvent.class;
83
						listener.onOsgiApplicationEvent(event);
84
						}
84
					}
85
						eventCache.put(listenerClass, eventType);
85
				}
86
					}
86
			}
87
					if (eventType.isInstance(event)) {
87
		}
88
						listener.onOsgiApplicationEvent(event);
88
	}
89
					}
90
				}
91
			}
92
		}
93
	}
94
}
89
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ListenerServiceActivator.java (+93 lines)
Added 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.activator;
16
17
import org.apache.commons.logging.Log;
18
import org.apache.commons.logging.LogFactory;
19
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;
20
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
21
import org.osgi.framework.BundleActivator;
22
import org.osgi.framework.BundleContext;
23
24
/**
25
 * Initializes the event multicaster infrastructure.
26
 *
27
 * @author Bill Gallagher
28
 * @author Andy Piper
29
 * @author Hal Hildebrand
30
 * @author Adrian Colyer
31
 * @author Costin Leau
32
 * @author Olaf Otto
33
 */
34
public class ListenerServiceActivator implements BundleActivator {
35
    /**
36
     * Monitor used for dealing with the bundle activator and synchronous bundle threads
37
     */
38
    private final Object monitor = new Object();
39
    private boolean stopped = false;
40
    private OsgiBundleApplicationContextEventMulticaster multicaster;
41
    private volatile ListListenerAdapter osgiListeners;
42
    private final Log log = LogFactory.getLog(getClass());
43
    private final ExtenderConfiguration extenderConfiguration;
44
    private BundleContext extenderBundleContext;
45
46
    public ListenerServiceActivator(ExtenderConfiguration extenderConfiguration) {
47
        this.extenderConfiguration = extenderConfiguration;
48
    }
49
50
    public void start(BundleContext extenderBundleContext) throws Exception {
51
        this.extenderBundleContext = extenderBundleContext;
52
        initListenerService();
53
    }
54
55
    public void stop(BundleContext extenderBundleContext) throws Exception {
56
        synchronized (monitor) {
57
            if (stopped) {
58
                return;
59
            }
60
            stopped = true;
61
        }
62
63
        // release multicaster
64
        if (multicaster != null) {
65
            multicaster.removeAllListeners();
66
            multicaster = null;
67
        }
68
        // release listeners
69
        osgiListeners.destroy();
70
        osgiListeners = null;
71
    }
72
73
    protected void initListenerService() {
74
        this.multicaster = extenderConfiguration.getEventMulticaster();
75
76
        addApplicationListener(multicaster);
77
        multicaster.addApplicationListener(extenderConfiguration.getContextEventListener());
78
79
        if (log.isDebugEnabled())
80
            log.debug("Initialization of OSGi listeners service completed...");
81
    }
82
83
    protected void addApplicationListener(OsgiBundleApplicationContextEventMulticaster multicaster) {
84
        osgiListeners = new ListListenerAdapter(this.extenderBundleContext);
85
        osgiListeners.afterPropertiesSet();
86
        // register the listener that does the dispatching
87
        multicaster.addApplicationListener(osgiListeners);
88
    }
89
90
    public OsgiBundleApplicationContextEventMulticaster getMulticaster() {
91
        return multicaster;
92
    }
93
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LoggingActivator.java (+41 lines)
Added 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.activator;
16
17
import org.apache.commons.logging.Log;
18
import org.apache.commons.logging.LogFactory;
19
import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
20
import org.osgi.framework.BundleActivator;
21
import org.osgi.framework.BundleContext;
22
import org.osgi.framework.Version;
23
24
/**
25
 * Simply writes status convenient status information to the log.
26
 *
27
 * @author Olaf Otto
28
 */
29
public class LoggingActivator implements BundleActivator {
30
    private final Log log = LogFactory.getLog(getClass());
31
32
    public void start(BundleContext extenderBundleContext) throws Exception {
33
        Version extenderVersion = OsgiBundleUtils.getBundleVersion(extenderBundleContext.getBundle());
34
        log.info("Starting [" + extenderBundleContext.getBundle().getSymbolicName() + "] bundle v.[" + extenderVersion + "]");
35
    }
36
37
    public void stop(BundleContext extenderBundleContext) throws Exception {
38
        Version extenderVersion = OsgiBundleUtils.getBundleVersion(extenderBundleContext.getBundle());
39
        log.info("Stopping [" + extenderBundleContext.getBundle().getSymbolicName() + "] bundle v.[" + extenderVersion + "]");
40
    }
41
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/NamespaceHandlerActivator.java (+129 lines)
Added 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.activator;
16
17
import org.apache.commons.logging.Log;
18
import org.apache.commons.logging.LogFactory;
19
import org.eclipse.gemini.blueprint.extender.internal.activator.listeners.BaseListener;
20
import org.eclipse.gemini.blueprint.extender.internal.activator.listeners.NamespaceBundleLister;
21
import org.eclipse.gemini.blueprint.extender.internal.support.NamespaceManager;
22
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
23
import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
24
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
25
import org.osgi.framework.Bundle;
26
import org.osgi.framework.BundleActivator;
27
import org.osgi.framework.BundleContext;
28
import org.osgi.framework.Version;
29
30
/**
31
 * @author Bill Gallagher
32
 * @author Andy Piper
33
 * @author Hal Hildebrand
34
 * @author Adrian Colyer
35
 * @author Costin Leau
36
 * @author Olaf Otto
37
 */
38
public class NamespaceHandlerActivator implements BundleActivator {
39
    /**
40
     * Monitor used for dealing with the bundle activator and synchronous bundle threads
41
     */
42
    private final Object monitor = new Object();
43
    private boolean stopped = false;
44
    private final Log log = LogFactory.getLog(getClass());
45
    private NamespaceManager nsManager;
46
    private BaseListener nsListener;
47
    private long bundleId;
48
    private BundleContext extenderBundleContext;
49
    private DefaultVersionMatcher versionMatcher;
50
51
    public void start(BundleContext extenderBundleContext) {
52
        this.extenderBundleContext = extenderBundleContext;
53
        this.nsManager = new NamespaceManager(extenderBundleContext);
54
        this.bundleId = extenderBundleContext.getBundle().getBundleId();
55
        Version extenderVersion = OsgiBundleUtils.getBundleVersion(extenderBundleContext.getBundle());
56
        this.versionMatcher = new DefaultVersionMatcher(getManagedBundleExtenderVersionHeader(), extenderVersion);
57
58
        initNamespaceHandlers(extenderBundleContext);
59
    }
60
61
    public void stop(BundleContext context) throws Exception {
62
        synchronized (monitor) {
63
            if (stopped) {
64
                return;
65
            }
66
            stopped = true;
67
        }
68
69
        this.nsListener.close();
70
        this.extenderBundleContext.removeBundleListener(this.nsListener);
71
        this.nsListener = null;
72
        this.nsManager.destroy();
73
    }
74
75
    protected String getManagedBundleExtenderVersionHeader() {
76
        return ConfigUtils.EXTENDER_VERSION;
77
    }
78
79
    protected void initNamespaceHandlers(BundleContext extenderBundleContext) {
80
        nsManager = new NamespaceManager(extenderBundleContext);
81
82
        // register listener first to make sure any bundles in INSTALLED state
83
        // are not lost
84
85
        // if the property is defined and true, consider bundles in STARTED/LAZY-INIT state, otherwise use RESOLVED
86
        boolean nsResolved = !Boolean.getBoolean("org.eclipse.gemini.blueprint.ns.bundles.started");
87
        nsListener = new NamespaceBundleLister(nsResolved, this);
88
        extenderBundleContext.addBundleListener(nsListener);
89
90
        Bundle[] previousBundles = extenderBundleContext.getBundles();
91
92
        for (Bundle bundle : previousBundles) {
93
            // special handling for uber bundle being restarted
94
            if ((nsResolved && OsgiBundleUtils.isBundleResolved(bundle)) || (!nsResolved && OsgiBundleUtils.isBundleActive(bundle)) || bundleId == bundle.getBundleId()) {
95
                maybeAddNamespaceHandlerFor(bundle, false);
96
            } else if (OsgiBundleUtils.isBundleLazyActivated(bundle)) {
97
                maybeAddNamespaceHandlerFor(bundle, true);
98
            }
99
        }
100
101
        // discovery finished, publish the resolvers/parsers in the OSGi space
102
        nsManager.afterPropertiesSet();
103
    }
104
105
106
    public void maybeAddNamespaceHandlerFor(Bundle bundle, boolean isLazy) {
107
        if (handlerBundleMatchesExtenderVersion(bundle)) {
108
            nsManager.maybeAddNamespaceHandlerFor(bundle, isLazy);
109
        }
110
    }
111
112
    public void maybeRemoveNameSpaceHandlerFor(Bundle bundle) {
113
        if (handlerBundleMatchesExtenderVersion(bundle))
114
            nsManager.maybeRemoveNameSpaceHandlerFor(bundle);
115
    }
116
117
    /**
118
     * Utility method that does extender range version check and appropriate logging.
119
     */
120
    protected boolean handlerBundleMatchesExtenderVersion(Bundle bundle) {
121
        if (!versionMatcher.matchVersion(bundle)) {
122
            if (log.isDebugEnabled())
123
                log.debug("Ignoring handler bundle " + OsgiStringUtils.nullSafeNameAndSymName(bundle)
124
                        + "] due to mismatch in expected extender version");
125
            return false;
126
        }
127
        return true;
128
    }
129
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/listeners/BaseListener.java (+99 lines)
Added 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.activator.listeners;
16
17
import org.apache.commons.logging.Log;
18
import org.apache.commons.logging.LogFactory;
19
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
20
import org.osgi.framework.Bundle;
21
import org.osgi.framework.BundleEvent;
22
import org.osgi.framework.SynchronousBundleListener;
23
24
import java.util.Map;
25
import java.util.WeakHashMap;
26
27
/**
28
 * Common base class for {@link org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener} listeners.
29
 *
30
 * @author Costin Leau
31
 */
32
public abstract class BaseListener implements SynchronousBundleListener {
33
    public static final int LAZY_ACTIVATION_EVENT_TYPE = 0x00000200;
34
35
    protected final Log log = LogFactory.getLog(getClass());
36
37
    /**
38
     * flag indicating whether the context is down or not - useful during shutdown
39
     */
40
    private volatile boolean isClosed = false;
41
42
    /**
43
     * common cache used for tracking down bundles started lazily so they don't get processed twice (once when
44
     * started lazy, once when started fully)
45
     */
46
    protected final Map<Bundle, Object> lazyBundleCache = new WeakHashMap<Bundle, Object>();
47
    /**
48
     * dummy value for the bundle cache
49
     */
50
    private final Object VALUE = new Object();
51
52
    // caches the bundle
53
    protected void push(Bundle bundle) {
54
        synchronized (lazyBundleCache) {
55
            lazyBundleCache.put(bundle, VALUE);
56
        }
57
    }
58
59
    // checks the presence of the bundle as well as removing it
60
    protected boolean pop(Bundle bundle) {
61
        synchronized (lazyBundleCache) {
62
            return (lazyBundleCache.remove(bundle) != null);
63
        }
64
    }
65
66
    /**
67
     * A bundle has been started, stopped, resolved, or unresolved. This method is a synchronous callback, do not do
68
     * any long-running work in this thread.
69
     *
70
     * @see org.osgi.framework.SynchronousBundleListener#bundleChanged
71
     */
72
    public void bundleChanged(BundleEvent event) {
73
74
        boolean trace = log.isTraceEnabled();
75
76
        // check if the listener is still alive
77
        if (isClosed) {
78
            if (trace)
79
                log.trace("Listener is closed; events are being ignored");
80
            return;
81
        }
82
        if (trace) {
83
            log.trace("Processing bundle event [" + OsgiStringUtils.nullSafeToString(event) + "] for bundle ["
84
                    + OsgiStringUtils.nullSafeSymbolicName(event.getBundle()) + "]");
85
        }
86
        try {
87
            handleEvent(event);
88
        } catch (Exception ex) {
89
            /* log exceptions before swallowing */
90
            log.warn("Got exception while handling event " + event, ex);
91
        }
92
    }
93
94
    protected abstract void handleEvent(BundleEvent event);
95
96
    public void close() {
97
        this.isClosed = true;
98
    }
99
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/listeners/NamespaceBundleLister.java (+73 lines)
Added 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.activator.listeners;
16
17
import org.eclipse.gemini.blueprint.extender.internal.activator.NamespaceHandlerActivator;
18
import org.osgi.framework.Bundle;
19
import org.osgi.framework.BundleEvent;
20
21
/**
22
 * Bundle listener used for detecting namespace handler/resolvers. Exists as a separate listener so that it can be
23
 * registered early to avoid race conditions with bundles in INSTALLING state but still to avoid premature context
24
 * creation before the Spring {@link org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener} is not fully initialized.
25
 *
26
 * @author Costin Leau
27
 */
28
public class NamespaceBundleLister extends BaseListener {
29
30
    private final boolean resolved;
31
    private final NamespaceHandlerActivator namespaceHandlerActivator;
32
33
    public NamespaceBundleLister(boolean resolvedBundles, NamespaceHandlerActivator namespaceHandlerActivator) {
34
        this.resolved = resolvedBundles;
35
        this.namespaceHandlerActivator = namespaceHandlerActivator;
36
    }
37
38
    protected void handleEvent(BundleEvent event) {
39
        Bundle bundle = event.getBundle();
40
41
        switch (event.getType()) {
42
43
            case BundleEvent.RESOLVED:
44
                if (resolved) {
45
                    this.namespaceHandlerActivator.maybeAddNamespaceHandlerFor(bundle, false);
46
                }
47
                break;
48
49
            case LAZY_ACTIVATION_EVENT_TYPE: {
50
                if (!resolved) {
51
                    push(bundle);
52
                    this.namespaceHandlerActivator.maybeAddNamespaceHandlerFor(bundle, true);
53
                }
54
                break;
55
            }
56
            case BundleEvent.STARTED: {
57
                if (!resolved) {
58
                    if (!pop(bundle)) {
59
                        this.namespaceHandlerActivator.maybeAddNamespaceHandlerFor(bundle, false);
60
                    }
61
                }
62
                break;
63
            }
64
            case BundleEvent.STOPPED: {
65
                pop(bundle);
66
                this.namespaceHandlerActivator.maybeRemoveNameSpaceHandlerFor(bundle);
67
                break;
68
            }
69
            default:
70
                break;
71
        }
72
    }
73
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/BlueprintLoaderListener.java (-100 / +95 lines)
Lines 1-101 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc.
2
 * Copyright (c) 2006, 2010 VMware Inc.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution. 
5
 * and Apache License v2.0 which accompanies this distribution. 
6
 * The Eclipse Public License is available at 
6
 * The Eclipse Public License is available at 
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
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.
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. 
9
 * You may elect to redistribute this code under either of these licenses. 
10
 * 
10
 * 
11
 * Contributors:
11
 * Contributors:
12
 *   VMware Inc.
12
 *   VMware Inc.
13
 *****************************************************************************/
13
 *****************************************************************************/
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;
19
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintConfigUtils;
20
import org.eclipse.gemini.blueprint.extender.internal.activator.ApplicationContextConfigurationFactory;
20
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintContainerConfig;
21
import org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener;
21
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintContainerCreator;
22
import org.eclipse.gemini.blueprint.extender.internal.activator.OsgiContextProcessor;
22
import org.eclipse.gemini.blueprint.extender.internal.blueprint.event.EventAdminDispatcher;
23
import org.eclipse.gemini.blueprint.extender.internal.activator.TypeCompatibilityChecker;
23
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
24
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintConfigUtils;
24
import org.eclipse.gemini.blueprint.extender.support.ApplicationContextConfiguration;
25
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintContainerConfig;
25
import org.osgi.framework.Bundle;
26
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintExtenderConfiguration;
26
import org.osgi.framework.BundleContext;
27
import org.eclipse.gemini.blueprint.extender.internal.blueprint.event.EventAdminDispatcher;
27
28
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
28
/**
29
import org.eclipse.gemini.blueprint.extender.support.ApplicationContextConfiguration;
29
 * RFC124 extension to the Spring DM extender.
30
30
 * 
31
/**
31
 * @author Costin Leau
32
 * RFC124 extension to the Spring DM extender.
32
 */
33
 * 
33
public class BlueprintLoaderListener extends ContextLoaderListener {
34
 * @author Costin Leau
34
    private volatile BlueprintListenerManager listenerManager;
35
 */
35
    private volatile BlueprintContainerProcessor contextProcessor;
36
public class BlueprintLoaderListener extends ContextLoaderListener {
36
	private volatile TypeCompatibilityChecker typeChecker;
37
37
    private ListenerServiceActivator listenerServiceActivator;
38
	private volatile EventAdminDispatcher dispatcher;
38
39
	private volatile BlueprintListenerManager listenerManager;
39
    public BlueprintLoaderListener(ExtenderConfiguration extenderConfiguration, ListenerServiceActivator listenerServiceActivator) {
40
	private volatile Bundle bundle;
40
        super(extenderConfiguration);
41
	private volatile BlueprintContainerProcessor contextProcessor;
41
        this.listenerServiceActivator = listenerServiceActivator;
42
	private volatile TypeCompatibilityChecker typeChecker;
42
    }
43
43
44
	@Override
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
55
	@Override
55
	@Override
56
	public void stop(BundleContext context) throws Exception {
56
	public void stop(BundleContext context) throws Exception {
57
		super.stop(context);
57
		super.stop(context);
58
		listenerManager.destroy();
58
		listenerManager.destroy();
59
	}
59
	}
60
60
61
	@Override
61
	@Override
62
	protected ExtenderConfiguration initExtenderConfiguration(BundleContext bundleContext) {
62
	protected ApplicationContextConfigurationFactory createContextConfigFactory() {
63
		return new BlueprintExtenderConfiguration(bundleContext, log);
63
		return new ApplicationContextConfigurationFactory() {
64
	}
64
65
65
			public ApplicationContextConfiguration createConfiguration(Bundle bundle) {
66
	@Override
66
				return new BlueprintContainerConfig(bundle);
67
	protected ApplicationContextConfigurationFactory createContextConfigFactory() {
67
			}
68
		return new ApplicationContextConfigurationFactory() {
68
		};
69
69
	}
70
			public ApplicationContextConfiguration createConfiguration(Bundle bundle) {
70
71
				return new BlueprintContainerConfig(bundle);
71
    /**
72
			}
72
     * Always use the {@link BlueprintContainerCreator}, never the configured creator.
73
		};
73
     * Rationale: Backwards compatibility. Both DM and Blueprint extenders are available simultaneously,
74
	}
74
     * however Blueprint extender support is new and must not be broken by existing configurations. Otherwise, existing
75
75
     * users would have to make their creators aware of the difference between blueprint and dm containers.
76
	@Override
76
     */
77
	protected OsgiContextProcessor createContextProcessor() {
77
    @Override
78
		return contextProcessor;
78
    protected OsgiApplicationContextCreator getOsgiApplicationContextCreator() {
79
	}
79
        return new BlueprintContainerCreator();
80
80
    }
81
	@Override
81
82
	protected TypeCompatibilityChecker getTypeCompatibilityChecker() {
82
    @Override
83
		return typeChecker;
83
	protected OsgiContextProcessor createContextProcessor() {
84
	}
84
		return contextProcessor;
85
85
	}
86
	@Override
86
87
	protected String getManagedBundleExtenderVersionHeader() {
87
	@Override
88
		return BlueprintConfigUtils.EXTENDER_VERSION;
88
	protected TypeCompatibilityChecker getTypeCompatibilityChecker() {
89
	}
89
		return typeChecker;
90
90
	}
91
	@Override
91
92
	protected void addApplicationListener(OsgiBundleApplicationContextEventMulticaster multicaster) {
92
	@Override
93
		super.addApplicationListener(multicaster);
93
	protected String getManagedBundleExtenderVersionHeader() {
94
		// monitor bootstrapping events
94
		return BlueprintConfigUtils.EXTENDER_VERSION;
95
		multicaster.addApplicationListener(contextProcessor);
95
	}
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 (-69 / +102 lines)
Lines 1-69 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc.
2
 * Copyright (c) 2006, 2010 VMware Inc.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution. 
5
 * and Apache License v2.0 which accompanies this distribution. 
6
 * The Eclipse Public License is available at 
6
 * The Eclipse Public License is available at 
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
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.
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. 
9
 * You may elect to redistribute this code under either of these licenses. 
10
 * 
10
 * 
11
 * Contributors:
11
 * Contributors:
12
 *   VMware Inc.
12
 *   VMware Inc.
13
 *****************************************************************************/
13
 *****************************************************************************/
14
14
15
package org.eclipse.gemini.blueprint.extender.internal.boot;
15
package org.eclipse.gemini.blueprint.extender.internal.boot;
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.osgi.framework.BundleActivator;
19
import org.eclipse.gemini.blueprint.extender.internal.activator.*;
20
import org.osgi.framework.BundleContext;
20
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
21
import org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener;
21
import org.osgi.framework.BundleActivator;
22
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.BlueprintLoaderListener;
22
import org.osgi.framework.BundleContext;
23
import org.eclipse.gemini.blueprint.util.OsgiPlatformDetector;
23
import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.BlueprintLoaderListener;
24
import org.springframework.util.ClassUtils;
24
import org.eclipse.gemini.blueprint.util.OsgiPlatformDetector;
25
25
import org.springframework.util.ClassUtils;
26
/**
26
27
 * Bundle activator that simply the lifecycle callbacks to other activators.
27
/**
28
 * 
28
 * Bundle activator that simply the lifecycle callbacks to other activators.
29
 * @author Costin Leau
29
 *
30
 * 
30
 * @author Costin Leau
31
 */
31
 *
32
public class ChainActivator implements BundleActivator {
32
 */
33
33
public class ChainActivator implements BundleActivator {
34
	protected final Log log = LogFactory.getLog(getClass());
34
35
35
	protected final Log log = LogFactory.getLog(getClass());
36
	private static final boolean BLUEPRINT_AVAILABLE =
36
37
			ClassUtils.isPresent("org.osgi.service.blueprint.container.BlueprintContainer", ChainActivator.class
37
	private static final boolean BLUEPRINT_AVAILABLE =
38
					.getClassLoader());
38
			ClassUtils.isPresent("org.osgi.service.blueprint.container.BlueprintContainer", ChainActivator.class
39
39
					.getClassLoader());
40
	private final BundleActivator[] CHAIN;
40
41
41
	private final BundleActivator[] CHAIN;
42
	public ChainActivator() {
42
43
		if (OsgiPlatformDetector.isR42()) {
43
	public ChainActivator() {
44
			if (BLUEPRINT_AVAILABLE) {
44
        final LoggingActivator logStatus = new LoggingActivator();
45
				log.info("Blueprint API detected; enabling Blueprint Container functionality");
45
        final JavaBeansCacheActivator activateJavaBeansCache = new JavaBeansCacheActivator();
46
				CHAIN = new BundleActivator[] { new ContextLoaderListener(), new BlueprintLoaderListener() };
46
        final NamespaceHandlerActivator activateCustomNamespaceHandling = new NamespaceHandlerActivator();
47
			}
47
        final NamespaceHandlerActivator activateBlueprintspecificNamespaceHandling = new BlueprintNamespaceHandlerActivator();
48
			else {
48
        final ExtenderConfiguration initializeExtenderConfiguration = new ExtenderConfiguration();
49
				log.warn("Blueprint API not found; disabling Blueprint Container functionality");
49
        final ListenerServiceActivator activateListeners = new ListenerServiceActivator(initializeExtenderConfiguration);
50
				CHAIN = new BundleActivator[] { new ContextLoaderListener() };	
50
        final ContextLoaderListener listenForSpringDmBundles = new ContextLoaderListener(initializeExtenderConfiguration);
51
			}
51
        final BlueprintLoaderListener listenForBlueprintBundles = new BlueprintLoaderListener(initializeExtenderConfiguration, activateListeners);
52
		} else {
52
53
			log.warn("Pre-4.2 OSGi platform detected; disabling Blueprint Container functionality");
53
        if (OsgiPlatformDetector.isR42()) {
54
			CHAIN = new BundleActivator[] { new ContextLoaderListener() };
54
			if (BLUEPRINT_AVAILABLE) {
55
		}
55
				log.info("Blueprint API detected; enabling Blueprint Container functionality");
56
	}
56
				CHAIN = new BundleActivator[] {
57
57
                        logStatus,
58
	public void start(BundleContext context) throws Exception {
58
                        activateJavaBeansCache,
59
		for (int i = 0; i < CHAIN.length; i++) {
59
                        activateCustomNamespaceHandling,
60
			CHAIN[i].start(context);
60
                        activateBlueprintspecificNamespaceHandling,
61
		}
61
                        initializeExtenderConfiguration,
62
	}
62
                        activateListeners,
63
63
                        listenForSpringDmBundles,
64
	public void stop(BundleContext context) throws Exception {
64
                        listenForBlueprintBundles
65
		for (int i = CHAIN.length - 1; i >= 0; i--) {
65
                };
66
			CHAIN[i].stop(context);
66
			}
67
		}
67
			else {
68
	}
68
				log.warn("Blueprint API not found; disabling Blueprint Container functionality");
69
}
69
				CHAIN = new BundleActivator[] {
70
                        logStatus,
71
                        activateJavaBeansCache,
72
                        activateCustomNamespaceHandling,
73
                        initializeExtenderConfiguration,
74
                        activateListeners,
75
                        listenForSpringDmBundles
76
                };
77
			}
78
		} else {
79
			log.warn("Pre-4.2 OSGi platform detected; disabling Blueprint Container functionality");
80
            CHAIN = new BundleActivator[] {
81
                    logStatus,
82
                    activateJavaBeansCache,
83
                    activateCustomNamespaceHandling,
84
                    initializeExtenderConfiguration,
85
                    activateListeners,
86
                    listenForSpringDmBundles
87
            };
88
        }
89
	}
90
91
	public void start(BundleContext context) throws Exception {
92
		for (int i = 0; i < CHAIN.length; i++) {
93
			CHAIN[i].start(context);
94
		}
95
	}
96
97
	public void stop(BundleContext context) throws Exception {
98
		for (int i = CHAIN.length - 1; i >= 0; i--) {
99
			CHAIN[i].stop(context);
100
		}
101
	}
102
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/support/DefaultOsgiBundleApplicationContextListener.java (-66 / +65 lines)
Lines 1-67 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc., Oracle Inc.
2
 * Copyright (c) 2006, 2010 VMware Inc., Oracle Inc.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution. 
5
 * and Apache License v2.0 which accompanies this distribution. 
6
 * The Eclipse Public License is available at 
6
 * The Eclipse Public License is available at 
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
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.
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. 
9
 * You may elect to redistribute this code under either of these licenses. 
10
 * 
10
 * 
11
 * Contributors:
11
 * Contributors:
12
 *   VMware Inc.
12
 *   VMware Inc.
13
 *   Oracle Inc.
13
 *   Oracle Inc.
14
 *****************************************************************************/
14
 *****************************************************************************/
15
15
16
package org.eclipse.gemini.blueprint.extender.internal.support;
16
package org.eclipse.gemini.blueprint.extender.internal.support;
17
17
18
import org.apache.commons.logging.Log;
18
import org.apache.commons.logging.Log;
19
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEvent;
19
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEvent;
20
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener;
20
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener;
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;
24
25
25
/**
26
/**
26
 * Default application context event logger. Logs (using the {@link org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener} logger, the events received.
27
 * Default application context event logger. Logs (using the {@link ContextLoaderListener} logger, the events received.
27
 * 
28
 * 
28
 * @author Costin Leau
29
 * @author Costin Leau
29
 * @author Andy Piper
30
 * @author Andy Piper
30
 */
31
 */
31
public class DefaultOsgiBundleApplicationContextListener implements
32
public class DefaultOsgiBundleApplicationContextListener implements
32
		OsgiBundleApplicationContextListener<OsgiBundleApplicationContextEvent> {
33
		OsgiBundleApplicationContextListener<OsgiBundleApplicationContextEvent> {
33
34
34
	/** logger */
35
	/** logger */
35
	private final Log log;
36
	private final Log log;
36
37
37
	public DefaultOsgiBundleApplicationContextListener(Log log) {
38
	public DefaultOsgiBundleApplicationContextListener(Log log) {
38
		this.log = log;
39
		this.log = log;
39
	}
40
	}
40
41
41
	public void onOsgiApplicationEvent(OsgiBundleApplicationContextEvent event) {
42
	public void onOsgiApplicationEvent(OsgiBundleApplicationContextEvent event) {
42
		String applicationContextString = event.getApplicationContext().getDisplayName();
43
		String applicationContextString = event.getApplicationContext().getDisplayName();
43
44
44
		if (event instanceof OsgiBundleContextRefreshedEvent) {
45
		if (event instanceof OsgiBundleContextRefreshedEvent) {
45
			log.info("Application context successfully refreshed (" + applicationContextString + ")");
46
			log.info("Application context successfully refreshed (" + applicationContextString + ")");
46
		}
47
		}
47
48
48
		if (event instanceof OsgiBundleContextFailedEvent) {
49
		if (event instanceof OsgiBundleContextFailedEvent) {
49
			OsgiBundleContextFailedEvent failureEvent = (OsgiBundleContextFailedEvent) event;
50
			OsgiBundleContextFailedEvent failureEvent = (OsgiBundleContextFailedEvent) event;
50
			log.error("Application context refresh failed (" + applicationContextString + ")", failureEvent
51
			log.error("Application context refresh failed (" + applicationContextString + ")", failureEvent
51
					.getFailureCause());
52
					.getFailureCause());
52
53
53
		}
54
		}
54
55
55
		if (event instanceof OsgiBundleContextClosedEvent) {
56
		if (event instanceof OsgiBundleContextClosedEvent) {
56
			OsgiBundleContextClosedEvent closedEvent = (OsgiBundleContextClosedEvent) event;
57
			OsgiBundleContextClosedEvent closedEvent = (OsgiBundleContextClosedEvent) event;
57
			Throwable error = closedEvent.getFailureCause();
58
			Throwable error = closedEvent.getFailureCause();
58
59
59
			if (error == null) {
60
			if (error == null) {
60
				log.info("Application context succesfully closed (" + applicationContextString + ")");
61
				log.info("Application context succesfully closed (" + applicationContextString + ")");
61
			} else {
62
			} else {
62
				log.error("Application context close failed (" + applicationContextString + ")", error);
63
				log.error("Application context close failed (" + applicationContextString + ")", error);
63
			}
64
			}
64
		}
65
		}
65
	}
66
	}
67
}
66
}
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfiguration.java (-540 / +528 lines)
Lines 1-541 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc.
2
 * Copyright (c) 2006, 2010 VMware Inc.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution. 
5
 * and Apache License v2.0 which accompanies this distribution. 
6
 * The Eclipse Public License is available at 
6
 * The Eclipse Public License is available at 
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
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.
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. 
9
 * You may elect to redistribute this code under either of these licenses. 
10
 * 
10
 * 
11
 * Contributors:
11
 * Contributors:
12
 *   VMware Inc.
12
 *   VMware Inc.
13
 *****************************************************************************/
13
 *****************************************************************************/
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;
17
import org.apache.commons.logging.Log;
18
import java.net.URL;
18
import org.apache.commons.logging.LogFactory;
19
import java.net.URLDecoder;
19
import org.eclipse.gemini.blueprint.context.ConfigurableOsgiBundleApplicationContext;
20
import java.util.ArrayList;
20
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;
21
import java.util.Collections;
21
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;
22
import java.util.Enumeration;
22
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener;
23
import java.util.List;
23
import org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext;
24
import java.util.Properties;
24
import org.eclipse.gemini.blueprint.extender.OsgiApplicationContextCreator;
25
import java.util.Timer;
25
import org.eclipse.gemini.blueprint.extender.OsgiBeanFactoryPostProcessor;
26
26
import org.eclipse.gemini.blueprint.extender.OsgiServiceDependencyFactory;
27
import org.apache.commons.logging.Log;
27
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;
28
import org.osgi.framework.Bundle;
28
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
29
import org.osgi.framework.BundleContext;
29
import org.eclipse.gemini.blueprint.util.BundleDelegatingClassLoader;
30
import org.springframework.beans.BeanUtils;
30
import org.osgi.framework.Bundle;
31
import org.springframework.beans.factory.DisposableBean;
31
import org.osgi.framework.BundleActivator;
32
import org.springframework.context.event.SimpleApplicationEventMulticaster;
32
import org.osgi.framework.BundleContext;
33
import org.springframework.core.task.SimpleAsyncTaskExecutor;
33
import org.springframework.beans.BeanUtils;
34
import org.springframework.core.task.TaskExecutor;
34
import org.springframework.beans.factory.DisposableBean;
35
import org.eclipse.gemini.blueprint.context.ConfigurableOsgiBundleApplicationContext;
35
import org.springframework.context.event.SimpleApplicationEventMulticaster;
36
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;
36
import org.springframework.core.task.SimpleAsyncTaskExecutor;
37
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;
37
import org.springframework.core.task.TaskExecutor;
38
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener;
38
import org.springframework.scheduling.timer.TimerTaskExecutor;
39
import org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext;
39
import org.springframework.util.Assert;
40
import org.eclipse.gemini.blueprint.extender.OsgiApplicationContextCreator;
40
import org.springframework.util.ObjectUtils;
41
import org.eclipse.gemini.blueprint.extender.OsgiBeanFactoryPostProcessor;
41
42
import org.eclipse.gemini.blueprint.extender.OsgiServiceDependencyFactory;
42
import java.io.UnsupportedEncodingException;
43
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;
43
import java.net.URL;
44
import org.eclipse.gemini.blueprint.extender.support.DefaultOsgiApplicationContextCreator;
44
import java.net.URLDecoder;
45
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
45
import java.util.*;
46
import org.eclipse.gemini.blueprint.util.BundleDelegatingClassLoader;
46
47
import org.springframework.scheduling.timer.TimerTaskExecutor;
47
/**
48
import org.springframework.util.Assert;
48
 * Configuration class for the extender. Takes care of locating the extender specific configurations and merging the
49
import org.springframework.util.ObjectUtils;
49
 * results with the defaults.
50
50
 * 
51
/**
51
 * @author Costin Leau
52
 * Configuration class for the extender. Takes care of locating the extender specific configurations and merging the
52
 */
53
 * results with the defaults.
53
public class ExtenderConfiguration implements BundleActivator {
54
 * 
54
55
 * @author Costin Leau
55
	/** logger */
56
 */
56
    protected final Log log = LogFactory.getLog(getClass());
57
public class ExtenderConfiguration implements DisposableBean {
57
58
58
    private static final String TASK_EXECUTOR_NAME = "taskExecutor";
59
	/** logger */
59
60
	private final Log log;
60
	private static final String SHUTDOWN_TASK_EXECUTOR_NAME = "shutdownTaskExecutor";
61
61
62
	private static final String TASK_EXECUTOR_NAME = "taskExecutor";
62
	private static final String CONTEXT_CREATOR_NAME = "applicationContextCreator";
63
63
64
	private static final String SHUTDOWN_TASK_EXECUTOR_NAME = "shutdownTaskExecutor";
64
	private static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "osgiApplicationEventMulticaster";
65
65
66
	private static final String CONTEXT_CREATOR_NAME = "applicationContextCreator";
66
	private static final String CONTEXT_LISTENER_NAME = "osgiApplicationContextListener";
67
67
68
	private static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "osgiApplicationEventMulticaster";
68
	private static final String PROPERTIES_NAME = "extenderProperties";
69
69
70
	private static final String CONTEXT_LISTENER_NAME = "osgiApplicationContextListener";
70
	private static final String SHUTDOWN_WAIT_KEY = "shutdown.wait.time";
71
71
72
	private static final String PROPERTIES_NAME = "extenderProperties";
72
	private static final String PROCESS_ANNOTATIONS_KEY = "process.annotations";
73
73
74
	private static final String SHUTDOWN_WAIT_KEY = "shutdown.wait.time";
74
	private static final String WAIT_FOR_DEPS_TIMEOUT_KEY = "dependencies.wait.time";
75
75
76
	private static final String PROCESS_ANNOTATIONS_KEY = "process.annotations";
76
	private static final String EXTENDER_CFG_LOCATION = "META-INF/spring/extender";
77
77
78
	private static final String WAIT_FOR_DEPS_TIMEOUT_KEY = "dependencies.wait.time";
78
	private static final String XML_PATTERN = "*.xml";
79
79
80
	private static final String EXTENDER_CFG_LOCATION = "META-INF/spring/extender";
80
	private static final String ANNOTATION_DEPENDENCY_FACTORY =
81
81
			"org.eclipse.gemini.blueprint.extensions.annotation.ServiceReferenceDependencyBeanFactoryPostProcessor";
82
	private static final String XML_PATTERN = "*.xml";
82
83
83
	/** annotation processing system property (kept for backwards compatibility) */
84
	private static final String ANNOTATION_DEPENDENCY_FACTORY =
84
	private static final String AUTO_ANNOTATION_PROCESSING =
85
			"org.eclipse.gemini.blueprint.extensions.annotation.ServiceReferenceDependencyBeanFactoryPostProcessor";
85
			"org.eclipse.gemini.blueprint.extender.annotation.auto.processing";
86
86
87
	/** annotation processing system property (kept for backwards compatibility) */
87
	//
88
	private static final String AUTO_ANNOTATION_PROCESSING =
88
	// defaults
89
			"org.eclipse.gemini.blueprint.extender.annotation.auto.processing";
89
	//
90
90
91
	//
91
	// default dependency wait time (in milliseconds)
92
	// defaults
92
	private static final long DEFAULT_DEP_WAIT = ConfigUtils.DIRECTIVE_TIMEOUT_DEFAULT * 1000;
93
	//
93
	private static final boolean DEFAULT_NS_BUNDLE_STATE = true;
94
94
	private static final long DEFAULT_SHUTDOWN_WAIT = 10 * 1000;
95
	// default dependency wait time (in milliseconds)
95
	private static final boolean DEFAULT_PROCESS_ANNOTATION = false;
96
	private static final long DEFAULT_DEP_WAIT = ConfigUtils.DIRECTIVE_TIMEOUT_DEFAULT * 1000;
96
97
	private static final boolean DEFAULT_NS_BUNDLE_STATE = true;
97
	private ConfigurableOsgiBundleApplicationContext extenderConfiguration;
98
	private static final long DEFAULT_SHUTDOWN_WAIT = 10 * 1000;
98
99
	private static final boolean DEFAULT_PROCESS_ANNOTATION = false;
99
	private TaskExecutor taskExecutor, shutdownTaskExecutor;
100
100
101
	private ConfigurableOsgiBundleApplicationContext extenderConfiguration;
101
	private boolean isTaskExecutorManagedInternally;
102
102
103
	private TaskExecutor taskExecutor, shutdownTaskExecutor;
103
	private boolean isShutdownTaskExecutorManagedInternally;
104
104
105
	private boolean isTaskExecutorManagedInternally;
105
	private boolean isMulticasterManagedInternally;
106
106
107
	private boolean isShutdownTaskExecutorManagedInternally;
107
	private long shutdownWaitTime, dependencyWaitTime;
108
108
109
	private boolean isMulticasterManagedInternally;
109
	private boolean processAnnotation, nsBundledResolved;
110
110
111
	private long shutdownWaitTime, dependencyWaitTime;
111
	private OsgiBundleApplicationContextEventMulticaster eventMulticaster;
112
112
113
	private boolean processAnnotation, nsBundledResolved;
113
	private OsgiBundleApplicationContextListener contextEventListener;
114
114
115
	private OsgiBundleApplicationContextEventMulticaster eventMulticaster;
115
	private boolean forceThreadShutdown;
116
116
117
	private OsgiBundleApplicationContextListener contextEventListener;
117
	private OsgiApplicationContextCreator contextCreator = null;
118
118
119
	private boolean forceThreadShutdown;
119
	/** bundle wrapped class loader */
120
120
	private ClassLoader classLoader;
121
	private OsgiApplicationContextCreator contextCreator;
121
	/** List of context post processors */
122
122
	private final List<OsgiBeanFactoryPostProcessor> postProcessors =
123
	/** bundle wrapped class loader */
123
			Collections.synchronizedList(new ArrayList<OsgiBeanFactoryPostProcessor>(0));
124
	private final ClassLoader classLoader;
124
	/** List of service dependency factories */
125
	/** List of context post processors */
125
	private final List<OsgiServiceDependencyFactory> dependencyFactories =
126
	private final List<OsgiBeanFactoryPostProcessor> postProcessors =
126
			Collections.synchronizedList(new ArrayList<OsgiServiceDependencyFactory>(0));
127
			Collections.synchronizedList(new ArrayList<OsgiBeanFactoryPostProcessor>(0));
127
128
	/** List of service dependency factories */
128
	// fields reading/writing lock
129
	private final List<OsgiServiceDependencyFactory> dependencyFactories =
129
	private final Object lock = new Object();
130
			Collections.synchronizedList(new ArrayList<OsgiServiceDependencyFactory>(0));
130
131
131
	/**
132
	// fields reading/writing lock
132
	 * Constructs a new <code>ExtenderConfiguration</code> instance. Locates the extender configuration, creates an
133
	private final Object lock = new Object();
133
	 * application context which will returned the extender items.
134
134
	 * 
135
	/**
135
	 * @param extenderBundleContext extender OSGi bundle context
136
	 * Constructs a new <code>ExtenderConfiguration</code> instance. Locates the extender configuration, creates an
136
	 */
137
	 * application context which will returned the extender items.
137
	public void start(BundleContext extenderBundleContext) {
138
	 * 
138
		Bundle bundle = extenderBundleContext.getBundle();
139
	 * @param bundleContext extender OSGi bundle context
139
		Properties properties = new Properties(createDefaultProperties());
140
	 */
140
141
	public ExtenderConfiguration(BundleContext bundleContext, Log log) {
141
		Enumeration<?> enm = bundle.findEntries(EXTENDER_CFG_LOCATION, XML_PATTERN, false);
142
		this.log = log;
142
143
		Bundle bundle = bundleContext.getBundle();
143
		if (enm == null) {
144
		Properties properties = new Properties(createDefaultProperties());
144
			log.info("No custom extender configuration detected; using defaults...");
145
145
			synchronized (lock) {
146
		Enumeration<?> enm = bundle.findEntries(EXTENDER_CFG_LOCATION, XML_PATTERN, false);
146
				taskExecutor = createDefaultTaskExecutor();
147
147
				shutdownTaskExecutor = createDefaultShutdownTaskExecutor();
148
		if (enm == null) {
148
				eventMulticaster = createDefaultEventMulticaster();
149
			log.info("No custom extender configuration detected; using defaults...");
149
				contextEventListener = createDefaultApplicationContextListener();
150
150
			}
151
			synchronized (lock) {
151
			classLoader = BundleDelegatingClassLoader.createBundleClassLoaderFor(bundle);
152
				taskExecutor = createDefaultTaskExecutor();
152
		} else {
153
				shutdownTaskExecutor = createDefaultShutdownTaskExecutor();
153
			String[] configs = copyEnumerationToList(enm);
154
				eventMulticaster = createDefaultEventMulticaster();
154
155
				contextCreator = createDefaultApplicationContextCreator();
155
			log.info("Detected extender custom configurations at " + ObjectUtils.nullSafeToString(configs));
156
				contextEventListener = createDefaultApplicationContextListener();
156
			// create OSGi specific XML context
157
157
			ConfigurableOsgiBundleApplicationContext extenderAppCtx = new OsgiBundleXmlApplicationContext(configs);
158
			}
158
			extenderAppCtx.setBundleContext(extenderBundleContext);
159
			classLoader = BundleDelegatingClassLoader.createBundleClassLoaderFor(bundle);
159
			extenderAppCtx.refresh();
160
		} else {
160
161
			String[] configs = copyEnumerationToList(enm);
161
			synchronized (lock) {
162
162
				extenderConfiguration = extenderAppCtx;
163
			log.info("Detected extender custom configurations at " + ObjectUtils.nullSafeToString(configs));
163
				// initialize beans
164
			// create OSGi specific XML context
164
				taskExecutor =
165
			ConfigurableOsgiBundleApplicationContext extenderAppCtx = new OsgiBundleXmlApplicationContext(configs);
165
						extenderConfiguration.containsBean(TASK_EXECUTOR_NAME) ? (TaskExecutor) extenderConfiguration
166
			extenderAppCtx.setBundleContext(bundleContext);
166
								.getBean(TASK_EXECUTOR_NAME, TaskExecutor.class) : createDefaultTaskExecutor();
167
			extenderAppCtx.refresh();
167
168
168
				shutdownTaskExecutor =
169
			synchronized (lock) {
169
						extenderConfiguration.containsBean(SHUTDOWN_TASK_EXECUTOR_NAME) ? (TaskExecutor) extenderConfiguration
170
				extenderConfiguration = extenderAppCtx;
170
								.getBean(SHUTDOWN_TASK_EXECUTOR_NAME, TaskExecutor.class)
171
				// initialize beans
171
								: createDefaultShutdownTaskExecutor();
172
				taskExecutor =
172
173
						extenderConfiguration.containsBean(TASK_EXECUTOR_NAME) ? (TaskExecutor) extenderConfiguration
173
				eventMulticaster =
174
								.getBean(TASK_EXECUTOR_NAME, TaskExecutor.class) : createDefaultTaskExecutor();
174
						extenderConfiguration.containsBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME) ? (OsgiBundleApplicationContextEventMulticaster) extenderConfiguration
175
175
								.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
176
				shutdownTaskExecutor =
176
										OsgiBundleApplicationContextEventMulticaster.class)
177
						extenderConfiguration.containsBean(SHUTDOWN_TASK_EXECUTOR_NAME) ? (TaskExecutor) extenderConfiguration
177
								: createDefaultEventMulticaster();
178
								.getBean(SHUTDOWN_TASK_EXECUTOR_NAME, TaskExecutor.class)
178
179
								: createDefaultShutdownTaskExecutor();
179
				contextCreator =
180
180
						extenderConfiguration.containsBean(CONTEXT_CREATOR_NAME) ? (OsgiApplicationContextCreator) extenderConfiguration
181
				eventMulticaster =
181
								.getBean(CONTEXT_CREATOR_NAME, OsgiApplicationContextCreator.class)
182
						extenderConfiguration.containsBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME) ? (OsgiBundleApplicationContextEventMulticaster) extenderConfiguration
182
								: null;
183
								.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
183
184
										OsgiBundleApplicationContextEventMulticaster.class)
184
				contextEventListener =
185
								: createDefaultEventMulticaster();
185
						extenderConfiguration.containsBean(CONTEXT_LISTENER_NAME) ? (OsgiBundleApplicationContextListener) extenderConfiguration
186
186
								.getBean(CONTEXT_LISTENER_NAME, OsgiBundleApplicationContextListener.class)
187
				contextCreator =
187
								: createDefaultApplicationContextListener();
188
						extenderConfiguration.containsBean(CONTEXT_CREATOR_NAME) ? (OsgiApplicationContextCreator) extenderConfiguration
188
			}
189
								.getBean(CONTEXT_CREATOR_NAME, OsgiApplicationContextCreator.class)
189
190
								: createDefaultApplicationContextCreator();
190
			// get post processors
191
191
			postProcessors.addAll(extenderConfiguration.getBeansOfType(OsgiBeanFactoryPostProcessor.class).values());
192
				contextEventListener =
192
193
						extenderConfiguration.containsBean(CONTEXT_LISTENER_NAME) ? (OsgiBundleApplicationContextListener) extenderConfiguration
193
			// get dependency factories
194
								.getBean(CONTEXT_LISTENER_NAME, OsgiBundleApplicationContextListener.class)
194
			dependencyFactories.addAll(extenderConfiguration.getBeansOfType(OsgiServiceDependencyFactory.class)
195
								: createDefaultApplicationContextListener();
195
					.values());
196
			}
196
197
197
			classLoader = extenderConfiguration.getClassLoader();
198
			// get post processors
198
			// extender properties using the defaults as backup
199
			postProcessors.addAll(extenderConfiguration.getBeansOfType(OsgiBeanFactoryPostProcessor.class).values());
199
			if (extenderConfiguration.containsBean(PROPERTIES_NAME)) {
200
200
				Properties customProperties =
201
			// get dependency factories
201
						(Properties) extenderConfiguration.getBean(PROPERTIES_NAME, Properties.class);
202
			dependencyFactories.addAll(extenderConfiguration.getBeansOfType(OsgiServiceDependencyFactory.class)
202
				Enumeration<?> propertyKey = customProperties.propertyNames();
203
					.values());
203
				while (propertyKey.hasMoreElements()) {
204
204
					String property = (String) propertyKey.nextElement();
205
			classLoader = extenderConfiguration.getClassLoader();
205
					properties.setProperty(property, customProperties.getProperty(property));
206
			// extender properties using the defaults as backup
206
				}
207
			if (extenderConfiguration.containsBean(PROPERTIES_NAME)) {
207
			}
208
				Properties customProperties =
208
		}
209
						(Properties) extenderConfiguration.getBean(PROPERTIES_NAME, Properties.class);
209
210
				Enumeration<?> propertyKey = customProperties.propertyNames();
210
		synchronized (lock) {
211
				while (propertyKey.hasMoreElements()) {
211
			shutdownWaitTime = getShutdownWaitTime(properties);
212
					String property = (String) propertyKey.nextElement();
212
			dependencyWaitTime = getDependencyWaitTime(properties);
213
					properties.setProperty(property, customProperties.getProperty(property));
213
			processAnnotation = getProcessAnnotations(properties);
214
				}
214
		}
215
			}
215
216
		}
216
		// load default dependency factories
217
217
		addDefaultDependencyFactories();
218
		synchronized (lock) {
218
219
			shutdownWaitTime = getShutdownWaitTime(properties);
219
		// allow post processing
220
			dependencyWaitTime = getDependencyWaitTime(properties);
220
		contextCreator = postProcess(contextCreator);
221
			processAnnotation = getProcessAnnotations(properties);
221
	}
222
		}
222
223
223
	/**
224
		// load default dependency factories
224
	 * Allows post processing of the context creator.
225
		addDefaultDependencyFactories();
225
	 * 
226
226
	 * @param contextCreator
227
		// allow post processing
227
	 * @return
228
		contextCreator = postProcess(contextCreator);
228
	 */
229
	}
229
	protected OsgiApplicationContextCreator postProcess(OsgiApplicationContextCreator contextCreator) {
230
230
		return contextCreator;
231
	/**
231
	}
232
	 * Allows post processing of the context creator.
232
233
	 * 
233
	/**
234
	 * @param contextCreator
234
	 * {@inheritDoc}
235
	 * @return
235
	 * 
236
	 */
236
	 * Cleanup the configuration items.
237
	protected OsgiApplicationContextCreator postProcess(OsgiApplicationContextCreator contextCreator) {
237
	 */
238
		return contextCreator;
238
	public void stop(BundleContext extenderBundleContext) {
239
	}
239
240
240
		synchronized (lock) {
241
	/**
241
			if (isMulticasterManagedInternally) {
242
	 * {@inheritDoc}
242
				eventMulticaster.removeAllListeners();
243
	 * 
243
				eventMulticaster = null;
244
	 * Cleanup the configuration items.
244
			}
245
	 */
245
246
	public void destroy() {
246
			if (extenderConfiguration != null) {
247
247
				extenderConfiguration.close();
248
		synchronized (lock) {
248
				extenderConfiguration = null;
249
			if (isMulticasterManagedInternally) {
249
			}
250
				eventMulticaster.removeAllListeners();
250
251
				eventMulticaster = null;
251
			// postpone the task executor shutdown
252
			}
252
			if (forceThreadShutdown) {
253
253
254
			if (extenderConfiguration != null) {
254
				if (isTaskExecutorManagedInternally) {
255
				extenderConfiguration.close();
255
					log.warn("Forcing the (internally created) taskExecutor to stop...");
256
				extenderConfiguration = null;
256
					ThreadGroup th = ((SimpleAsyncTaskExecutor) taskExecutor).getThreadGroup();
257
			}
257
					if (!th.isDestroyed()) {
258
258
						// ask the threads nicely to stop
259
			// postpone the task executor shutdown
259
						th.interrupt();
260
			if (forceThreadShutdown) {
260
					}
261
261
				}
262
				if (isTaskExecutorManagedInternally) {
262
				taskExecutor = null;
263
					log.warn("Forcing the (internally created) taskExecutor to stop...");
263
			}
264
					ThreadGroup th = ((SimpleAsyncTaskExecutor) taskExecutor).getThreadGroup();
264
265
					if (!th.isDestroyed()) {
265
			if (isShutdownTaskExecutorManagedInternally) {
266
						// ask the threads nicely to stop
266
				try {
267
						th.interrupt();
267
					((DisposableBean) shutdownTaskExecutor).destroy();
268
					}
268
				} catch (Exception ex) {
269
				}
269
					log.debug("Received exception while shutting down shutdown task executor", ex);
270
				taskExecutor = null;
270
				}
271
			}
271
				shutdownTaskExecutor = null;
272
272
			}
273
			if (isShutdownTaskExecutorManagedInternally) {
273
		}
274
				try {
274
	}
275
					((DisposableBean) shutdownTaskExecutor).destroy();
275
276
				} catch (Exception ex) {
276
	/**
277
					log.debug("Received exception while shutting down shutdown task executor", ex);
277
	 * Copies the URLs returned by the given enumeration and returns them as an array of Strings for consumption by the
278
				}
278
	 * application context.
279
				shutdownTaskExecutor = null;
279
	 * 
280
			}
280
	 * @param enm
281
		}
281
	 * @return
282
	}
282
	 */
283
283
	@SuppressWarnings("deprecation")
284
	/**
284
	private String[] copyEnumerationToList(Enumeration<?> enm) {
285
	 * Copies the URLs returned by the given enumeration and returns them as an array of Strings for consumption by the
285
		List<String> urls = new ArrayList<String>(4);
286
	 * application context.
286
		while (enm != null && enm.hasMoreElements()) {
287
	 * 
287
			URL configURL = (URL) enm.nextElement();
288
	 * @param enm
288
			if (configURL != null) {
289
	 * @return
289
				String configURLAsString = configURL.toExternalForm();
290
	 */
290
				try {
291
	@SuppressWarnings("deprecation")
291
					urls.add(URLDecoder.decode(configURLAsString, "UTF8"));
292
	private String[] copyEnumerationToList(Enumeration<?> enm) {
292
				} catch (UnsupportedEncodingException uee) {
293
		List<String> urls = new ArrayList<String>(4);
293
					log.warn("UTF8 encoding not supported, using the platform default");
294
		while (enm != null && enm.hasMoreElements()) {
294
					urls.add(URLDecoder.decode(configURLAsString));
295
			URL configURL = (URL) enm.nextElement();
295
				}
296
			if (configURL != null) {
296
			}
297
				String configURLAsString = configURL.toExternalForm();
297
		}
298
				try {
298
299
					urls.add(URLDecoder.decode(configURLAsString, "UTF8"));
299
		return (String[]) urls.toArray(new String[urls.size()]);
300
				} catch (UnsupportedEncodingException uee) {
300
	}
301
					log.warn("UTF8 encoding not supported, using the platform default");
301
302
					urls.add(URLDecoder.decode(configURLAsString));
302
	private Properties createDefaultProperties() {
303
				}
303
		Properties properties = new Properties();
304
			}
304
		properties.setProperty(SHUTDOWN_WAIT_KEY, "" + DEFAULT_SHUTDOWN_WAIT);
305
		}
305
		properties.setProperty(PROCESS_ANNOTATIONS_KEY, "" + DEFAULT_PROCESS_ANNOTATION);
306
306
		properties.setProperty(WAIT_FOR_DEPS_TIMEOUT_KEY, "" + DEFAULT_DEP_WAIT);
307
		return (String[]) urls.toArray(new String[urls.size()]);
307
308
	}
308
		return properties;
309
309
	}
310
	private Properties createDefaultProperties() {
310
311
		Properties properties = new Properties();
311
	protected void addDefaultDependencyFactories() {
312
		properties.setProperty(SHUTDOWN_WAIT_KEY, "" + DEFAULT_SHUTDOWN_WAIT);
312
		boolean debug = log.isDebugEnabled();
313
		properties.setProperty(PROCESS_ANNOTATIONS_KEY, "" + DEFAULT_PROCESS_ANNOTATION);
313
314
		properties.setProperty(WAIT_FOR_DEPS_TIMEOUT_KEY, "" + DEFAULT_DEP_WAIT);
314
		// default JDK 1.4 processor
315
315
		dependencyFactories.add(0, new MandatoryImporterDependencyFactory());
316
		return properties;
316
317
	}
317
		// load through reflection the dependency and injection processors if running on JDK 1.5 and annotation
318
318
		// processing is enabled
319
	protected void addDefaultDependencyFactories() {
319
		if (processAnnotation) {
320
		boolean debug = log.isDebugEnabled();
320
			// dependency processor
321
321
			Class<?> annotationProcessor = null;
322
		// default JDK 1.4 processor
322
			try {
323
		dependencyFactories.add(0, new MandatoryImporterDependencyFactory());
323
				annotationProcessor =
324
324
						Class.forName(ANNOTATION_DEPENDENCY_FACTORY, false, ExtenderConfiguration.class
325
		// load through reflection the dependency and injection processors if running on JDK 1.5 and annotation
325
								.getClassLoader());
326
		// processing is enabled
326
			} catch (ClassNotFoundException cnfe) {
327
		if (processAnnotation) {
327
				log.warn("Spring DM annotation package not found, annotation processing disabled.");
328
			// dependency processor
328
				log.debug("Spring DM annotation package not found, annotation processing disabled.", cnfe);
329
			Class<?> annotationProcessor = null;
329
				return;
330
			try {
330
			}
331
				annotationProcessor =
331
			Object processor = BeanUtils.instantiateClass(annotationProcessor);
332
						Class.forName(ANNOTATION_DEPENDENCY_FACTORY, false, ExtenderConfiguration.class
332
			Assert.isInstanceOf(OsgiServiceDependencyFactory.class, processor);
333
								.getClassLoader());
333
			dependencyFactories.add(1, (OsgiServiceDependencyFactory) processor);
334
			} catch (ClassNotFoundException cnfe) {
334
335
				log.warn("Spring DM annotation package not found, annotation processing disabled.");
335
			if (debug)
336
				log.debug("Spring DM annotation package not found, annotation processing disabled.", cnfe);
336
				log.debug("Succesfully loaded annotation dependency processor [" + ANNOTATION_DEPENDENCY_FACTORY + "]");
337
				return;
337
338
			}
338
			// add injection processor (first in line)
339
			Object processor = BeanUtils.instantiateClass(annotationProcessor);
339
			postProcessors.add(0, new OsgiAnnotationPostProcessor());
340
			Assert.isInstanceOf(OsgiServiceDependencyFactory.class, processor);
340
			log.info("Spring-DM annotation processing enabled");
341
			dependencyFactories.add(1, (OsgiServiceDependencyFactory) processor);
341
		} else {
342
342
			if (debug) {
343
			if (debug)
343
				log.debug("Spring-DM annotation processing disabled; [" + ANNOTATION_DEPENDENCY_FACTORY
344
				log.debug("Succesfully loaded annotation dependency processor [" + ANNOTATION_DEPENDENCY_FACTORY + "]");
344
						+ "] not loaded");
345
345
			}
346
			// add injection processor (first in line)
346
		}
347
			postProcessors.add(0, new OsgiAnnotationPostProcessor());
347
348
			log.info("Spring-DM annotation processing enabled");
348
	}
349
		} else {
349
350
			if (debug) {
350
	private TaskExecutor createDefaultTaskExecutor() {
351
				log.debug("Spring-DM annotation processing disabled; [" + ANNOTATION_DEPENDENCY_FACTORY
351
		// create thread-pool for starting contexts
352
						+ "] not loaded");
352
		ThreadGroup threadGroup =
353
			}
353
				new ThreadGroup("eclipse-gemini-blueprint-extender[" + ObjectUtils.getIdentityHexString(this) + "]-threads");
354
		}
354
		threadGroup.setDaemon(false);
355
355
356
	}
356
		SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
357
357
		taskExecutor.setThreadGroup(threadGroup);
358
	private TaskExecutor createDefaultTaskExecutor() {
358
		taskExecutor.setThreadNamePrefix("EclipseGeminiBlueprintExtenderThread-");
359
		// create thread-pool for starting contexts
359
360
		ThreadGroup threadGroup =
360
		isTaskExecutorManagedInternally = true;
361
				new ThreadGroup("eclipse-gemini-blueprint-extender[" + ObjectUtils.getIdentityHexString(this) + "]-threads");
361
362
		threadGroup.setDaemon(false);
362
		return taskExecutor;
363
363
	}
364
		SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
364
365
		taskExecutor.setThreadGroup(threadGroup);
365
	private TaskExecutor createDefaultShutdownTaskExecutor() {
366
		taskExecutor.setThreadNamePrefix("EclipseGeminiBlueprintExtenderThread-");
366
		TimerTaskExecutor taskExecutor = new TimerTaskExecutor() {
367
367
			@Override
368
		isTaskExecutorManagedInternally = true;
368
			protected Timer createTimer() {
369
369
				return new Timer("Gemini Blueprint context shutdown thread", true);
370
		return taskExecutor;
370
			}
371
	}
371
		};
372
372
373
	private TaskExecutor createDefaultShutdownTaskExecutor() {
373
		taskExecutor.afterPropertiesSet();
374
		TimerTaskExecutor taskExecutor = new TimerTaskExecutor() {
374
		isShutdownTaskExecutorManagedInternally = true;
375
			@Override
375
		return taskExecutor;
376
			protected Timer createTimer() {
376
	}
377
				return new Timer("Gemini Blueprint context shutdown thread", true);
377
378
			}
378
	private OsgiBundleApplicationContextEventMulticaster createDefaultEventMulticaster() {
379
		};
379
		isMulticasterManagedInternally = true;
380
380
		return new OsgiBundleApplicationContextEventMulticasterAdapter(new SimpleApplicationEventMulticaster());
381
		taskExecutor.afterPropertiesSet();
381
	}
382
		isShutdownTaskExecutorManagedInternally = true;
382
383
		return taskExecutor;
383
	private OsgiBundleApplicationContextListener createDefaultApplicationContextListener() {
384
	}
384
		return new DefaultOsgiBundleApplicationContextListener(log);
385
385
	}
386
	private OsgiBundleApplicationContextEventMulticaster createDefaultEventMulticaster() {
386
387
		isMulticasterManagedInternally = true;
387
	private long getShutdownWaitTime(Properties properties) {
388
		return new OsgiBundleApplicationContextEventMulticasterAdapter(new SimpleApplicationEventMulticaster());
388
		return Long.parseLong(properties.getProperty(SHUTDOWN_WAIT_KEY));
389
	}
389
	}
390
390
391
	private OsgiApplicationContextCreator createDefaultApplicationContextCreator() {
391
	private long getDependencyWaitTime(Properties properties) {
392
		return new DefaultOsgiApplicationContextCreator();
392
		return Long.parseLong(properties.getProperty(WAIT_FOR_DEPS_TIMEOUT_KEY));
393
	}
393
	}
394
394
395
	private OsgiBundleApplicationContextListener createDefaultApplicationContextListener() {
395
	private boolean getProcessAnnotations(Properties properties) {
396
		return new DefaultOsgiBundleApplicationContextListener(log);
396
		return Boolean.valueOf(properties.getProperty(PROCESS_ANNOTATIONS_KEY)).booleanValue()
397
	}
397
				|| Boolean.getBoolean(AUTO_ANNOTATION_PROCESSING);
398
398
	}
399
	private long getShutdownWaitTime(Properties properties) {
399
400
		return Long.parseLong(properties.getProperty(SHUTDOWN_WAIT_KEY));
400
	/**
401
	}
401
	 * Returns the taskExecutor.
402
402
	 * 
403
	private long getDependencyWaitTime(Properties properties) {
403
	 * @return Returns the taskExecutor
404
		return Long.parseLong(properties.getProperty(WAIT_FOR_DEPS_TIMEOUT_KEY));
404
	 */
405
	}
405
	public TaskExecutor getTaskExecutor() {
406
406
		synchronized (lock) {
407
	private boolean getProcessAnnotations(Properties properties) {
407
			return taskExecutor;
408
		return Boolean.valueOf(properties.getProperty(PROCESS_ANNOTATIONS_KEY)).booleanValue()
408
		}
409
				|| Boolean.getBoolean(AUTO_ANNOTATION_PROCESSING);
409
	}
410
	}
410
411
411
	/**
412
	/**
412
	 * Returns the shutdown task executor.
413
	 * Returns the taskExecutor.
413
	 * 
414
	 * 
414
	 * @return Returns the shutdown task executor
415
	 * @return Returns the taskExecutor
415
	 */
416
	 */
416
	public TaskExecutor getShutdownTaskExecutor() {
417
	public TaskExecutor getTaskExecutor() {
417
		synchronized (lock) {
418
		synchronized (lock) {
418
			return shutdownTaskExecutor;
419
			return taskExecutor;
419
		}
420
		}
420
	}
421
	}
421
422
422
	/**
423
	/**
423
	 * Returns the contextEventListener.
424
	 * Returns the shutdown task executor.
424
	 * 
425
	 * 
425
	 * @return Returns the contextEventListener
426
	 * @return Returns the shutdown task executor
426
	 */
427
	 */
427
	public OsgiBundleApplicationContextListener getContextEventListener() {
428
	public TaskExecutor getShutdownTaskExecutor() {
428
		synchronized (lock) {
429
		synchronized (lock) {
429
			return contextEventListener;
430
			return shutdownTaskExecutor;
430
		}
431
		}
431
	}
432
	}
432
433
433
	/**
434
	/**
434
	 * Returns the shutdownWaitTime.
435
	 * Returns the contextEventListener.
435
	 * 
436
	 * 
436
	 * @return Returns the shutdownWaitTime
437
	 * @return Returns the contextEventListener
437
	 */
438
	 */
438
	public long getShutdownWaitTime() {
439
	public OsgiBundleApplicationContextListener getContextEventListener() {
439
		synchronized (lock) {
440
		synchronized (lock) {
440
			return shutdownWaitTime;
441
			return contextEventListener;
441
		}
442
		}
442
	}
443
	}
443
444
444
	/**
445
	/**
445
	 * Indicates if the process annotation is enabled or not.
446
	 * Returns the shutdownWaitTime.
446
	 * 
447
	 * 
447
	 * @return Returns true if the annotation should be processed or not otherwise.
448
	 * @return Returns the shutdownWaitTime
448
	 */
449
	 */
449
	public boolean shouldProcessAnnotation() {
450
	public long getShutdownWaitTime() {
450
		synchronized (lock) {
451
		synchronized (lock) {
451
			return processAnnotation;
452
			return shutdownWaitTime;
452
		}
453
		}
453
	}
454
	}
454
455
455
	/**
456
	/**
456
	 * Returns the dependencyWaitTime.
457
	 * Indicates if the process annotation is enabled or not.
457
	 * 
458
	 * 
458
	 * @return Returns the dependencyWaitTime
459
	 * @return Returns true if the annotation should be processed or not otherwise.
459
	 */
460
	 */
460
	public long getDependencyWaitTime() {
461
	public boolean shouldProcessAnnotation() {
461
		synchronized (lock) {
462
		synchronized (lock) {
462
			return dependencyWaitTime;
463
			return processAnnotation;
463
		}
464
		}
464
	}
465
	}
465
466
466
	/**
467
	/**
467
	 * Returns the eventMulticaster.
468
	 * Returns the dependencyWaitTime.
468
	 * 
469
	 * 
469
	 * @return Returns the eventMulticaster
470
	 * @return Returns the dependencyWaitTime
470
	 */
471
	 */
471
	public OsgiBundleApplicationContextEventMulticaster getEventMulticaster() {
472
	public long getDependencyWaitTime() {
472
		synchronized (lock) {
473
		synchronized (lock) {
473
			return eventMulticaster;
474
			return dependencyWaitTime;
474
		}
475
		}
475
	}
476
	}
476
477
477
	/**
478
	/**
478
	 * Sets the flag to force the taskExtender to close up in case of runaway threads - this applies *only* if the
479
	 * Returns the eventMulticaster.
479
	 * taskExecutor has been created internally.
480
	 * 
480
	 * 
481
	 * @return Returns the eventMulticaster
481
	 * <p/> The flag will cause a best attempt to shutdown the threads.
482
	 */
482
	 * 
483
	public OsgiBundleApplicationContextEventMulticaster getEventMulticaster() {
483
	 * @param forceThreadShutdown The forceThreadShutdown to set.
484
		synchronized (lock) {
484
	 */
485
			return eventMulticaster;
485
	public void setForceThreadShutdown(boolean forceThreadShutdown) {
486
		}
486
		synchronized (lock) {
487
	}
487
			this.forceThreadShutdown = forceThreadShutdown;
488
488
		}
489
	/**
489
	}
490
	 * Sets the flag to force the taskExtender to close up in case of runaway threads - this applies *only* if the
490
491
	 * taskExecutor has been created internally.
491
	/**
492
	 * 
492
	 * Returns the contextCreator.
493
	 * <p/> The flag will cause a best attempt to shutdown the threads.
493
	 * 
494
	 * 
494
	 * @return Returns the contextCreator
495
	 * @param forceThreadShutdown The forceThreadShutdown to set.
495
	 */
496
	 */
496
	public OsgiApplicationContextCreator getContextCreator() {
497
	public void setForceThreadShutdown(boolean forceThreadShutdown) {
497
		synchronized (lock) {
498
		synchronized (lock) {
498
			return contextCreator;
499
			this.forceThreadShutdown = forceThreadShutdown;
499
		}
500
		}
500
	}
501
	}
501
502
502
	/**
503
	/**
503
	 * Returns the postProcessors.
504
	 * Returns the contextCreator.
504
	 * 
505
	 * 
505
	 * @return Returns the postProcessors
506
	 * @return Returns the contextCreator
506
	 */
507
	 */
507
	public List<OsgiBeanFactoryPostProcessor> getPostProcessors() {
508
	public OsgiApplicationContextCreator getContextCreator() {
508
		return postProcessors;
509
		synchronized (lock) {
509
	}
510
			return contextCreator;
510
511
		}
511
	/**
512
	}
512
	 * Returns the class loader wrapped around the extender bundle.
513
513
	 * 
514
	/**
514
	 * @return extender bundle class loader
515
	 * Returns the postProcessors.
515
	 */
516
	 * 
516
	public ClassLoader getClassLoader() {
517
	 * @return Returns the postProcessors
517
		return classLoader;
518
	 */
518
	}
519
	public List<OsgiBeanFactoryPostProcessor> getPostProcessors() {
519
520
		return postProcessors;
520
	/**
521
	}
521
	 * Returns the dependencies factories declared by the extender configuration. The list automatically contains the
522
522
	 * default listeners (such as the annotation one).
523
	/**
523
	 * 
524
	 * Returns the class loader wrapped around the extender bundle.
524
	 * @return list of dependency factories
525
	 * 
525
	 */
526
	 * @return extender bundle class loader
526
	public List<OsgiServiceDependencyFactory> getDependencyFactories() {
527
	 */
527
		return dependencyFactories;
528
	public ClassLoader getClassLoader() {
528
	}
529
		return classLoader;
530
	}
531
532
	/**
533
	 * Returns the dependencies factories declared by the extender configuration. The list automatically contains the
534
	 * default listeners (such as the annotation one).
535
	 * 
536
	 * @return list of dependency factories
537
	 */
538
	public List<OsgiServiceDependencyFactory> getDependencyFactories() {
539
		return dependencyFactories;
540
	}
541
}
529
}
(-)a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/ContextLoaderListenerTest.java (-25 / +26 lines)
Lines 1-17 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc.
2
 * Copyright (c) 2006, 2010 VMware Inc.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution. 
5
 * and Apache License v2.0 which accompanies this distribution. 
6
 * The Eclipse Public License is available at 
6
 * The Eclipse Public License is available at 
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
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.
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. 
9
 * You may elect to redistribute this code under either of these licenses. 
10
 * 
10
 * 
11
 * Contributors:
11
 * Contributors:
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;
Lines 21-33 import java.util.Properties; Link Here
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.TestTaskExecutor;
25
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
26
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
26
import org.eclipse.gemini.blueprint.extender.internal.support.TestTaskExecutor;
27
import org.eclipse.gemini.blueprint.mock.EntryLookupControllingMockBundle;
27
import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;
28
import org.eclipse.gemini.blueprint.mock.MockBundle;
28
import org.eclipse.gemini.blueprint.mock.EntryLookupControllingMockBundle;
29
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
29
import org.eclipse.gemini.blueprint.mock.MockBundle;
30
import org.eclipse.gemini.blueprint.mock.MockServiceRegistration;
30
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
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;
Lines 40-52 import org.springframework.core.io.ClassPathResource; 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 {
(-)a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationCustomSettingsTest.java (-104 / +102 lines)
Lines 1-105 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc.
2
 * Copyright (c) 2006, 2010 VMware Inc.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution. 
5
 * and Apache License v2.0 which accompanies this distribution. 
6
 * The Eclipse Public License is available at 
6
 * The Eclipse Public License is available at 
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
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.
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. 
9
 * You may elect to redistribute this code under either of these licenses. 
10
 * 
10
 * 
11
 * Contributors:
11
 * Contributors:
12
 *   VMware Inc.
12
 *   VMware Inc.
13
 *****************************************************************************/
13
 *****************************************************************************/
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;
17
import junit.framework.TestCase;
18
import java.util.Enumeration;
18
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;
19
import java.util.List;
19
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;
20
20
import org.eclipse.gemini.blueprint.mock.ArrayEnumerator;
21
import junit.framework.TestCase;
21
import org.eclipse.gemini.blueprint.mock.MockBundle;
22
22
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
23
import org.apache.commons.logging.LogFactory;
23
import org.osgi.framework.Bundle;
24
import org.osgi.framework.Bundle;
24
import org.osgi.framework.BundleContext;
25
import org.osgi.framework.BundleContext;
25
import org.springframework.core.task.SimpleAsyncTaskExecutor;
26
import org.springframework.core.task.SimpleAsyncTaskExecutor;
26
import org.springframework.core.task.TaskExecutor;
27
import org.springframework.core.task.TaskExecutor;
27
28
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;
28
import java.net.URL;
29
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;
29
import java.util.Enumeration;
30
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
30
import java.util.List;
31
import org.eclipse.gemini.blueprint.mock.ArrayEnumerator;
31
32
import org.eclipse.gemini.blueprint.mock.MockBundle;
32
/**
33
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
33
 * @author Costin Leau
34
34
 */
35
/**
35
public class ExtenderConfigurationCustomSettingsTest extends TestCase {
36
 * @author Costin Leau
36
37
 */
37
	private ExtenderConfiguration config;
38
public class ExtenderConfigurationCustomSettingsTest extends TestCase {
38
	private BundleContext bundleContext;
39
39
	private Bundle bundle;
40
	private ExtenderConfiguration config;
40
41
	private BundleContext bundleContext;
41
	protected void setUp() throws Exception {
42
	private Bundle bundle;
42
		bundle = new MockBundle() {
43
43
44
	protected void setUp() throws Exception {
44
			public Enumeration findEntries(String path, String filePattern, boolean recurse) {
45
		bundle = new MockBundle() {
45
				return new ArrayEnumerator(new URL[] { getClass().getResource(
46
46
						"/org/eclipse/gemini/blueprint/extender/internal/support/extender-custom-config.xml") });
47
			public Enumeration findEntries(String path, String filePattern, boolean recurse) {
47
			}
48
				return new ArrayEnumerator(new URL[] { getClass().getResource(
48
		};
49
						"/org/eclipse/gemini/blueprint/extender/internal/support/extender-custom-config.xml") });
49
50
			}
50
		bundleContext = new MockBundleContext(bundle);
51
		};
51
		config = new ExtenderConfiguration();
52
52
        config.start(this.bundleContext);
53
		bundleContext = new MockBundleContext(bundle);
53
	}
54
		config = new ExtenderConfiguration(bundleContext, LogFactory.getLog(ExtenderConfiguration.class));
54
55
	}
55
	protected void tearDown() throws Exception {
56
56
		config.stop(this.bundleContext);
57
	protected void tearDown() throws Exception {
57
		config = null;
58
		config.destroy();
58
	}
59
		config = null;
59
60
	}
60
	public void testTaskExecutor() throws Exception {
61
61
		assertTrue(config.getTaskExecutor() instanceof SimpleAsyncTaskExecutor);
62
	public void testTaskExecutor() throws Exception {
62
		assertEquals("conf-extender-thread", ((SimpleAsyncTaskExecutor) config.getTaskExecutor()).getThreadNamePrefix());
63
		assertTrue(config.getTaskExecutor() instanceof SimpleAsyncTaskExecutor);
63
	}
64
		assertEquals("conf-extender-thread", ((SimpleAsyncTaskExecutor) config.getTaskExecutor()).getThreadNamePrefix());
64
65
	}
65
	public void testShutdownTaskExecutor() throws Exception {
66
66
		TaskExecutor executor = config.getShutdownTaskExecutor();
67
	public void testShutdownTaskExecutor() throws Exception {
67
		assertTrue(executor instanceof SimpleAsyncTaskExecutor);
68
		TaskExecutor executor = config.getShutdownTaskExecutor();
68
	}
69
		assertTrue(executor instanceof SimpleAsyncTaskExecutor);
69
70
	}
70
	public void testEventMulticaster() throws Exception {
71
71
		assertTrue(config.getEventMulticaster() instanceof OsgiBundleApplicationContextEventMulticasterAdapter);
72
	public void testEventMulticaster() throws Exception {
72
	}
73
		assertTrue(config.getEventMulticaster() instanceof OsgiBundleApplicationContextEventMulticasterAdapter);
73
74
	}
74
	public void testApplicationContextCreator() throws Exception {
75
75
		assertTrue(config.getContextCreator() instanceof DummyContextCreator);
76
	public void testApplicationContextCreator() throws Exception {
76
	}
77
		assertTrue(config.getContextCreator() instanceof DummyContextCreator);
77
78
	}
78
	public void testShutdownWaitTime() throws Exception {
79
79
		// 300 ms
80
	public void testShutdownWaitTime() throws Exception {
80
		assertEquals(300, config.getShutdownWaitTime());
81
		// 300 ms
81
	}
82
		assertEquals(300, config.getShutdownWaitTime());
82
83
	}
83
	public void testShouldProcessAnnotation() throws Exception {
84
84
		assertTrue(config.shouldProcessAnnotation());
85
	public void testShouldProcessAnnotation() throws Exception {
85
	}
86
		assertTrue(config.shouldProcessAnnotation());
86
87
	}
87
	public void testDependencyWaitTime() throws Exception {
88
88
		// 200 ms
89
	public void testDependencyWaitTime() throws Exception {
89
		assertEquals(200, config.getDependencyWaitTime());
90
		// 200 ms
90
	}
91
		assertEquals(200, config.getDependencyWaitTime());
91
92
	}
92
	public void testPostProcessors() throws Exception {
93
93
		List postProcessors = config.getPostProcessors();
94
	public void testPostProcessors() throws Exception {
94
		assertEquals(1, postProcessors.size());
95
		List postProcessors = config.getPostProcessors();
95
		assertTrue(postProcessors.get(0) instanceof DummyProcessor);
96
		assertEquals(1, postProcessors.size());
96
	}
97
		assertTrue(postProcessors.get(0) instanceof DummyProcessor);
97
98
	}
98
	public void testDependencyFactories() throws Exception {
99
99
		List factories = config.getDependencyFactories();
100
	public void testDependencyFactories() throws Exception {
100
		assertEquals("wrong number of dependencies factories registered by default", 1, factories.size());
101
		List factories = config.getDependencyFactories();
101
		assertTrue(factories.get(0) instanceof MandatoryImporterDependencyFactory);
102
		assertEquals("wrong number of dependencies factories registered by default", 1, factories.size());
102
	}
103
		assertTrue(factories.get(0) instanceof MandatoryImporterDependencyFactory);
104
	}
105
}
103
}
(-)a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationDefaultSettingsTest.java (-91 / +87 lines)
Lines 1-91 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc.
2
 * Copyright (c) 2006, 2010 VMware Inc.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution. 
5
 * and Apache License v2.0 which accompanies this distribution. 
6
 * The Eclipse Public License is available at 
6
 * The Eclipse Public License is available at 
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
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.
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. 
9
 * You may elect to redistribute this code under either of these licenses. 
10
 * 
10
 * 
11
 * Contributors:
11
 * Contributors:
12
 *   VMware Inc.
12
 *   VMware Inc.
13
 *****************************************************************************/
13
 *****************************************************************************/
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;
17
import junit.framework.TestCase;
18
18
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;
19
import junit.framework.TestCase;
19
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;
20
20
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
21
import org.apache.commons.logging.LogFactory;
21
import org.osgi.framework.BundleContext;
22
import org.osgi.framework.BundleContext;
22
import org.springframework.core.task.SimpleAsyncTaskExecutor;
23
import org.springframework.core.task.SimpleAsyncTaskExecutor;
23
import org.springframework.core.task.TaskExecutor;
24
import org.springframework.core.task.TaskExecutor;
24
import org.springframework.scheduling.timer.TimerTaskExecutor;
25
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;
25
26
import org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;
26
import java.util.List;
27
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
27
28
import org.eclipse.gemini.blueprint.extender.support.DefaultOsgiApplicationContextCreator;
28
/**
29
import org.eclipse.gemini.blueprint.mock.MockBundleContext;
29
 * @author Costin Leau
30
import org.springframework.scheduling.timer.TimerTaskExecutor;
30
 */
31
31
public class ExtenderConfigurationDefaultSettingsTest extends TestCase {
32
/**
32
33
 * @author Costin Leau
33
	private ExtenderConfiguration config;
34
 */
34
	private BundleContext bundleContext;
35
public class ExtenderConfigurationDefaultSettingsTest extends TestCase {
35
36
36
	protected void setUp() throws Exception {
37
	private ExtenderConfiguration config;
37
		bundleContext = new MockBundleContext();
38
	private BundleContext bundleContext;
38
		config = new ExtenderConfiguration();
39
39
        this.config.start(this.bundleContext);
40
	protected void setUp() throws Exception {
40
	}
41
		bundleContext = new MockBundleContext();
41
42
		config = new ExtenderConfiguration(bundleContext, LogFactory.getLog(ExtenderConfiguration.class));
42
	protected void tearDown() throws Exception {
43
	}
43
		config.start(this.bundleContext);
44
44
		config = null;
45
	protected void tearDown() throws Exception {
45
	}
46
		config.destroy();
46
47
		config = null;
47
	public void testTaskExecutor() throws Exception {
48
	}
48
		assertTrue(config.getTaskExecutor() instanceof SimpleAsyncTaskExecutor);
49
49
	}
50
	public void testTaskExecutor() throws Exception {
50
51
		assertTrue(config.getTaskExecutor() instanceof SimpleAsyncTaskExecutor);
51
	public void testShutdownTaskExecutor() throws Exception {
52
	}
52
		TaskExecutor executor = config.getShutdownTaskExecutor();
53
53
		assertTrue(executor instanceof TimerTaskExecutor);
54
	public void testShutdownTaskExecutor() throws Exception {
54
	}
55
		TaskExecutor executor = config.getShutdownTaskExecutor();
55
56
		assertTrue(executor instanceof TimerTaskExecutor);
56
	public void testEventMulticaster() throws Exception {
57
	}
57
		assertTrue(config.getEventMulticaster() instanceof OsgiBundleApplicationContextEventMulticasterAdapter);
58
58
	}
59
	public void testEventMulticaster() throws Exception {
59
60
		assertTrue(config.getEventMulticaster() instanceof OsgiBundleApplicationContextEventMulticasterAdapter);
60
	public void testApplicationContextCreator() throws Exception {
61
	}
61
        assertNull(config.getContextCreator());
62
62
	}
63
	public void testApplicationContextCreator() throws Exception {
63
64
		assertTrue(config.getContextCreator() instanceof DefaultOsgiApplicationContextCreator);
64
	public void testShutdownWaitTime() throws Exception {
65
	}
65
		// 10 seconds in ms
66
66
		assertEquals(10 * 1000, config.getShutdownWaitTime());
67
	public void testShutdownWaitTime() throws Exception {
67
	}
68
		// 10 seconds in ms
68
69
		assertEquals(10 * 1000, config.getShutdownWaitTime());
69
	public void testShouldProcessAnnotation() throws Exception {
70
	}
70
		assertFalse(config.shouldProcessAnnotation());
71
71
	}
72
	public void testShouldProcessAnnotation() throws Exception {
72
73
		assertFalse(config.shouldProcessAnnotation());
73
	public void testDependencyWaitTime() throws Exception {
74
	}
74
		// 5 minutes in ms
75
75
		assertEquals(5 * 60 * 1000, config.getDependencyWaitTime());
76
	public void testDependencyWaitTime() throws Exception {
76
	}
77
		// 5 minutes in ms
77
78
		assertEquals(5 * 60 * 1000, config.getDependencyWaitTime());
78
	public void testPostProcessors() throws Exception {
79
	}
79
		List postProcessors = config.getPostProcessors();
80
80
		assertTrue(postProcessors.isEmpty());
81
	public void testPostProcessors() throws Exception {
81
	}
82
		List postProcessors = config.getPostProcessors();
82
83
		assertTrue(postProcessors.isEmpty());
83
	public void testDependencyFactories() throws Exception {
84
	}
84
		List factories = config.getDependencyFactories();
85
85
		assertEquals("wrong number of dependencies factories registered by default", 1, factories.size());
86
	public void testDependencyFactories() throws Exception {
86
		assertTrue(factories.get(0) instanceof MandatoryImporterDependencyFactory);
87
		List factories = config.getDependencyFactories();
87
	}
88
		assertEquals("wrong number of dependencies factories registered by default", 1, factories.size());
89
		assertTrue(factories.get(0) instanceof MandatoryImporterDependencyFactory);
90
	}
91
}
88
}
92
- 

Return to bug 356683