Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 223184 Details for
Bug 356683
Construct application contexts defined in extender fragments only once and share across extender instances
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
Decomposed ContextLoaderListener with singleton configuration for 356683
356683__Separate_staged_configuration_and_listeners.patch (text/plain), 128.13 KB, created by
Olaf Otto
on 2012-11-05 10:49:23 EST
(
hide
)
Description:
Decomposed ContextLoaderListener with singleton configuration for 356683
Filename:
MIME Type:
Creator:
Olaf Otto
Created:
2012-11-05 10:49:23 EST
Size:
128.13 KB
patch
obsolete
>Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintExtenderConfiguration.java >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintExtenderConfiguration.java (date 1346404121000) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/support/BlueprintExtenderConfiguration.java (date 1346404121000) >@@ -1,44 +0,0 @@ >-/****************************************************************************** >- * Copyright (c) 2006, 2010 VMware Inc. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * and Apache License v2.0 which accompanies this distribution. >- * The Eclipse Public License is available at >- * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0 >- * is available at http://www.opensource.org/licenses/apache2.0.php. >- * You may elect to redistribute this code under either of these licenses. >- * >- * Contributors: >- * VMware Inc. >- *****************************************************************************/ >- >-package org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support; >- >-import org.apache.commons.logging.Log; >-import org.eclipse.gemini.blueprint.extender.OsgiApplicationContextCreator; >-import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration; >-import org.osgi.framework.BundleContext; >- >-/** >- * Extension of the default extender configuration for handling RFC 124 extender semantics. >- * >- * @author Costin Leau >- * >- */ >-public class BlueprintExtenderConfiguration extends ExtenderConfiguration { >- >- private final OsgiApplicationContextCreator contextCreator = new BlueprintContainerCreator(); >- >- /** >- * Constructs a new <code>BlueprintExtenderConfiguration</code> instance. >- * >- * @param bundleContext >- */ >- public BlueprintExtenderConfiguration(BundleContext bundleContext, Log log) { >- super(bundleContext, log); >- } >- >- public OsgiApplicationContextCreator getContextCreator() { >- return contextCreator; >- } >-} >Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ContextLoaderListener.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP ><+>/******************************************************************************\r\n * Copyright (c) 2006, 2010 VMware Inc., Oracle Inc.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * and Apache License v2.0 which accompanies this distribution. \r\n * The Eclipse Public License is available at \r\n * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0\r\n * is available at http://www.opensource.org/licenses/apache2.0.php.\r\n * You may elect to redistribute this code under either of these licenses. \r\n * \r\n * Contributors:\r\n * VMware Inc.\r\n * Oracle Inc.\r\n *****************************************************************************/\r\n\r\npackage org.eclipse.gemini.blueprint.extender.internal.activator;\r\n\r\nimport java.util.Map;\r\nimport java.util.WeakHashMap;\r\n\r\nimport org.apache.commons.logging.Log;\r\nimport org.apache.commons.logging.LogFactory;\r\nimport org.osgi.framework.Bundle;\r\nimport org.osgi.framework.BundleActivator;\r\nimport org.osgi.framework.BundleContext;\r\nimport org.osgi.framework.BundleEvent;\r\nimport org.osgi.framework.SynchronousBundleListener;\r\nimport org.osgi.framework.Version;\r\nimport org.springframework.beans.BeanUtils;\r\nimport org.springframework.beans.CachedIntrospectionResults;\r\nimport org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;\r\nimport org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;\r\nimport org.eclipse.gemini.blueprint.extender.internal.support.NamespaceManager;\r\nimport org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;\r\nimport org.eclipse.gemini.blueprint.service.exporter.support.OsgiServiceFactoryBean;\r\nimport org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceCollectionProxyFactoryBean;\r\nimport org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceProxyFactoryBean;\r\nimport org.eclipse.gemini.blueprint.util.OsgiBundleUtils;\r\nimport org.eclipse.gemini.blueprint.util.OsgiStringUtils;\r\n\r\n/**\r\n * Osgi Extender that bootstraps 'Spring powered bundles'.\r\n * \r\n * <p/> The class listens to bundle events and manages the creation and destruction of application contexts for bundles\r\n * that have one or both of: <ul> <li>A manifest header entry Spring-Context <li>XML files in META-INF/spring folder\r\n * </ul>\r\n * \r\n * <p/> The extender also discovers any Spring namespace/schema handlers in resolved bundles and makes them available\r\n * through a dedicated OSGi service.\r\n * \r\n * <p/> The extender behaviour can be customized by attaching fragments to the extender bundle. On startup, the extender\r\n * will look for <code>META-INF/spring/*.xml</code> files and merge them into an application context. From the resulting\r\n * context, the context will look for beans with predefined names to determine its configuration. The current version\r\n * recognises the following bean names:\r\n * \r\n * <table border=\"1\"> <tr> <th>Bean Name</th> <th>Bean Type</th> <th>Description</th> </tr> <tr>\r\n * <td><code>taskExecutor</code></td> <td><code>org.springframework.core.task.TaskExecutor</code></td> <td>Task executor\r\n * used for creating the discovered application contexts.</td> </tr> <tr> <td><code>shutdownTaskExecutor</code></td>\r\n * <td><code>org.springframework.core.task.TaskExecutor</code></td> <td>Task executor used for shutting down various\r\n * application contexts.</td> </tr> <tr> <td><code>extenderProperties</code></td>\r\n * <td><code>java.util.Properties</code></td> <td>Various properties for configuring the extender behaviour (see\r\n * below)</td> </tr> </table>\r\n * \r\n * <p/> <code>extenderProperties</code> recognises the following properties:\r\n * \r\n * <table border=\"1\"> <tr> <th>Name</th> <th>Type</th> <th>Description</th> </tr> <tr>\r\n * <td><code>shutdown.wait.time</code></td> <td>Number</td> <td>The amount of time the extender will wait for each\r\n * application context to shutdown gracefully. Expressed in milliseconds.</td> </tr> <tr>\r\n * <td><code>process.annotations</code></td> <td>Boolean</td> <td>Whether or not, the extender will process SpringOSGi\r\n * annotations.</td> </tr> </table>\r\n * \r\n * <p/> Note: The extender configuration context is created during the bundle activation (a synchronous OSGi lifecycle\r\n * callback) and should contain only simple bean definitions that will not delay context initialisation. </p>\r\n * \r\n * @author Bill Gallagher\r\n * @author Andy Piper\r\n * @author Hal Hildebrand\r\n * @author Adrian Colyer\r\n * @author Costin Leau\r\n */\r\npublic class ContextLoaderListener implements BundleActivator {\r\n\r\n\t/**\r\n\t * Common base class for {@link ContextLoaderListener} listeners.\r\n\t * \r\n\t * @author Costin Leau\r\n\t */\r\n\tprivate abstract class BaseListener implements SynchronousBundleListener {\r\n\r\n\t\tstatic final int LAZY_ACTIVATION_EVENT_TYPE = 0x00000200;\r\n\r\n\t\tprotected final Log log = LogFactory.getLog(getClass());\r\n\r\n\t\t/**\r\n\t\t * common cache used for tracking down bundles started lazily so they don't get processed twice (once when\r\n\t\t * started lazy, once when started fully)\r\n\t\t */\r\n\t\tprotected Map<Bundle, Object> lazyBundleCache = new WeakHashMap<Bundle, Object>();\r\n\t\t/** dummy value for the bundle cache */\r\n\t\tprivate final Object VALUE = new Object();\r\n\r\n\t\t// caches the bundle\n\t\tprotected void push(Bundle bundle) {\r\n\t\t\tsynchronized (lazyBundleCache) {\r\n\t\t\t\tlazyBundleCache.put(bundle, VALUE);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// checks the presence of the bundle as well as removing it\n\t\tprotected boolean pop(Bundle bundle) {\r\n\t\t\tsynchronized (lazyBundleCache) {\r\n\t\t\t\treturn (lazyBundleCache.remove(bundle) != null);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * A bundle has been started, stopped, resolved, or unresolved. This method is a synchronous callback, do not do\r\n\t\t * any long-running work in this thread.\r\n\t\t * \r\n\t\t * @see org.osgi.framework.SynchronousBundleListener#bundleChanged\r\n\t\t */\r\n\t\tpublic void bundleChanged(BundleEvent event) {\r\n\r\n\t\t\tboolean trace = log.isTraceEnabled();\r\n\r\n\t\t\t// check if the listener is still alive\n\t\t\tif (isClosed) {\r\n\t\t\t\tif (trace)\r\n\t\t\t\t\tlog.trace(\"Listener is closed; events are being ignored\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tif (trace) {\r\n\t\t\t\tlog.trace(\"Processing bundle event [\" + OsgiStringUtils.nullSafeToString(event) + \"] for bundle [\"\r\n\t\t\t\t\t\t+ OsgiStringUtils.nullSafeSymbolicName(event.getBundle()) + \"]\");\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\thandleEvent(event);\r\n\t\t\t} catch (Exception ex) {\r\n\t\t\t\t/* log exceptions before swallowing */\r\n\t\t\t\tlog.warn(\"Got exception while handling event \" + event, ex);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tprotected abstract void handleEvent(BundleEvent event);\r\n\t}\r\n\r\n\t/**\r\n\t * Bundle listener used for detecting namespace handler/resolvers. Exists as a separate listener so that it can be\r\n\t * registered early to avoid race conditions with bundles in INSTALLING state but still to avoid premature context\r\n\t * creation before the Spring {@link ContextLoaderListener} is not fully initialized.\r\n\t * \r\n\t * @author Costin Leau\r\n\t */\r\n\tprivate class NamespaceBundleLister extends BaseListener {\r\n\r\n\t\tprivate final boolean resolved;\r\n\r\n\t\tNamespaceBundleLister(boolean resolvedBundles) {\r\n\t\t\tthis.resolved = resolvedBundles;\r\n\t\t}\r\n\r\n\t\tprotected void handleEvent(BundleEvent event) {\r\n\t\t\tBundle bundle = event.getBundle();\r\n\r\n\t\t\tswitch (event.getType()) {\r\n\r\n\t\t\tcase BundleEvent.RESOLVED:\r\n\t\t\t\tif (resolved) {\r\n\t\t\t\t\tmaybeAddNamespaceHandlerFor(bundle, false);\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase LAZY_ACTIVATION_EVENT_TYPE: {\r\n\t\t\t\tif (!resolved) {\r\n\t\t\t\t\tpush(bundle);\r\n\t\t\t\t\tmaybeAddNamespaceHandlerFor(bundle, true);\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase BundleEvent.STARTED: {\r\n\t\t\t\tif (!resolved) {\r\n\t\t\t\t\tif (!pop(bundle)) {\r\n\t\t\t\t\t\tmaybeAddNamespaceHandlerFor(bundle, false);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase BundleEvent.STOPPED: {\r\n\t\t\t\tpop(bundle);\r\n\t\t\t\tmaybeRemoveNameSpaceHandlerFor(bundle);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Bundle listener used for context creation/destruction.\r\n\t */\r\n\tprivate class ContextBundleListener extends BaseListener {\r\n\r\n\t\tprotected void handleEvent(BundleEvent event) {\r\n\r\n\t\t\tBundle bundle = event.getBundle();\r\n\r\n\t\t\t// ignore current bundle for context creation\n\t\t\tif (bundle.getBundleId() == bundleId) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tswitch (event.getType()) {\r\n\t\t\tcase LAZY_ACTIVATION_EVENT_TYPE: {\r\n\t\t\t\t// activate bundle\n\t\t\t\ttry {\r\n\t\t\t\t\tbundle.loadClass(\"org.osgi.service.blueprint.container.BlueprintContainer\");\r\n\t\t\t\t} catch (Exception ex) {\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase BundleEvent.STARTED: {\r\n\t\t\t\tlifecycleManager.maybeCreateApplicationContextFor(bundle);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase BundleEvent.STOPPING: {\r\n\t\t\t\tif (OsgiBundleUtils.isSystemBundle(bundle)) {\r\n\t\t\t\t\tif (log.isDebugEnabled()) {\r\n\t\t\t\t\t\tlog.debug(\"System bundle stopping\");\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// System bundle is shutting down; Special handling for\n\t\t\t\t\t// framework shutdown\n\t\t\t\t\tshutdown();\r\n\t\t\t\t} else {\r\n\t\t\t\t\tlifecycleManager.maybeCloseApplicationContextFor(bundle);\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprotected final Log log = LogFactory.getLog(getClass());\r\n\r\n\t/** extender bundle id */\r\n\tprivate long bundleId;\r\n\r\n\t/** extender configuration */\r\n\tprivate ExtenderConfiguration extenderConfiguration;\r\n\r\n\t/** Spring namespace/resolver manager */\r\n\tprivate NamespaceManager nsManager;\r\n\r\n\t/** The bundle's context */\r\n\tprivate BundleContext bundleContext;\r\n\r\n\t/** Bundle listener interested in context creation */\r\n\tprivate SynchronousBundleListener contextListener;\r\n\r\n\t/** Bundle listener interested in namespace resolvers/parsers discovery */\r\n\tprivate SynchronousBundleListener nsListener;\r\n\r\n\t/**\r\n\t * Monitor used for dealing with the bundle activator and synchronous bundle threads\r\n\t */\r\n\tprivate final Object monitor = new Object();\r\n\r\n\t/**\r\n\t * flag indicating whether the context is down or not - useful during shutdown\r\n\t */\r\n\tprivate volatile boolean isClosed = false;\r\n\r\n\t/** This extender version */\r\n\tprivate Version extenderVersion;\r\n\r\n\tprivate volatile OsgiBundleApplicationContextEventMulticaster multicaster;\r\n\r\n\tprivate volatile LifecycleManager lifecycleManager;\r\n\tprivate volatile VersionMatcher versionMatcher;\r\n\tprivate volatile OsgiContextProcessor processor;\r\n\tprivate volatile ListListenerAdapter osgiListeners;\r\n\r\n\t/**\r\n\t * <p/> Called by OSGi when this bundle is started. Finds all previously resolved bundles and adds namespace\r\n\t * handlers for them if necessary. </p> <p/> Creates application contexts for bundles started before the extender\r\n\t * was started. </p> <p/> Registers a namespace/entity resolving service for use by web app contexts. </p>\r\n\t * \r\n\t * @see org.osgi.framework.BundleActivator#start\r\n\t */\r\n\tpublic void start(BundleContext context) throws Exception {\r\n\r\n\t\tthis.bundleContext = context;\r\n\t\tthis.bundleId = context.getBundle().getBundleId();\r\n\r\n\t\tthis.extenderVersion = OsgiBundleUtils.getBundleVersion(context.getBundle());\r\n\t\tlog.info(\"Starting [\" + bundleContext.getBundle().getSymbolicName() + \"] bundle v.[\" + extenderVersion + \"]\");\r\n\t\tversionMatcher = new DefaultVersionMatcher(getManagedBundleExtenderVersionHeader(), extenderVersion);\r\n\t\tprocessor = createContextProcessor();\r\n\r\n\t\t// init cache (to prevent ad-hoc Java Bean discovery on lazy bundles)\n\t\tinitJavaBeansCache();\r\n\r\n\t\t// Step 1 : discover existing namespaces (in case there are fragments with custom XML definitions)\n\t\tnsManager = new NamespaceManager(context);\r\n\t\tinitNamespaceHandlers(bundleContext);\r\n\r\n\t\t// Step 2: initialize the extender configuration\n\t\textenderConfiguration = initExtenderConfiguration(bundleContext);\r\n\r\n\t\t// init the OSGi event dispatch/listening system\n\t\tinitListenerService();\r\n\r\n\t\t// initialize the configuration once namespace handlers have been detected\n\t\tlifecycleManager =\r\n\t\t\t\tnew LifecycleManager(extenderConfiguration, versionMatcher, createContextConfigFactory(),\r\n\t\t\t\t\t\tthis.processor, getTypeCompatibilityChecker(), bundleContext);\r\n\r\n\t\t// Step 3: discover the bundles that are started\n\t\t// and require context creation\n\t\tinitStartedBundles(bundleContext);\r\n\t}\r\n\r\n\tprotected ExtenderConfiguration initExtenderConfiguration(BundleContext bundleContext) {\r\n\t\treturn new ExtenderConfiguration(bundleContext, log);\r\n\t}\r\n\r\n\tprotected OsgiContextProcessor createContextProcessor() {\r\n\t\treturn new NoOpOsgiContextProcessor();\r\n\t}\r\n\r\n\tprotected TypeCompatibilityChecker getTypeCompatibilityChecker() {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tprotected String getManagedBundleExtenderVersionHeader() {\r\n\t\treturn ConfigUtils.EXTENDER_VERSION;\r\n\t}\r\n\r\n\tprotected void initNamespaceHandlers(BundleContext context) {\r\n\t\tnsManager = new NamespaceManager(context);\r\n\r\n\t\t// register listener first to make sure any bundles in INSTALLED state\n\t\t// are not lost\r\n\t\t\r\n\t\t// if the property is defined and true, consider bundles in STARTED/LAZY-INIT state, otherwise use RESOLVED\r\n\t\tboolean nsResolved = !Boolean.getBoolean(\"org.eclipse.gemini.blueprint.ns.bundles.started\");\n\t\tnsListener = new NamespaceBundleLister(nsResolved);\r\n\t\tcontext.addBundleListener(nsListener);\r\n\r\n\t\tBundle[] previousBundles = context.getBundles();\r\n\r\n\t\tfor (Bundle bundle : previousBundles) {\r\n\t\t\t// special handling for uber bundle being restarted\n\t\t\tif ((nsResolved && OsgiBundleUtils.isBundleResolved(bundle)) || (!nsResolved && OsgiBundleUtils.isBundleActive(bundle)) || bundleId == bundle.getBundleId()) {\r\n\t\t\t\tmaybeAddNamespaceHandlerFor(bundle, false);\r\n\t\t\t} else if (OsgiBundleUtils.isBundleLazyActivated(bundle)) {\r\n\t\t\t\tmaybeAddNamespaceHandlerFor(bundle, true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// discovery finished, publish the resolvers/parsers in the OSGi space\n\t\tnsManager.afterPropertiesSet();\r\n\t}\r\n\r\n\tprotected void initStartedBundles(BundleContext bundleContext) {\r\n\t\t// register the context creation listener\n\t\tcontextListener = new ContextBundleListener();\r\n\t\t// listen to any changes in bundles\n\t\tbundleContext.addBundleListener(contextListener);\r\n\t\t// get the bundles again to get an updated view\n\t\tBundle[] previousBundles = bundleContext.getBundles();\r\n\r\n\t\t// Instantiate all previously resolved bundles which are Spring\n\t\t// powered\n\t\tfor (int i = 0; i < previousBundles.length; i++) {\r\n\t\t\tif (OsgiBundleUtils.isBundleActive(previousBundles[i])) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tlifecycleManager.maybeCreateApplicationContextFor(previousBundles[i]);\r\n\t\t\t\t} catch (Throwable e) {\r\n\t\t\t\t\tlog.warn(\"Cannot start bundle \" + OsgiStringUtils.nullSafeSymbolicName(previousBundles[i])\r\n\t\t\t\t\t\t\t+ \" due to\", e);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Called by OSGi when this bundled is stopped. Unregister the namespace/entity resolving service and clear all\r\n\t * state. No further management of application contexts created by this extender prior to stopping the bundle occurs\r\n\t * after this point (even if the extender bundle is subsequently restarted).\r\n\t * \r\n\t * @see org.osgi.framework.BundleActivator#stop\r\n\t */\r\n\tpublic void stop(BundleContext context) throws Exception {\r\n\t\tshutdown();\r\n\t}\r\n\r\n\t/**\r\n\t * Shutdown the extender and all bundled managed by it. Shutdown of contexts is in the topological order of the\r\n\t * dependency graph formed by the service references.\r\n\t */\r\n\tprotected void shutdown() {\r\n\t\tsynchronized (monitor) {\r\n\t\t\t// if already closed, bail out\n\t\t\tif (isClosed)\r\n\t\t\t\treturn;\r\n\t\t\telse\r\n\t\t\t\tisClosed = true;\r\n\t\t}\r\n\t\tlog.info(\"Stopping [\" + bundleContext.getBundle().getSymbolicName() + \"] bundle v.[\" + extenderVersion + \"]\");\r\n\r\n\t\tdestroyJavaBeansCache();\r\n\r\n\t\t// remove the bundle listeners (we are closing down)\n\t\tif (contextListener != null) {\r\n\t\t\tbundleContext.removeBundleListener(contextListener);\r\n\t\t\tcontextListener = null;\r\n\t\t}\r\n\r\n\t\tif (nsListener != null) {\r\n\t\t\tbundleContext.removeBundleListener(nsListener);\r\n\t\t\tnsListener = null;\r\n\t\t}\r\n\r\n\t\t// close managed bundles\n\t\tlifecycleManager.destroy();\r\n\t\t// clear the namespace registry\n\t\tnsManager.destroy();\r\n\r\n\t\t// release multicaster\n\t\tif (multicaster != null) {\r\n\t\t\tmulticaster.removeAllListeners();\r\n\t\t\tmulticaster = null;\r\n\t\t}\r\n\t\t// release listeners\n\t\tosgiListeners.destroy();\r\n\t\tosgiListeners = null;\r\n\r\n\t\textenderConfiguration.destroy();\r\n\t}\r\n\r\n\tprivate void initJavaBeansCache() {\r\n\t\tClass<?>[] classes =\r\n\t\t\t\tnew Class<?>[] { OsgiServiceFactoryBean.class, OsgiServiceProxyFactoryBean.class,\r\n\t\t\t\t\t\tOsgiServiceCollectionProxyFactoryBean.class };\r\n\r\n\t\tCachedIntrospectionResults.acceptClassLoader(OsgiStringUtils.class.getClassLoader());\r\n\r\n\t\tfor (Class<?> clazz : classes) {\r\n\t\t\tBeanUtils.getPropertyDescriptors(clazz);\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void destroyJavaBeansCache() {\r\n\t\tCachedIntrospectionResults.clearClassLoader(OsgiStringUtils.class.getClassLoader());\r\n\t}\r\n\r\n\tprotected void maybeAddNamespaceHandlerFor(Bundle bundle, boolean isLazy) {\r\n\t\tif (handlerBundleMatchesExtenderVersion(bundle))\r\n\t\t\tnsManager.maybeAddNamespaceHandlerFor(bundle, isLazy);\r\n\t}\r\n\r\n\tprotected void maybeRemoveNameSpaceHandlerFor(Bundle bundle) {\r\n\t\tif (handlerBundleMatchesExtenderVersion(bundle))\r\n\t\t\tnsManager.maybeRemoveNameSpaceHandlerFor(bundle);\r\n\t}\r\n\r\n\t/**\r\n\t * Utility method that does extender range versioning and approapriate\r\n\t * \r\n\t * logging.\r\n\t * \r\n\t * @param bundle\r\n\t */\r\n\tprivate boolean handlerBundleMatchesExtenderVersion(Bundle bundle) {\r\n\t\tif (!versionMatcher.matchVersion(bundle)) {\r\n\t\t\tif (log.isDebugEnabled())\r\n\t\t\t\tlog.debug(\"Ignoring handler bundle \" + OsgiStringUtils.nullSafeNameAndSymName(bundle)\r\n\t\t\t\t\t\t+ \"] due to mismatch in expected extender version\");\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\tprotected ApplicationContextConfigurationFactory createContextConfigFactory() {\r\n\t\treturn new DefaultApplicationContextConfigurationFactory();\r\n\t}\r\n\r\n\tprotected void initListenerService() {\r\n\t\tmulticaster = extenderConfiguration.getEventMulticaster();\r\n\r\n\t\taddApplicationListener(multicaster);\r\n\t\tmulticaster.addApplicationListener(extenderConfiguration.getContextEventListener());\r\n\r\n\t\tif (log.isDebugEnabled())\r\n\t\t\tlog.debug(\"Initialization of OSGi listeners service completed...\");\r\n\t}\r\n\r\n\tprotected void addApplicationListener(OsgiBundleApplicationContextEventMulticaster multicaster) {\r\n\t\tosgiListeners = new ListListenerAdapter(bundleContext);\r\n\t\tosgiListeners.afterPropertiesSet();\r\n\t\t// register the listener that does the dispatching\n\t\tmulticaster.addApplicationListener(osgiListeners);\r\n\t}\r\n} >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ContextLoaderListener.java (date 1346404121000) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ContextLoaderListener.java (revision ) >@@ -15,28 +15,16 @@ > > package org.eclipse.gemini.blueprint.extender.internal.activator; > >-import java.util.Map; >-import java.util.WeakHashMap; >- > import org.apache.commons.logging.Log; > import org.apache.commons.logging.LogFactory; >-import org.osgi.framework.Bundle; >-import org.osgi.framework.BundleActivator; >-import org.osgi.framework.BundleContext; >-import org.osgi.framework.BundleEvent; >-import org.osgi.framework.SynchronousBundleListener; >-import org.osgi.framework.Version; >-import org.springframework.beans.BeanUtils; >-import org.springframework.beans.CachedIntrospectionResults; >-import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster; >+import org.eclipse.gemini.blueprint.extender.OsgiApplicationContextCreator; >+import org.eclipse.gemini.blueprint.extender.internal.activator.listeners.BaseListener; > import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration; >-import org.eclipse.gemini.blueprint.extender.internal.support.NamespaceManager; >+import org.eclipse.gemini.blueprint.extender.support.DefaultOsgiApplicationContextCreator; > import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils; >-import org.eclipse.gemini.blueprint.service.exporter.support.OsgiServiceFactoryBean; >-import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceCollectionProxyFactoryBean; >-import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceProxyFactoryBean; > import org.eclipse.gemini.blueprint.util.OsgiBundleUtils; > import org.eclipse.gemini.blueprint.util.OsgiStringUtils; >+import org.osgi.framework.*; > > /** > * Osgi Extender that bootstraps 'Spring powered bundles'. >@@ -80,123 +68,7 @@ > */ > public class ContextLoaderListener implements BundleActivator { > >- /** >+ /** >- * Common base class for {@link ContextLoaderListener} listeners. >- * >- * @author Costin Leau >- */ >- private abstract class BaseListener implements SynchronousBundleListener { >- >- static final int LAZY_ACTIVATION_EVENT_TYPE = 0x00000200; >- >- protected final Log log = LogFactory.getLog(getClass()); >- >- /** >- * common cache used for tracking down bundles started lazily so they don't get processed twice (once when >- * started lazy, once when started fully) >- */ >- protected Map<Bundle, Object> lazyBundleCache = new WeakHashMap<Bundle, Object>(); >- /** dummy value for the bundle cache */ >- private final Object VALUE = new Object(); >- >- // caches the bundle >- protected void push(Bundle bundle) { >- synchronized (lazyBundleCache) { >- lazyBundleCache.put(bundle, VALUE); >- } >- } >- >- // checks the presence of the bundle as well as removing it >- protected boolean pop(Bundle bundle) { >- synchronized (lazyBundleCache) { >- return (lazyBundleCache.remove(bundle) != null); >- } >- } >- >- /** >- * A bundle has been started, stopped, resolved, or unresolved. This method is a synchronous callback, do not do >- * any long-running work in this thread. >- * >- * @see org.osgi.framework.SynchronousBundleListener#bundleChanged >- */ >- public void bundleChanged(BundleEvent event) { >- >- boolean trace = log.isTraceEnabled(); >- >- // check if the listener is still alive >- if (isClosed) { >- if (trace) >- log.trace("Listener is closed; events are being ignored"); >- return; >- } >- if (trace) { >- log.trace("Processing bundle event [" + OsgiStringUtils.nullSafeToString(event) + "] for bundle [" >- + OsgiStringUtils.nullSafeSymbolicName(event.getBundle()) + "]"); >- } >- try { >- handleEvent(event); >- } catch (Exception ex) { >- /* log exceptions before swallowing */ >- log.warn("Got exception while handling event " + event, ex); >- } >- } >- >- protected abstract void handleEvent(BundleEvent event); >- } >- >- /** >- * Bundle listener used for detecting namespace handler/resolvers. Exists as a separate listener so that it can be >- * registered early to avoid race conditions with bundles in INSTALLING state but still to avoid premature context >- * creation before the Spring {@link ContextLoaderListener} is not fully initialized. >- * >- * @author Costin Leau >- */ >- private class NamespaceBundleLister extends BaseListener { >- >- private final boolean resolved; >- >- NamespaceBundleLister(boolean resolvedBundles) { >- this.resolved = resolvedBundles; >- } >- >- protected void handleEvent(BundleEvent event) { >- Bundle bundle = event.getBundle(); >- >- switch (event.getType()) { >- >- case BundleEvent.RESOLVED: >- if (resolved) { >- maybeAddNamespaceHandlerFor(bundle, false); >- } >- break; >- >- case LAZY_ACTIVATION_EVENT_TYPE: { >- if (!resolved) { >- push(bundle); >- maybeAddNamespaceHandlerFor(bundle, true); >- } >- break; >- } >- case BundleEvent.STARTED: { >- if (!resolved) { >- if (!pop(bundle)) { >- maybeAddNamespaceHandlerFor(bundle, false); >- } >- } >- break; >- } >- case BundleEvent.STOPPED: { >- pop(bundle); >- maybeRemoveNameSpaceHandlerFor(bundle); >- break; >- } >- default: >- break; >- } >- } >- } >- >- /** > * Bundle listener used for context creation/destruction. > */ > private class ContextBundleListener extends BaseListener { >@@ -244,24 +116,19 @@ > > protected final Log log = LogFactory.getLog(getClass()); > >+ private ExtenderConfiguration extenderConfiguration; >+ private VersionMatcher versionMatcher; >+ private Version extenderVersion; >+ >- /** extender bundle id */ >+ /** extender bundle id */ > private long bundleId; > >- /** extender configuration */ >- private ExtenderConfiguration extenderConfiguration; >- >- /** Spring namespace/resolver manager */ >- private NamespaceManager nsManager; >- > /** The bundle's context */ > private BundleContext bundleContext; > > /** Bundle listener interested in context creation */ >- private SynchronousBundleListener contextListener; >+ private BaseListener contextListener; > >- /** Bundle listener interested in namespace resolvers/parsers discovery */ >- private SynchronousBundleListener nsListener; >- > /** > * Monitor used for dealing with the bundle activator and synchronous bundle threads > */ >@@ -272,60 +139,44 @@ > */ > private volatile boolean isClosed = false; > >- /** This extender version */ >- private Version extenderVersion; >- >- private volatile OsgiBundleApplicationContextEventMulticaster multicaster; >- > private volatile LifecycleManager lifecycleManager; >- private volatile VersionMatcher versionMatcher; > private volatile OsgiContextProcessor processor; >- private volatile ListListenerAdapter osgiListeners; > >+ public ContextLoaderListener(ExtenderConfiguration extenderConfiguration) { >+ this.extenderConfiguration = extenderConfiguration; >+ } >+ >- /** >+ /** > * <p/> Called by OSGi when this bundle is started. Finds all previously resolved bundles and adds namespace > * handlers for them if necessary. </p> <p/> Creates application contexts for bundles started before the extender > * was started. </p> <p/> Registers a namespace/entity resolving service for use by web app contexts. </p> > * > * @see org.osgi.framework.BundleActivator#start > */ >- public void start(BundleContext context) throws Exception { >+ public void start(BundleContext extenderBundleContext) throws Exception { > >- this.bundleContext = context; >- this.bundleId = context.getBundle().getBundleId(); >+ this.bundleContext = extenderBundleContext; >+ this.bundleId = extenderBundleContext.getBundle().getBundleId(); >+ this.extenderVersion = OsgiBundleUtils.getBundleVersion(extenderBundleContext.getBundle()); >+ this.versionMatcher = new DefaultVersionMatcher(getManagedBundleExtenderVersionHeader(), extenderVersion); >+ this.processor = createContextProcessor(); > >- this.extenderVersion = OsgiBundleUtils.getBundleVersion(context.getBundle()); >- log.info("Starting [" + bundleContext.getBundle().getSymbolicName() + "] bundle v.[" + extenderVersion + "]"); >- versionMatcher = new DefaultVersionMatcher(getManagedBundleExtenderVersionHeader(), extenderVersion); >- processor = createContextProcessor(); >- >- // init cache (to prevent ad-hoc Java Bean discovery on lazy bundles) >- initJavaBeansCache(); >- >- // Step 1 : discover existing namespaces (in case there are fragments with custom XML definitions) >- nsManager = new NamespaceManager(context); >- initNamespaceHandlers(bundleContext); >- >- // Step 2: initialize the extender configuration >- extenderConfiguration = initExtenderConfiguration(bundleContext); >- >- // init the OSGi event dispatch/listening system >- initListenerService(); >- > // initialize the configuration once namespace handlers have been detected >- lifecycleManager = >- new LifecycleManager(extenderConfiguration, versionMatcher, createContextConfigFactory(), >- this.processor, getTypeCompatibilityChecker(), bundleContext); >+ this.lifecycleManager = >+ new LifecycleManager( >+ this.extenderConfiguration, >+ getVersionMatcher(), >+ createContextConfigFactory(), >+ getOsgiApplicationContextCreator(), >+ this.processor, >+ getTypeCompatibilityChecker(), >+ bundleContext); > > // Step 3: discover the bundles that are started > // and require context creation > initStartedBundles(bundleContext); > } > >- protected ExtenderConfiguration initExtenderConfiguration(BundleContext bundleContext) { >- return new ExtenderConfiguration(bundleContext, log); >- } >- > protected OsgiContextProcessor createContextProcessor() { > return new NoOpOsgiContextProcessor(); > } >@@ -334,36 +185,6 @@ > return null; > } > >- protected String getManagedBundleExtenderVersionHeader() { >- return ConfigUtils.EXTENDER_VERSION; >- } >- >- protected void initNamespaceHandlers(BundleContext context) { >- nsManager = new NamespaceManager(context); >- >- // register listener first to make sure any bundles in INSTALLED state >- // are not lost >- >- // if the property is defined and true, consider bundles in STARTED/LAZY-INIT state, otherwise use RESOLVED >- boolean nsResolved = !Boolean.getBoolean("org.eclipse.gemini.blueprint.ns.bundles.started"); >- nsListener = new NamespaceBundleLister(nsResolved); >- context.addBundleListener(nsListener); >- >- Bundle[] previousBundles = context.getBundles(); >- >- for (Bundle bundle : previousBundles) { >- // special handling for uber bundle being restarted >- if ((nsResolved && OsgiBundleUtils.isBundleResolved(bundle)) || (!nsResolved && OsgiBundleUtils.isBundleActive(bundle)) || bundleId == bundle.getBundleId()) { >- maybeAddNamespaceHandlerFor(bundle, false); >- } else if (OsgiBundleUtils.isBundleLazyActivated(bundle)) { >- maybeAddNamespaceHandlerFor(bundle, true); >- } >- } >- >- // discovery finished, publish the resolvers/parsers in the OSGi space >- nsManager.afterPropertiesSet(); >- } >- > protected void initStartedBundles(BundleContext bundleContext) { > // register the context creation listener > contextListener = new ContextBundleListener(); >@@ -409,9 +230,8 @@ > else > isClosed = true; > } >- log.info("Stopping [" + bundleContext.getBundle().getSymbolicName() + "] bundle v.[" + extenderVersion + "]"); > >- destroyJavaBeansCache(); >+ this.contextListener.close(); > > // remove the bundle listeners (we are closing down) > if (contextListener != null) { >@@ -419,89 +239,31 @@ > contextListener = null; > } > >- if (nsListener != null) { >- bundleContext.removeBundleListener(nsListener); >- nsListener = null; >- } >- > // close managed bundles > lifecycleManager.destroy(); >- // clear the namespace registry >- nsManager.destroy(); >- >- // release multicaster >- if (multicaster != null) { >- multicaster.removeAllListeners(); >- multicaster = null; >- } >+ } >- // release listeners >- osgiListeners.destroy(); >- osgiListeners = null; > >- extenderConfiguration.destroy(); >+ protected ApplicationContextConfigurationFactory createContextConfigFactory() { >+ return new DefaultApplicationContextConfigurationFactory(); > } > >- private void initJavaBeansCache() { >- Class<?>[] classes = >- new Class<?>[] { OsgiServiceFactoryBean.class, OsgiServiceProxyFactoryBean.class, >- OsgiServiceCollectionProxyFactoryBean.class }; >- >- CachedIntrospectionResults.acceptClassLoader(OsgiStringUtils.class.getClassLoader()); >- >- for (Class<?> clazz : classes) { >- BeanUtils.getPropertyDescriptors(clazz); >+ public VersionMatcher getVersionMatcher() { >+ return versionMatcher; >- } >+ } >- } > >- private void destroyJavaBeansCache() { >- CachedIntrospectionResults.clearClassLoader(OsgiStringUtils.class.getClassLoader()); >+ protected String getManagedBundleExtenderVersionHeader() { >+ return ConfigUtils.EXTENDER_VERSION; >- } >+ } > >- protected void maybeAddNamespaceHandlerFor(Bundle bundle, boolean isLazy) { >- if (handlerBundleMatchesExtenderVersion(bundle)) >- nsManager.maybeAddNamespaceHandlerFor(bundle, isLazy); >+ private OsgiApplicationContextCreator getOsgiApplicationContextCreator() { >+ OsgiApplicationContextCreator creator = this.extenderConfiguration.getContextCreator(); >+ if (creator == null) { >+ creator = createDefaultOsgiApplicationContextCreator(); >- } >+ } >- >- protected void maybeRemoveNameSpaceHandlerFor(Bundle bundle) { >- if (handlerBundleMatchesExtenderVersion(bundle)) >- nsManager.maybeRemoveNameSpaceHandlerFor(bundle); >+ return creator; >- } >+ } > >- /** >- * Utility method that does extender range versioning and approapriate >- * >- * logging. >- * >- * @param bundle >- */ >- private boolean handlerBundleMatchesExtenderVersion(Bundle bundle) { >- if (!versionMatcher.matchVersion(bundle)) { >- if (log.isDebugEnabled()) >- log.debug("Ignoring handler bundle " + OsgiStringUtils.nullSafeNameAndSymName(bundle) >- + "] due to mismatch in expected extender version"); >- return false; >- } >- return true; >- } >- >- protected ApplicationContextConfigurationFactory createContextConfigFactory() { >- return new DefaultApplicationContextConfigurationFactory(); >- } >- >- protected void initListenerService() { >- multicaster = extenderConfiguration.getEventMulticaster(); >- >- addApplicationListener(multicaster); >- multicaster.addApplicationListener(extenderConfiguration.getContextEventListener()); >- >- if (log.isDebugEnabled()) >- log.debug("Initialization of OSGi listeners service completed..."); >- } >- >- protected void addApplicationListener(OsgiBundleApplicationContextEventMulticaster multicaster) { >- osgiListeners = new ListListenerAdapter(bundleContext); >- osgiListeners.afterPropertiesSet(); >- // register the listener that does the dispatching >- multicaster.addApplicationListener(osgiListeners); >+ protected OsgiApplicationContextCreator createDefaultOsgiApplicationContextCreator() { >+ return new DefaultOsgiApplicationContextCreator(); >- } >+ } > } >\ No newline at end of file >Index: extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationCustomSettingsTest.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP ><+>/******************************************************************************\r\n * Copyright (c) 2006, 2010 VMware Inc.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * and Apache License v2.0 which accompanies this distribution. \r\n * The Eclipse Public License is available at \r\n * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0\r\n * is available at http://www.opensource.org/licenses/apache2.0.php.\r\n * You may elect to redistribute this code under either of these licenses. \r\n * \r\n * Contributors:\r\n * VMware Inc.\r\n *****************************************************************************/\r\n\r\npackage org.eclipse.gemini.blueprint.extender.internal.support;\r\n\r\nimport java.net.URL;\r\nimport java.util.Enumeration;\r\nimport java.util.List;\r\n\r\nimport junit.framework.TestCase;\r\n\r\nimport org.apache.commons.logging.LogFactory;\r\nimport org.osgi.framework.Bundle;\r\nimport org.osgi.framework.BundleContext;\r\nimport org.springframework.core.task.SimpleAsyncTaskExecutor;\r\nimport org.springframework.core.task.TaskExecutor;\r\nimport org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;\r\nimport org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;\r\nimport org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;\r\nimport org.eclipse.gemini.blueprint.mock.ArrayEnumerator;\r\nimport org.eclipse.gemini.blueprint.mock.MockBundle;\r\nimport org.eclipse.gemini.blueprint.mock.MockBundleContext;\r\n\r\n/**\r\n * @author Costin Leau\r\n */\r\npublic class ExtenderConfigurationCustomSettingsTest extends TestCase {\r\n\r\n\tprivate ExtenderConfiguration config;\r\n\tprivate BundleContext bundleContext;\r\n\tprivate Bundle bundle;\r\n\r\n\tprotected void setUp() throws Exception {\r\n\t\tbundle = new MockBundle() {\r\n\r\n\t\t\tpublic Enumeration findEntries(String path, String filePattern, boolean recurse) {\r\n\t\t\t\treturn new ArrayEnumerator(new URL[] { getClass().getResource(\r\n\t\t\t\t\t\t\"/org/eclipse/gemini/blueprint/extender/internal/support/extender-custom-config.xml\") });\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tbundleContext = new MockBundleContext(bundle);\r\n\t\tconfig = new ExtenderConfiguration(bundleContext, LogFactory.getLog(ExtenderConfiguration.class));\r\n\t}\r\n\r\n\tprotected void tearDown() throws Exception {\r\n\t\tconfig.destroy();\r\n\t\tconfig = null;\r\n\t}\r\n\r\n\tpublic void testTaskExecutor() throws Exception {\r\n\t\tassertTrue(config.getTaskExecutor() instanceof SimpleAsyncTaskExecutor);\r\n\t\tassertEquals(\"conf-extender-thread\", ((SimpleAsyncTaskExecutor) config.getTaskExecutor()).getThreadNamePrefix());\r\n\t}\r\n\r\n\tpublic void testShutdownTaskExecutor() throws Exception {\r\n\t\tTaskExecutor executor = config.getShutdownTaskExecutor();\r\n\t\tassertTrue(executor instanceof SimpleAsyncTaskExecutor);\r\n\t}\r\n\r\n\tpublic void testEventMulticaster() throws Exception {\r\n\t\tassertTrue(config.getEventMulticaster() instanceof OsgiBundleApplicationContextEventMulticasterAdapter);\r\n\t}\r\n\r\n\tpublic void testApplicationContextCreator() throws Exception {\r\n\t\tassertTrue(config.getContextCreator() instanceof DummyContextCreator);\r\n\t}\r\n\r\n\tpublic void testShutdownWaitTime() throws Exception {\r\n\t\t// 300 ms\r\n\t\tassertEquals(300, config.getShutdownWaitTime());\r\n\t}\r\n\r\n\tpublic void testShouldProcessAnnotation() throws Exception {\r\n\t\tassertTrue(config.shouldProcessAnnotation());\r\n\t}\r\n\r\n\tpublic void testDependencyWaitTime() throws Exception {\r\n\t\t// 200 ms\r\n\t\tassertEquals(200, config.getDependencyWaitTime());\r\n\t}\r\n\r\n\tpublic void testPostProcessors() throws Exception {\r\n\t\tList postProcessors = config.getPostProcessors();\r\n\t\tassertEquals(1, postProcessors.size());\r\n\t\tassertTrue(postProcessors.get(0) instanceof DummyProcessor);\r\n\t}\r\n\r\n\tpublic void testDependencyFactories() throws Exception {\r\n\t\tList factories = config.getDependencyFactories();\r\n\t\tassertEquals(\"wrong number of dependencies factories registered by default\", 1, factories.size());\r\n\t\tassertTrue(factories.get(0) instanceof MandatoryImporterDependencyFactory);\r\n\t}\r\n} >=================================================================== >--- extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationCustomSettingsTest.java (date 1346404121000) >+++ extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationCustomSettingsTest.java (revision ) >@@ -51,11 +51,12 @@ > }; > > bundleContext = new MockBundleContext(bundle); >- config = new ExtenderConfiguration(bundleContext, LogFactory.getLog(ExtenderConfiguration.class)); >+ config = new ExtenderConfiguration(); >+ config.start(this.bundleContext); > } > > protected void tearDown() throws Exception { >- config.destroy(); >+ config.stop(this.bundleContext); > config = null; > } > >\ No newline at end of file >Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/boot/ChainActivator.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP ><+>/******************************************************************************\r\n * Copyright (c) 2006, 2010 VMware Inc.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * and Apache License v2.0 which accompanies this distribution. \r\n * The Eclipse Public License is available at \r\n * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0\r\n * is available at http://www.opensource.org/licenses/apache2.0.php.\r\n * You may elect to redistribute this code under either of these licenses. \r\n * \r\n * Contributors:\r\n * VMware Inc.\r\n *****************************************************************************/\r\n\r\npackage org.eclipse.gemini.blueprint.extender.internal.boot;\r\n\r\nimport org.apache.commons.logging.Log;\r\nimport org.apache.commons.logging.LogFactory;\r\nimport org.osgi.framework.BundleActivator;\r\nimport org.osgi.framework.BundleContext;\r\nimport org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener;\r\nimport org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.BlueprintLoaderListener;\r\nimport org.eclipse.gemini.blueprint.util.OsgiPlatformDetector;\r\nimport org.springframework.util.ClassUtils;\r\n\r\n/**\r\n * Bundle activator that simply the lifecycle callbacks to other activators.\r\n * \r\n * @author Costin Leau\r\n * \r\n */\r\npublic class ChainActivator implements BundleActivator {\r\n\r\n\tprotected final Log log = LogFactory.getLog(getClass());\r\n\r\n\tprivate static final boolean BLUEPRINT_AVAILABLE =\r\n\t\t\tClassUtils.isPresent(\"org.osgi.service.blueprint.container.BlueprintContainer\", ChainActivator.class\r\n\t\t\t\t\t.getClassLoader());\r\n\r\n\tprivate final BundleActivator[] CHAIN;\r\n\r\n\tpublic ChainActivator() {\r\n\t\tif (OsgiPlatformDetector.isR42()) {\r\n\t\t\tif (BLUEPRINT_AVAILABLE) {\r\n\t\t\t\tlog.info(\"Blueprint API detected; enabling Blueprint Container functionality\");\r\n\t\t\t\tCHAIN = new BundleActivator[] { new ContextLoaderListener(), new BlueprintLoaderListener() };\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tlog.warn(\"Blueprint API not found; disabling Blueprint Container functionality\");\r\n\t\t\t\tCHAIN = new BundleActivator[] { new ContextLoaderListener() };\t\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tlog.warn(\"Pre-4.2 OSGi platform detected; disabling Blueprint Container functionality\");\r\n\t\t\tCHAIN = new BundleActivator[] { new ContextLoaderListener() };\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void start(BundleContext context) throws Exception {\r\n\t\tfor (int i = 0; i < CHAIN.length; i++) {\r\n\t\t\tCHAIN[i].start(context);\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void stop(BundleContext context) throws Exception {\r\n\t\tfor (int i = CHAIN.length - 1; i >= 0; i--) {\r\n\t\t\tCHAIN[i].stop(context);\r\n\t\t}\r\n\t}\r\n}\r\n >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/boot/ChainActivator.java (date 1346404121000) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/boot/ChainActivator.java (revision ) >@@ -16,18 +16,19 @@ > > import org.apache.commons.logging.Log; > import org.apache.commons.logging.LogFactory; >+import org.eclipse.gemini.blueprint.extender.internal.activator.*; >+import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration; > import org.osgi.framework.BundleActivator; > import org.osgi.framework.BundleContext; >-import org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener; > import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.BlueprintLoaderListener; > import org.eclipse.gemini.blueprint.util.OsgiPlatformDetector; > import org.springframework.util.ClassUtils; > > /** > * Bundle activator that simply the lifecycle callbacks to other activators. >- * >+ * > * @author Costin Leau >- * >+ * > */ > public class ChainActivator implements BundleActivator { > >@@ -40,19 +41,51 @@ > private final BundleActivator[] CHAIN; > > public ChainActivator() { >+ final LoggingActivator logStatus = new LoggingActivator(); >+ final JavaBeansCacheActivator activateJavaBeansCache = new JavaBeansCacheActivator(); >+ final NamespaceHandlerActivator activateCustomNamespaceHandling = new NamespaceHandlerActivator(); >+ final NamespaceHandlerActivator activateBlueprintspecificNamespaceHandling = new BlueprintNamespaceHandlerActivator(); >+ final ExtenderConfiguration initializeExtenderConfiguration = new ExtenderConfiguration(); >+ final ListenerServiceActivator activateListeners = new ListenerServiceActivator(initializeExtenderConfiguration); >+ final ContextLoaderListener listenForSpringDmBundles = new ContextLoaderListener(initializeExtenderConfiguration); >+ final BlueprintLoaderListener listenForBlueprintBundles = new BlueprintLoaderListener(initializeExtenderConfiguration, activateListeners); >+ >- if (OsgiPlatformDetector.isR42()) { >+ if (OsgiPlatformDetector.isR42()) { > if (BLUEPRINT_AVAILABLE) { > log.info("Blueprint API detected; enabling Blueprint Container functionality"); >- CHAIN = new BundleActivator[] { new ContextLoaderListener(), new BlueprintLoaderListener() }; >+ CHAIN = new BundleActivator[] { >+ logStatus, >+ activateJavaBeansCache, >+ activateCustomNamespaceHandling, >+ activateBlueprintspecificNamespaceHandling, >+ initializeExtenderConfiguration, >+ activateListeners, >+ listenForSpringDmBundles, >+ listenForBlueprintBundles >+ }; > } > else { > log.warn("Blueprint API not found; disabling Blueprint Container functionality"); >- CHAIN = new BundleActivator[] { new ContextLoaderListener() }; >+ CHAIN = new BundleActivator[] { >+ logStatus, >+ activateJavaBeansCache, >+ activateCustomNamespaceHandling, >+ initializeExtenderConfiguration, >+ activateListeners, >+ listenForSpringDmBundles >+ }; > } > } else { > log.warn("Pre-4.2 OSGi platform detected; disabling Blueprint Container functionality"); >- CHAIN = new BundleActivator[] { new ContextLoaderListener() }; >+ CHAIN = new BundleActivator[] { >+ logStatus, >+ activateJavaBeansCache, >+ activateCustomNamespaceHandling, >+ initializeExtenderConfiguration, >+ activateListeners, >+ listenForSpringDmBundles >+ }; >- } >+ } > } > > public void start(BundleContext context) throws Exception { >Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ListenerServiceActivator.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ListenerServiceActivator.java (revision ) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ListenerServiceActivator.java (revision ) >@@ -0,0 +1,79 @@ >+package org.eclipse.gemini.blueprint.extender.internal.activator; >+ >+import org.apache.commons.logging.Log; >+import org.apache.commons.logging.LogFactory; >+import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster; >+import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration; >+import org.osgi.framework.BundleActivator; >+import org.osgi.framework.BundleContext; >+ >+/** >+ * Initializes the event multicaster infrastructure. >+ * >+ * @author Bill Gallagher >+ * @author Andy Piper >+ * @author Hal Hildebrand >+ * @author Adrian Colyer >+ * @author Costin Leau >+ * @author Olaf Otto >+ */ >+public class ListenerServiceActivator implements BundleActivator { >+ /** >+ * Monitor used for dealing with the bundle activator and synchronous bundle threads >+ */ >+ private final Object monitor = new Object(); >+ private boolean stopped = false; >+ private OsgiBundleApplicationContextEventMulticaster multicaster; >+ private volatile ListListenerAdapter osgiListeners; >+ private final Log log = LogFactory.getLog(getClass()); >+ private final ExtenderConfiguration extenderConfiguration; >+ private BundleContext extenderBundleContext; >+ >+ public ListenerServiceActivator(ExtenderConfiguration extenderConfiguration) { >+ this.extenderConfiguration = extenderConfiguration; >+ } >+ >+ public void start(BundleContext extenderBundleContext) throws Exception { >+ this.extenderBundleContext = extenderBundleContext; >+ initListenerService(); >+ } >+ >+ public void stop(BundleContext extenderBundleContext) throws Exception { >+ synchronized (monitor) { >+ if (stopped) { >+ return; >+ } >+ stopped = true; >+ } >+ >+ // release multicaster >+ if (multicaster != null) { >+ multicaster.removeAllListeners(); >+ multicaster = null; >+ } >+ // release listeners >+ osgiListeners.destroy(); >+ osgiListeners = null; >+ } >+ >+ protected void initListenerService() { >+ this.multicaster = extenderConfiguration.getEventMulticaster(); >+ >+ addApplicationListener(multicaster); >+ multicaster.addApplicationListener(extenderConfiguration.getContextEventListener()); >+ >+ if (log.isDebugEnabled()) >+ log.debug("Initialization of OSGi listeners service completed..."); >+ } >+ >+ protected void addApplicationListener(OsgiBundleApplicationContextEventMulticaster multicaster) { >+ osgiListeners = new ListListenerAdapter(this.extenderBundleContext); >+ osgiListeners.afterPropertiesSet(); >+ // register the listener that does the dispatching >+ multicaster.addApplicationListener(osgiListeners); >+ } >+ >+ public OsgiBundleApplicationContextEventMulticaster getMulticaster() { >+ return multicaster; >+ } >+} >Index: extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationDefaultSettingsTest.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP ><+>/******************************************************************************\r\n * Copyright (c) 2006, 2010 VMware Inc.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * and Apache License v2.0 which accompanies this distribution. \r\n * The Eclipse Public License is available at \r\n * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0\r\n * is available at http://www.opensource.org/licenses/apache2.0.php.\r\n * You may elect to redistribute this code under either of these licenses. \r\n * \r\n * Contributors:\r\n * VMware Inc.\r\n *****************************************************************************/\r\n\r\npackage org.eclipse.gemini.blueprint.extender.internal.support;\r\n\r\nimport java.util.List;\r\n\r\nimport junit.framework.TestCase;\r\n\r\nimport org.apache.commons.logging.LogFactory;\r\nimport org.osgi.framework.BundleContext;\r\nimport org.springframework.core.task.SimpleAsyncTaskExecutor;\r\nimport org.springframework.core.task.TaskExecutor;\r\nimport org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticasterAdapter;\r\nimport org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory;\r\nimport org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;\r\nimport org.eclipse.gemini.blueprint.extender.support.DefaultOsgiApplicationContextCreator;\r\nimport org.eclipse.gemini.blueprint.mock.MockBundleContext;\r\nimport org.springframework.scheduling.timer.TimerTaskExecutor;\r\n\r\n/**\r\n * @author Costin Leau\r\n */\r\npublic class ExtenderConfigurationDefaultSettingsTest extends TestCase {\r\n\r\n\tprivate ExtenderConfiguration config;\r\n\tprivate BundleContext bundleContext;\r\n\r\n\tprotected void setUp() throws Exception {\r\n\t\tbundleContext = new MockBundleContext();\r\n\t\tconfig = new ExtenderConfiguration(bundleContext, LogFactory.getLog(ExtenderConfiguration.class));\r\n\t}\r\n\r\n\tprotected void tearDown() throws Exception {\r\n\t\tconfig.destroy();\r\n\t\tconfig = null;\r\n\t}\r\n\r\n\tpublic void testTaskExecutor() throws Exception {\r\n\t\tassertTrue(config.getTaskExecutor() instanceof SimpleAsyncTaskExecutor);\r\n\t}\r\n\r\n\tpublic void testShutdownTaskExecutor() throws Exception {\r\n\t\tTaskExecutor executor = config.getShutdownTaskExecutor();\r\n\t\tassertTrue(executor instanceof TimerTaskExecutor);\r\n\t}\r\n\r\n\tpublic void testEventMulticaster() throws Exception {\r\n\t\tassertTrue(config.getEventMulticaster() instanceof OsgiBundleApplicationContextEventMulticasterAdapter);\r\n\t}\r\n\r\n\tpublic void testApplicationContextCreator() throws Exception {\r\n\t\tassertTrue(config.getContextCreator() instanceof DefaultOsgiApplicationContextCreator);\r\n\t}\r\n\r\n\tpublic void testShutdownWaitTime() throws Exception {\r\n\t\t// 10 seconds in ms\r\n\t\tassertEquals(10 * 1000, config.getShutdownWaitTime());\r\n\t}\r\n\r\n\tpublic void testShouldProcessAnnotation() throws Exception {\r\n\t\tassertFalse(config.shouldProcessAnnotation());\r\n\t}\r\n\r\n\tpublic void testDependencyWaitTime() throws Exception {\r\n\t\t// 5 minutes in ms\r\n\t\tassertEquals(5 * 60 * 1000, config.getDependencyWaitTime());\r\n\t}\r\n\r\n\tpublic void testPostProcessors() throws Exception {\r\n\t\tList postProcessors = config.getPostProcessors();\r\n\t\tassertTrue(postProcessors.isEmpty());\r\n\t}\r\n\r\n\tpublic void testDependencyFactories() throws Exception {\r\n\t\tList factories = config.getDependencyFactories();\r\n\t\tassertEquals(\"wrong number of dependencies factories registered by default\", 1, factories.size());\r\n\t\tassertTrue(factories.get(0) instanceof MandatoryImporterDependencyFactory);\r\n\t}\r\n} >=================================================================== >--- extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationDefaultSettingsTest.java (date 1346404121000) >+++ extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationDefaultSettingsTest.java (revision ) >@@ -39,11 +39,12 @@ > > protected void setUp() throws Exception { > bundleContext = new MockBundleContext(); >- config = new ExtenderConfiguration(bundleContext, LogFactory.getLog(ExtenderConfiguration.class)); >+ config = new ExtenderConfiguration(); >+ this.config.start(this.bundleContext); > } > > protected void tearDown() throws Exception { >- config.destroy(); >+ config.start(this.bundleContext); > config = null; > } > >@@ -61,7 +62,7 @@ > } > > public void testApplicationContextCreator() throws Exception { >- assertTrue(config.getContextCreator() instanceof DefaultOsgiApplicationContextCreator); >+ assertNull(config.getContextCreator()); > } > > public void testShutdownWaitTime() throws Exception { >\ No newline at end of file >Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/BlueprintLoaderListener.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP ><+>/******************************************************************************\r\n * Copyright (c) 2006, 2010 VMware Inc.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * and Apache License v2.0 which accompanies this distribution. \r\n * The Eclipse Public License is available at \r\n * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0\r\n * is available at http://www.opensource.org/licenses/apache2.0.php.\r\n * You may elect to redistribute this code under either of these licenses. \r\n * \r\n * Contributors:\r\n * VMware Inc.\r\n *****************************************************************************/\r\n\r\npackage org.eclipse.gemini.blueprint.extender.internal.blueprint.activator;\r\n\r\nimport org.osgi.framework.Bundle;\r\nimport org.osgi.framework.BundleContext;\r\nimport org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;\r\nimport org.eclipse.gemini.blueprint.extender.internal.activator.ApplicationContextConfigurationFactory;\r\nimport org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener;\r\nimport org.eclipse.gemini.blueprint.extender.internal.activator.OsgiContextProcessor;\r\nimport org.eclipse.gemini.blueprint.extender.internal.activator.TypeCompatibilityChecker;\r\nimport org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintConfigUtils;\r\nimport org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintContainerConfig;\r\nimport org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintExtenderConfiguration;\r\nimport org.eclipse.gemini.blueprint.extender.internal.blueprint.event.EventAdminDispatcher;\r\nimport org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;\r\nimport org.eclipse.gemini.blueprint.extender.support.ApplicationContextConfiguration;\r\n\r\n/**\r\n * RFC124 extension to the Spring DM extender.\r\n * \r\n * @author Costin Leau\r\n */\r\npublic class BlueprintLoaderListener extends ContextLoaderListener {\r\n\r\n\tprivate volatile EventAdminDispatcher dispatcher;\r\n\tprivate volatile BlueprintListenerManager listenerManager;\r\n\tprivate volatile Bundle bundle;\r\n\tprivate volatile BlueprintContainerProcessor contextProcessor;\r\n\tprivate volatile TypeCompatibilityChecker typeChecker;\r\n\r\n\t@Override\r\n\tpublic void start(BundleContext context) throws Exception {\r\n\t\tthis.listenerManager = new BlueprintListenerManager(context);\r\n\t\tthis.dispatcher = new EventAdminDispatcher(context);\r\n\t\tthis.bundle = context.getBundle();\r\n\t\tthis.contextProcessor = new BlueprintContainerProcessor(dispatcher, listenerManager, bundle);\r\n\t\tthis.typeChecker = new BlueprintTypeCompatibilityChecker(bundle);\r\n\r\n\t\tsuper.start(context);\r\n\t}\r\n\r\n\t@Override\r\n\tpublic void stop(BundleContext context) throws Exception {\r\n\t\tsuper.stop(context);\r\n\t\tlistenerManager.destroy();\r\n\t}\r\n\r\n\t@Override\r\n\tprotected ExtenderConfiguration initExtenderConfiguration(BundleContext bundleContext) {\r\n\t\treturn new BlueprintExtenderConfiguration(bundleContext, log);\r\n\t}\r\n\r\n\t@Override\r\n\tprotected ApplicationContextConfigurationFactory createContextConfigFactory() {\r\n\t\treturn new ApplicationContextConfigurationFactory() {\r\n\r\n\t\t\tpublic ApplicationContextConfiguration createConfiguration(Bundle bundle) {\r\n\t\t\t\treturn new BlueprintContainerConfig(bundle);\r\n\t\t\t}\r\n\t\t};\r\n\t}\r\n\r\n\t@Override\r\n\tprotected OsgiContextProcessor createContextProcessor() {\r\n\t\treturn contextProcessor;\r\n\t}\r\n\r\n\t@Override\r\n\tprotected TypeCompatibilityChecker getTypeCompatibilityChecker() {\r\n\t\treturn typeChecker;\r\n\t}\r\n\r\n\t@Override\r\n\tprotected String getManagedBundleExtenderVersionHeader() {\r\n\t\treturn BlueprintConfigUtils.EXTENDER_VERSION;\r\n\t}\r\n\r\n\t@Override\r\n\tprotected void addApplicationListener(OsgiBundleApplicationContextEventMulticaster multicaster) {\r\n\t\tsuper.addApplicationListener(multicaster);\r\n\t\t// monitor bootstrapping events\r\n\t\tmulticaster.addApplicationListener(contextProcessor);\r\n\t}\r\n\r\n\tprotected ApplicationContextConfiguration createContextConfig(Bundle bundle) {\r\n\t\treturn new BlueprintContainerConfig(bundle);\r\n\t}\r\n} >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/BlueprintLoaderListener.java (date 1346404121000) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/blueprint/activator/BlueprintLoaderListener.java (revision ) >@@ -14,19 +14,16 @@ > > package org.eclipse.gemini.blueprint.extender.internal.blueprint.activator; > >-import org.osgi.framework.Bundle; >-import org.osgi.framework.BundleContext; >-import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster; >-import org.eclipse.gemini.blueprint.extender.internal.activator.ApplicationContextConfigurationFactory; >-import org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener; >-import org.eclipse.gemini.blueprint.extender.internal.activator.OsgiContextProcessor; >-import org.eclipse.gemini.blueprint.extender.internal.activator.TypeCompatibilityChecker; >+import org.eclipse.gemini.blueprint.extender.OsgiApplicationContextCreator; >+import org.eclipse.gemini.blueprint.extender.internal.activator.*; > import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintConfigUtils; > import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintContainerConfig; >-import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintExtenderConfiguration; >+import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintContainerCreator; > import org.eclipse.gemini.blueprint.extender.internal.blueprint.event.EventAdminDispatcher; > import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration; > import org.eclipse.gemini.blueprint.extender.support.ApplicationContextConfiguration; >+import org.osgi.framework.Bundle; >+import org.osgi.framework.BundleContext; > > /** > * RFC124 extension to the Spring DM extender. >@@ -34,21 +31,24 @@ > * @author Costin Leau > */ > public class BlueprintLoaderListener extends ContextLoaderListener { >- >- private volatile EventAdminDispatcher dispatcher; >- private volatile BlueprintListenerManager listenerManager; >+ private volatile BlueprintListenerManager listenerManager; >- private volatile Bundle bundle; >- private volatile BlueprintContainerProcessor contextProcessor; >+ private volatile BlueprintContainerProcessor contextProcessor; > private volatile TypeCompatibilityChecker typeChecker; >+ private ListenerServiceActivator listenerServiceActivator; > >+ public BlueprintLoaderListener(ExtenderConfiguration extenderConfiguration, ListenerServiceActivator listenerServiceActivator) { >+ super(extenderConfiguration); >+ this.listenerServiceActivator = listenerServiceActivator; >+ } >+ >- @Override >+ @Override > public void start(BundleContext context) throws Exception { > this.listenerManager = new BlueprintListenerManager(context); >- this.dispatcher = new EventAdminDispatcher(context); >- this.bundle = context.getBundle(); >+ EventAdminDispatcher dispatcher = new EventAdminDispatcher(context); >+ Bundle bundle = context.getBundle(); > this.contextProcessor = new BlueprintContainerProcessor(dispatcher, listenerManager, bundle); > this.typeChecker = new BlueprintTypeCompatibilityChecker(bundle); >- >+ this.listenerServiceActivator.getMulticaster().addApplicationListener(this.contextProcessor); > super.start(context); > } > >@@ -59,11 +59,6 @@ > } > > @Override >- protected ExtenderConfiguration initExtenderConfiguration(BundleContext bundleContext) { >- return new BlueprintExtenderConfiguration(bundleContext, log); >- } >- >- @Override > protected ApplicationContextConfigurationFactory createContextConfigFactory() { > return new ApplicationContextConfigurationFactory() { > >@@ -73,7 +68,12 @@ > }; > } > >- @Override >+ @Override >+ protected OsgiApplicationContextCreator createDefaultOsgiApplicationContextCreator() { >+ return new BlueprintContainerCreator(); >+ } >+ >+ @Override > protected OsgiContextProcessor createContextProcessor() { > return contextProcessor; > } >@@ -86,16 +86,5 @@ > @Override > protected String getManagedBundleExtenderVersionHeader() { > return BlueprintConfigUtils.EXTENDER_VERSION; >- } >- >- @Override >- protected void addApplicationListener(OsgiBundleApplicationContextEventMulticaster multicaster) { >- super.addApplicationListener(multicaster); >- // monitor bootstrapping events >- multicaster.addApplicationListener(contextProcessor); >- } >- >- protected ApplicationContextConfiguration createContextConfig(Bundle bundle) { >- return new BlueprintContainerConfig(bundle); > } > } >\ No newline at end of file >Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/support/DefaultOsgiBundleApplicationContextListener.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP ><+>/******************************************************************************\r\n * Copyright (c) 2006, 2010 VMware Inc., Oracle Inc.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * and Apache License v2.0 which accompanies this distribution. \r\n * The Eclipse Public License is available at \r\n * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0\r\n * is available at http://www.opensource.org/licenses/apache2.0.php.\r\n * You may elect to redistribute this code under either of these licenses. \r\n * \r\n * Contributors:\r\n * VMware Inc.\r\n * Oracle Inc.\r\n *****************************************************************************/\r\n\r\npackage org.eclipse.gemini.blueprint.extender.internal.support;\r\n\r\nimport org.apache.commons.logging.Log;\r\nimport org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEvent;\r\nimport org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener;\r\nimport org.eclipse.gemini.blueprint.context.event.OsgiBundleContextClosedEvent;\r\nimport org.eclipse.gemini.blueprint.context.event.OsgiBundleContextFailedEvent;\r\nimport org.eclipse.gemini.blueprint.context.event.OsgiBundleContextRefreshedEvent;\r\nimport org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener;\r\n\r\n/**\r\n * Default application context event logger. Logs (using the {@link ContextLoaderListener} logger, the events received.\r\n * \r\n * @author Costin Leau\r\n * @author Andy Piper\r\n */\r\npublic class DefaultOsgiBundleApplicationContextListener implements\r\n\t\tOsgiBundleApplicationContextListener<OsgiBundleApplicationContextEvent> {\r\n\r\n\t/** logger */\r\n\tprivate final Log log;\r\n\r\n\tpublic DefaultOsgiBundleApplicationContextListener(Log log) {\r\n\t\tthis.log = log;\r\n\t}\r\n\r\n\tpublic void onOsgiApplicationEvent(OsgiBundleApplicationContextEvent event) {\r\n\t\tString applicationContextString = event.getApplicationContext().getDisplayName();\r\n\r\n\t\tif (event instanceof OsgiBundleContextRefreshedEvent) {\r\n\t\t\tlog.info(\"Application context successfully refreshed (\" + applicationContextString + \")\");\r\n\t\t}\r\n\r\n\t\tif (event instanceof OsgiBundleContextFailedEvent) {\r\n\t\t\tOsgiBundleContextFailedEvent failureEvent = (OsgiBundleContextFailedEvent) event;\r\n\t\t\tlog.error(\"Application context refresh failed (\" + applicationContextString + \")\", failureEvent\r\n\t\t\t\t\t.getFailureCause());\r\n\r\n\t\t}\r\n\r\n\t\tif (event instanceof OsgiBundleContextClosedEvent) {\r\n\t\t\tOsgiBundleContextClosedEvent closedEvent = (OsgiBundleContextClosedEvent) event;\r\n\t\t\tThrowable error = closedEvent.getFailureCause();\r\n\r\n\t\t\tif (error == null) {\r\n\t\t\t\tlog.info(\"Application context succesfully closed (\" + applicationContextString + \")\");\r\n\t\t\t} else {\r\n\t\t\t\tlog.error(\"Application context close failed (\" + applicationContextString + \")\", error);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n} >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/support/DefaultOsgiBundleApplicationContextListener.java (date 1346404121000) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/support/DefaultOsgiBundleApplicationContextListener.java (revision ) >@@ -21,10 +21,9 @@ > import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextClosedEvent; > import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextFailedEvent; > import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextRefreshedEvent; >-import org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener; > > /** >- * Default application context event logger. Logs (using the {@link ContextLoaderListener} logger, the events received. >+ * Default application context event logger. Logs (using the {@link org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener} logger, the events received. > * > * @author Costin Leau > * @author Andy Piper >\ No newline at end of file >Index: extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/ContextLoaderListenerTest.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP ><+>/******************************************************************************\r\n * Copyright (c) 2006, 2010 VMware Inc.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * and Apache License v2.0 which accompanies this distribution. \r\n * The Eclipse Public License is available at \r\n * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0\r\n * is available at http://www.opensource.org/licenses/apache2.0.php.\r\n * You may elect to redistribute this code under either of these licenses. \r\n * \r\n * Contributors:\r\n * VMware Inc.\r\n *****************************************************************************/\r\n\r\npackage org.eclipse.gemini.blueprint.extender.internal;\n\nimport java.util.Dictionary;\nimport java.util.Hashtable;\nimport java.util.Properties;\n\nimport junit.framework.TestCase;\n\nimport org.easymock.MockControl;\nimport org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener;\r\nimport org.eclipse.gemini.blueprint.extender.internal.support.TestTaskExecutor;\r\nimport org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils;\r\nimport org.eclipse.gemini.blueprint.mock.EntryLookupControllingMockBundle;\r\nimport org.eclipse.gemini.blueprint.mock.MockBundle;\r\nimport org.eclipse.gemini.blueprint.mock.MockBundleContext;\r\nimport org.eclipse.gemini.blueprint.mock.MockServiceRegistration;\r\nimport org.osgi.framework.Bundle;\nimport org.osgi.framework.BundleContext;\nimport org.osgi.framework.BundleEvent;\nimport org.osgi.framework.BundleListener;\nimport org.osgi.framework.Constants;\nimport org.springframework.core.io.ClassPathResource;\n\n/**\n * @author Adrian Colyer\n * \n */\npublic abstract class ContextLoaderListenerTest extends TestCase {\n\n\tprivate ContextLoaderListener listener;\n\n\n\tprotected void setUp() throws Exception {\n\t\tsuper.setUp();\n\t\tthis.listener = new ContextLoaderListener();\n\t}\n\n\tpublic void testStart() throws Exception {\n\t\tMockControl bundleContextControl = MockControl.createControl(BundleContext.class);\n\t\tBundleContext context = (BundleContext) bundleContextControl.getMock();\n\t\t// platform determination\n\n\t\t// extracting bundle id from bundle\n\t\tbundleContextControl.expectAndReturn(context.getBundle(), new MockBundle());\n\n\t\t// look for existing resolved bundles\n\t\tbundleContextControl.expectAndReturn(context.getBundles(), new Bundle[0], 2);\n\n\t\t// register namespace and entity resolving service\n\t\t// context.registerService((String[]) null, null, null);\n\t\t// bundleContextControl.setMatcher(MockControl.ALWAYS_MATCHER);\n\t\t// bundleContextControl.setReturnValue(null);\n\n\t\t// register context service\n\t\tcontext.registerService((String[]) null, null, null);\n\t\tbundleContextControl.setMatcher(MockControl.ALWAYS_MATCHER);\n\t\tbundleContextControl.setReturnValue(null, MockControl.ONE_OR_MORE);\n\n\t\t// create task executor\n\t\tEntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(null);\n\t\taBundle.setEntryReturnOnNextCallToGetEntry(null);\n\t\tbundleContextControl.expectAndReturn(context.getBundle(), aBundle, MockControl.ONE_OR_MORE);\n\n\t\t// listen for bundle events\n\t\tcontext.addBundleListener(null);\n\t\tbundleContextControl.setMatcher(MockControl.ALWAYS_MATCHER);\n\t\tbundleContextControl.setVoidCallable(2);\n\n\t\tbundleContextControl.expectAndReturn(context.registerService(new String[0], null, new Properties()),\n\t\t\tnew MockServiceRegistration(), MockControl.ONE_OR_MORE);\n\t\tbundleContextControl.setMatcher(MockControl.ALWAYS_MATCHER);\n\n\t\tbundleContextControl.replay();\n\n\t\tthis.listener.start(context);\n\t\tbundleContextControl.verify();\n\t}\n\n\tpublic void tstTaskExecutor() throws Exception {\n\t\tDictionary headers = new Hashtable();\n\t\theaders.put(Constants.BUNDLE_NAME, \"Extender mock bundle\");\n\t\tfinal EntryLookupControllingMockBundle aBundle = new EntryLookupControllingMockBundle(headers);\n\t\taBundle.setEntryReturnOnNextCallToGetEntry(new ClassPathResource(\"META-INF/spring/moved-extender.xml\").getURL());\n\n\t\tMockBundleContext ctx = new MockBundleContext() {\n\n\t\t\tpublic Bundle getBundle() {\n\t\t\t\treturn aBundle;\n\t\t\t}\n\t\t};\n\n\t\tthis.listener.start(ctx);\n\n\t\tDictionary hdrs = new Hashtable();\n\t\thdrs.put(ConfigUtils.SPRING_CONTEXT_HEADER, \"bla bla\");\n\t\tMockBundle anotherBundle = new MockBundle(hdrs);\n\t\tanotherBundle.setBundleId(1);\n\n\t\tBundleEvent event = new BundleEvent(BundleEvent.STARTED, anotherBundle);\n\n\t\tBundleListener listener = (BundleListener) ctx.getBundleListeners().iterator().next();\n\n\t\tTestTaskExecutor.called = false;\n\n\t\tlistener.bundleChanged(event);\n\t\tassertTrue(\"task executor should have been called if configured properly\", TestTaskExecutor.called);\n\t}\n\n}\n >=================================================================== >--- extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/ContextLoaderListenerTest.java (date 1346404121000) >+++ extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/ContextLoaderListenerTest.java (revision ) >@@ -22,6 +22,7 @@ > > import org.easymock.MockControl; > import org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener; >+import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration; > import org.eclipse.gemini.blueprint.extender.internal.support.TestTaskExecutor; > import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils; > import org.eclipse.gemini.blueprint.mock.EntryLookupControllingMockBundle; >@@ -40,13 +41,13 @@ > * > */ > public abstract class ContextLoaderListenerTest extends TestCase { >- > private ContextLoaderListener listener; >+ // TODO: mock & train once there are any applications of this base class. >+ private ExtenderConfiguration configuration; > >- >- protected void setUp() throws Exception { >+ protected void setUp() throws Exception { > super.setUp(); >- this.listener = new ContextLoaderListener(); >+ this.listener = new ContextLoaderListener(this.configuration); > } > > public void testStart() throws Exception { >Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LoggingActivator.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LoggingActivator.java (revision ) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LoggingActivator.java (revision ) >@@ -0,0 +1,27 @@ >+package org.eclipse.gemini.blueprint.extender.internal.activator; >+ >+import org.apache.commons.logging.Log; >+import org.apache.commons.logging.LogFactory; >+import org.eclipse.gemini.blueprint.util.OsgiBundleUtils; >+import org.osgi.framework.BundleActivator; >+import org.osgi.framework.BundleContext; >+import org.osgi.framework.Version; >+ >+/** >+ * Simply writes status convenient status information to the log. >+ * >+ * @author Olaf Otto >+ */ >+public class LoggingActivator implements BundleActivator { >+ private final Log log = LogFactory.getLog(getClass()); >+ >+ public void start(BundleContext extenderBundleContext) throws Exception { >+ Version extenderVersion = OsgiBundleUtils.getBundleVersion(extenderBundleContext.getBundle()); >+ log.info("Starting [" + extenderBundleContext.getBundle().getSymbolicName() + "] bundle v.[" + extenderVersion + "]"); >+ } >+ >+ public void stop(BundleContext extenderBundleContext) throws Exception { >+ Version extenderVersion = OsgiBundleUtils.getBundleVersion(extenderBundleContext.getBundle()); >+ log.info("Stopping [" + extenderBundleContext.getBundle().getSymbolicName() + "] bundle v.[" + extenderVersion + "]"); >+ } >+} >Index: core/src/test/java/org/eclipse/gemini/blueprint/context/support/ConfigLocationsTest.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP ><+>/******************************************************************************\r\n * Copyright (c) 2006, 2010 VMware Inc.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * and Apache License v2.0 which accompanies this distribution. \r\n * The Eclipse Public License is available at \r\n * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0\r\n * is available at http://www.opensource.org/licenses/apache2.0.php.\r\n * You may elect to redistribute this code under either of these licenses. \r\n * \r\n * Contributors:\r\n * VMware Inc.\r\n *****************************************************************************/\r\n\r\npackage org.eclipse.gemini.blueprint.context.support;\r\n\r\nimport java.lang.reflect.Method;\r\nimport java.util.Arrays;\r\n\r\nimport junit.framework.TestCase;\r\n\r\nimport org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext;\r\n\r\n/**\r\n * \r\n * @author Costin Leau\r\n */\r\npublic class ConfigLocationsTest extends TestCase {\r\n\r\n\tprivate OsgiBundleXmlApplicationContext context;\r\n\r\n\t@Override\r\n\tprotected void setUp() throws Exception {\r\n\t\tcontext = new OsgiBundleXmlApplicationContext();\r\n\t}\r\n\r\n\t@Override\r\n\tprotected void tearDown() throws Exception {\r\n\t\tcontext = null;\r\n\t}\r\n\r\n\tpublic void testExpandConfigFolders() throws Exception {\r\n\t\tString[] cfgs = new String[] { \"cnf/\", \"/cnf/\" };\r\n\t\tcontext.setConfigLocations(cfgs);\r\n\t\tString[] returned =\r\n\t\t\t\t(String[]) invokeMethod(\"expandLocations\", new Class[] { String[].class }, new Object[] { cfgs });\r\n\t\tSystem.out.println(\"returned \" + Arrays.toString(returned));\r\n\t\tassertTrue(Arrays.equals(new String[] { \"cnf/*.xml\", \"/cnf/*.xml\" }, returned));\r\n\t}\r\n\r\n\tprivate Object invokeMethod(String name, Class[] types, Object[] args) {\r\n\t\ttry {\r\n\t\t\tMethod mt = context.getClass().getDeclaredMethod(name, types);\r\n\t\t\tmt.setAccessible(true);\r\n\t\t\treturn mt.invoke(context, args);\r\n\t\t} catch (Exception ex) {\r\n\t\t\tthrow new RuntimeException(ex);\r\n\t\t}\r\n\t}\r\n}\r\n >=================================================================== >--- core/src/test/java/org/eclipse/gemini/blueprint/context/support/ConfigLocationsTest.java (date 1346404121000) >+++ core/src/test/java/org/eclipse/gemini/blueprint/context/support/ConfigLocationsTest.java (revision ) >@@ -44,7 +44,6 @@ > context.setConfigLocations(cfgs); > String[] returned = > (String[]) invokeMethod("expandLocations", new Class[] { String[].class }, new Object[] { cfgs }); >- System.out.println("returned " + Arrays.toString(returned)); > assertTrue(Arrays.equals(new String[] { "cnf/*.xml", "/cnf/*.xml" }, returned)); > } > >Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/listeners/NamespaceBundleLister.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/listeners/NamespaceBundleLister.java (revision ) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/listeners/NamespaceBundleLister.java (revision ) >@@ -0,0 +1,59 @@ >+package org.eclipse.gemini.blueprint.extender.internal.activator.listeners; >+ >+import org.eclipse.gemini.blueprint.extender.internal.activator.NamespaceHandlerActivator; >+import org.osgi.framework.Bundle; >+import org.osgi.framework.BundleEvent; >+ >+/** >+ * Bundle listener used for detecting namespace handler/resolvers. Exists as a separate listener so that it can be >+ * registered early to avoid race conditions with bundles in INSTALLING state but still to avoid premature context >+ * creation before the Spring {@link org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener} is not fully initialized. >+ * >+ * @author Costin Leau >+ */ >+public class NamespaceBundleLister extends BaseListener { >+ >+ private final boolean resolved; >+ private final NamespaceHandlerActivator namespaceHandlerActivator; >+ >+ public NamespaceBundleLister(boolean resolvedBundles, NamespaceHandlerActivator namespaceHandlerActivator) { >+ this.resolved = resolvedBundles; >+ this.namespaceHandlerActivator = namespaceHandlerActivator; >+ } >+ >+ protected void handleEvent(BundleEvent event) { >+ Bundle bundle = event.getBundle(); >+ >+ switch (event.getType()) { >+ >+ case BundleEvent.RESOLVED: >+ if (resolved) { >+ this.namespaceHandlerActivator.maybeAddNamespaceHandlerFor(bundle, false); >+ } >+ break; >+ >+ case LAZY_ACTIVATION_EVENT_TYPE: { >+ if (!resolved) { >+ push(bundle); >+ this.namespaceHandlerActivator.maybeAddNamespaceHandlerFor(bundle, true); >+ } >+ break; >+ } >+ case BundleEvent.STARTED: { >+ if (!resolved) { >+ if (!pop(bundle)) { >+ this.namespaceHandlerActivator.maybeAddNamespaceHandlerFor(bundle, false); >+ } >+ } >+ break; >+ } >+ case BundleEvent.STOPPED: { >+ pop(bundle); >+ this.namespaceHandlerActivator.maybeRemoveNameSpaceHandlerFor(bundle); >+ break; >+ } >+ default: >+ break; >+ } >+ } >+} >\ No newline at end of file >Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/JavaBeansCacheActivator.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/JavaBeansCacheActivator.java (revision ) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/JavaBeansCacheActivator.java (revision ) >@@ -0,0 +1,60 @@ >+package org.eclipse.gemini.blueprint.extender.internal.activator; >+ >+import org.eclipse.gemini.blueprint.service.exporter.support.OsgiServiceFactoryBean; >+import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceCollectionProxyFactoryBean; >+import org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceProxyFactoryBean; >+import org.eclipse.gemini.blueprint.util.OsgiStringUtils; >+import org.osgi.framework.BundleActivator; >+import org.osgi.framework.BundleContext; >+import org.springframework.beans.BeanUtils; >+import org.springframework.beans.CachedIntrospectionResults; >+ >+/** >+ * Used to prevent ad-hoc Java Bean discovery on lazy bundles. >+ * >+ * @author Bill Gallagher >+ * @author Andy Piper >+ * @author Hal Hildebrand >+ * @author Adrian Colyer >+ * @author Costin Leau >+ * @author Olaf Otto >+ */ >+public class JavaBeansCacheActivator implements BundleActivator { >+ /** >+ * Monitor used for dealing with the bundle activator and synchronous bundle threads >+ */ >+ private final Object monitor = new Object(); >+ private boolean stopped = false; >+ >+ public void start(BundleContext extenderBundleContext) { >+ initJavaBeansCache(); >+ } >+ >+ public void stop(BundleContext extenderBundleContext) { >+ synchronized (monitor) { >+ if (stopped) { >+ return; >+ } >+ stopped = true; >+ } >+ destroyJavaBeansCache(); >+ } >+ >+ private void initJavaBeansCache() { >+ Class<?>[] classes = >+ new Class<?>[] { OsgiServiceFactoryBean.class, OsgiServiceProxyFactoryBean.class, >+ OsgiServiceCollectionProxyFactoryBean.class }; >+ >+ CachedIntrospectionResults.acceptClassLoader(OsgiStringUtils.class.getClassLoader()); >+ >+ for (Class<?> clazz : classes) { >+ BeanUtils.getPropertyDescriptors(clazz); >+ } >+ } >+ >+ private void destroyJavaBeansCache() { >+ CachedIntrospectionResults.clearClassLoader(OsgiStringUtils.class.getClassLoader()); >+ } >+} >+ >+ >Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ListListenerAdapter.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP ><+>/******************************************************************************\r\n * Copyright (c) 2006, 2010 VMware Inc.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * and Apache License v2.0 which accompanies this distribution. \r\n * The Eclipse Public License is available at \r\n * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0\r\n * is available at http://www.opensource.org/licenses/apache2.0.php.\r\n * You may elect to redistribute this code under either of these licenses. \r\n * \r\n * Contributors:\r\n * VMware Inc.\r\n *****************************************************************************/\r\n\r\npackage org.eclipse.gemini.blueprint.extender.internal.activator;\r\n\r\nimport java.lang.reflect.ParameterizedType;\r\nimport java.lang.reflect.Type;\r\nimport java.lang.reflect.TypeVariable;\r\nimport java.util.Map;\r\nimport java.util.WeakHashMap;\r\n\r\nimport org.osgi.framework.BundleContext;\r\nimport org.osgi.util.tracker.ServiceTracker;\r\nimport org.springframework.beans.factory.DisposableBean;\r\nimport org.springframework.beans.factory.InitializingBean;\r\nimport org.springframework.core.GenericTypeResolver;\r\nimport org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEvent;\r\nimport org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener;\r\n\r\n/**\r\n * Listener interface that delegates to a list of listener. This is useful in OSGi environments when dealing with\r\n * dynamic collections which can be updated during iteration.\r\n * \r\n * @author Costin Leau\r\n * \r\n */\r\n@SuppressWarnings(\"unchecked\")\r\nclass ListListenerAdapter implements OsgiBundleApplicationContextListener<OsgiBundleApplicationContextEvent>,\r\n\t\tInitializingBean, DisposableBean {\r\n\r\n\tprivate final ServiceTracker tracker;\r\n\tprivate final Map<Class<? extends OsgiBundleApplicationContextListener>, Class<? extends OsgiBundleApplicationContextEvent>> eventCache =\r\n\t\t\tnew WeakHashMap<Class<? extends OsgiBundleApplicationContextListener>, Class<? extends OsgiBundleApplicationContextEvent>>();\r\n\r\n\t/**\r\n\t * Constructs a new <code>ListListenerAdapter</code> instance.\r\n\t * \r\n\t * @param listeners\r\n\t */\r\n\tpublic ListListenerAdapter(BundleContext bundleContext) {\r\n\t\tthis.tracker = new ServiceTracker(bundleContext, OsgiBundleApplicationContextListener.class.getName(), null);\r\n\t}\r\n\r\n\tpublic void afterPropertiesSet() {\r\n\t\tthis.tracker.open();\r\n\t}\r\n\r\n\tpublic void destroy() {\r\n\t\tthis.tracker.close();\r\n\t\teventCache.clear();\r\n\t}\r\n\r\n\tpublic void onOsgiApplicationEvent(OsgiBundleApplicationContextEvent event) {\r\n\t\tObject[] listeners = tracker.getServices();\r\n\r\n\t\tif (listeners != null) {\r\n\t\t\tsynchronized (eventCache) {\r\n\t\t\t\tfor (Object listnr : listeners) {\r\n\t\t\t\t\tOsgiBundleApplicationContextListener listener = (OsgiBundleApplicationContextListener) listnr;\r\n\t\t\t\t\tClass<? extends OsgiBundleApplicationContextListener> listenerClass = listener.getClass();\r\n\t\t\t\t\tClass<? extends OsgiBundleApplicationContextEvent> eventType = eventCache.get(listenerClass);\r\n\t\t\t\t\tif (eventType == null) {\r\n\t\t\t\t\t\tClass<?> evtType =\r\n\t\t\t\t\t\t\t\tGenericTypeResolver.resolveTypeArgument(listenerClass,\r\n\t\t\t\t\t\t\t\t\t\tOsgiBundleApplicationContextListener.class);\r\n\t\t\t\t\t\tif (evtType == null) {\r\n\t\t\t\t\t\t\tevtType = OsgiBundleApplicationContextEvent.class;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (evtType != null && evtType.isAssignableFrom(OsgiBundleApplicationContextEvent.class)) {\r\n\t\t\t\t\t\t\teventType = (Class<? extends OsgiBundleApplicationContextEvent>) evtType;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\teventType = OsgiBundleApplicationContextEvent.class;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\teventCache.put(listenerClass, eventType);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (eventType.isInstance(event)) {\r\n\t\t\t\t\t\tlistener.onOsgiApplicationEvent(event);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n} >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ListListenerAdapter.java (date 1346404121000) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/ListListenerAdapter.java (revision ) >@@ -14,20 +14,17 @@ > > package org.eclipse.gemini.blueprint.extender.internal.activator; > >-import java.lang.reflect.ParameterizedType; >-import java.lang.reflect.Type; >-import java.lang.reflect.TypeVariable; >-import java.util.Map; >-import java.util.WeakHashMap; >- >+import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEvent; >+import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener; > import org.osgi.framework.BundleContext; > import org.osgi.util.tracker.ServiceTracker; > import org.springframework.beans.factory.DisposableBean; > import org.springframework.beans.factory.InitializingBean; > import org.springframework.core.GenericTypeResolver; >-import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEvent; >-import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener; > >+import java.util.Map; >+import java.util.WeakHashMap; >+ > /** > * Listener interface that delegates to a list of listener. This is useful in OSGi environments when dealing with > * dynamic collections which can be updated during iteration. >@@ -45,8 +42,6 @@ > > /** > * Constructs a new <code>ListListenerAdapter</code> instance. >- * >- * @param listeners > */ > public ListListenerAdapter(BundleContext bundleContext) { > this.tracker = new ServiceTracker(bundleContext, OsgiBundleApplicationContextListener.class.getName(), null); >\ No newline at end of file >Index: core/src/test/java/org/eclipse/gemini/blueprint/context/internal/classloader/ChainedClassLoaderTest.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP ><+>/******************************************************************************\r\n * Copyright (c) 2006, 2010 VMware Inc.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * and Apache License v2.0 which accompanies this distribution. \r\n * The Eclipse Public License is available at \r\n * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0\r\n * is available at http://www.opensource.org/licenses/apache2.0.php.\r\n * You may elect to redistribute this code under either of these licenses. \r\n * \r\n * Contributors:\r\n * VMware Inc.\r\n *****************************************************************************/\r\n\r\npackage org.eclipse.gemini.blueprint.context.internal.classloader;\r\n\r\nimport java.net.URL;\r\nimport java.net.URLClassLoader;\r\nimport java.util.List;\r\n\r\nimport junit.framework.TestCase;\r\n\r\nimport org.eclipse.gemini.blueprint.TestUtils;\r\nimport org.eclipse.gemini.blueprint.context.support.internal.classloader.ChainedClassLoader;\r\nimport org.osgi.framework.Bundle;\r\n\r\n/**\r\n * @author Costin Leau\r\n */\r\npublic class ChainedClassLoaderTest extends TestCase {\r\n\r\n\tprivate ChainedClassLoader chainedLoader;\r\n\tprivate ClassLoader emptyCL;\r\n\r\n\r\n\tprotected void setUp() throws Exception {\r\n\t\temptyCL = new URLClassLoader(new URL[0], null) {\r\n\r\n\t\t\tpublic Class<?> loadClass(String name) throws ClassNotFoundException {\r\n\t\t\t\tthrow new ClassNotFoundException(name);\r\n\t\t\t}\r\n\r\n\t\t\tpublic URL getResource(String name) {\r\n\t\t\t\treturn null;\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tchainedLoader = new ChainedClassLoader(new ClassLoader[] { emptyCL }, emptyCL);\r\n\t}\r\n\r\n\tprotected void tearDown() throws Exception {\r\n\t\tchainedLoader = null;\r\n\t\temptyCL = null;\r\n\t}\r\n\r\n\tpublic void testChainedClassLoaderClassLoaderArray() throws Exception {\r\n\t\tString className = \"java.lang.Object\";\r\n\t\ttry {\r\n\t\t\temptyCL.loadClass(className);\r\n\t\t\tfail(\"should not be able to load classes\");\r\n\t\t}\r\n\t\tcatch (ClassNotFoundException cnfe) {\r\n\t\t\t// expected\r\n\t\t}\r\n\r\n\t\tchainedLoader = new ChainedClassLoader(new ClassLoader[] { emptyCL });\r\n\t\tchainedLoader.loadClass(className);\r\n\t}\r\n\r\n\tpublic void testParentClassLoader() throws Exception {\r\n\t\tchainedLoader = new ChainedClassLoader(new ClassLoader[] { emptyCL });\r\n\t\tClassLoader parent = chainedLoader.getParent();\r\n\t\tassertNotNull(parent);\r\n\t\t// fragile check (might fail on non SUN VMs)\r\n\t\tassertTrue(\"does the test run on a SUN VM or is it embedded?\", parent.getClass().getName().indexOf(\"App\") >= 0);\r\n\t}\r\n\r\n\tpublic void testChainedClassLoaderClassLoaderArrayClassLoader() throws Exception {\r\n\t\tString className = \"java.lang.Object\";\r\n\r\n\t\ttry {\r\n\t\t\temptyCL.loadClass(className);\r\n\t\t\tfail(\"should not be able to load classes\");\r\n\t\t}\r\n\t\tcatch (ClassNotFoundException cnfe) {\r\n\t\t\t// expected\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tchainedLoader.loadClass(className);\r\n\t\t\tfail(\"should not be able to load classes\");\r\n\t\t}\r\n\t\tcatch (ClassNotFoundException cnfe) {\r\n\t\t\t// expected\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void testGetResourceString() throws Exception {\r\n\t\tSystem.out.println(chainedLoader.getResource(\"java/lang/Object.class\"));\r\n\t\tassertNull(chainedLoader.getResource(\"java/lang/Object.class\"));\r\n\t\tchainedLoader.addClassLoader(Object.class);\r\n\t\tassertNotNull(chainedLoader.getResource(\"java/lang/Object.class\"));\r\n\t}\r\n\r\n\tpublic void testAddClassLoaderClass() throws Exception {\r\n\t\tchainedLoader.addClassLoader(Object.class);\r\n\t\tchainedLoader.loadClass(\"java.lang.Object\");\r\n\t}\r\n\r\n\tpublic void testAddClassLoaderClassLoader() throws Exception {\r\n\t\tchainedLoader.addClassLoader(Bundle.class.getClassLoader());\r\n\t\tchainedLoader.loadClass(\"org.osgi.framework.Bundle\");\r\n\t}\r\n\r\n\tpublic void testNonOSGiClassLoaderInsertOrder() throws Exception {\r\n\t\tClassLoader appLoader = ClassLoader.getSystemClassLoader();\r\n\t\tClassLoader extLoader = appLoader.getParent();\r\n\r\n\t\tchainedLoader.addClassLoader(extLoader);\r\n\t\tchainedLoader.addClassLoader(appLoader);\r\n\r\n\t\t// read the internal array\r\n\t\tList list = (List) TestUtils.getFieldValue(chainedLoader, \"nonOsgiLoaders\");\r\n\r\n\t\t// the loaders should be inserted based on their inheritance\r\n\t\tassertSame(appLoader, list.get(0));\r\n\t\tassertSame(extLoader, list.get(1));\r\n\t}\r\n} >=================================================================== >--- core/src/test/java/org/eclipse/gemini/blueprint/context/internal/classloader/ChainedClassLoaderTest.java (date 1346404121000) >+++ core/src/test/java/org/eclipse/gemini/blueprint/context/internal/classloader/ChainedClassLoaderTest.java (revision ) >@@ -96,7 +96,6 @@ > } > > public void testGetResourceString() throws Exception { >- System.out.println(chainedLoader.getResource("java/lang/Object.class")); > assertNull(chainedLoader.getResource("java/lang/Object.class")); > chainedLoader.addClassLoader(Object.class); > assertNotNull(chainedLoader.getResource("java/lang/Object.class")); >\ No newline at end of file >Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/BlueprintNamespaceHandlerActivator.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/BlueprintNamespaceHandlerActivator.java (revision ) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/BlueprintNamespaceHandlerActivator.java (revision ) >@@ -0,0 +1,14 @@ >+package org.eclipse.gemini.blueprint.extender.internal.activator; >+ >+import org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintConfigUtils; >+ >+/** >+ * @author Olaf Otto >+ */ >+public class BlueprintNamespaceHandlerActivator extends NamespaceHandlerActivator { >+ >+ @Override >+ protected String getManagedBundleExtenderVersionHeader() { >+ return BlueprintConfigUtils.EXTENDER_VERSION; >+ } >+} >Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/NamespaceHandlerActivator.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/NamespaceHandlerActivator.java (revision ) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/NamespaceHandlerActivator.java (revision ) >@@ -0,0 +1,115 @@ >+package org.eclipse.gemini.blueprint.extender.internal.activator; >+ >+import org.apache.commons.logging.Log; >+import org.apache.commons.logging.LogFactory; >+import org.eclipse.gemini.blueprint.extender.internal.activator.listeners.BaseListener; >+import org.eclipse.gemini.blueprint.extender.internal.activator.listeners.NamespaceBundleLister; >+import org.eclipse.gemini.blueprint.extender.internal.support.NamespaceManager; >+import org.eclipse.gemini.blueprint.extender.support.internal.ConfigUtils; >+import org.eclipse.gemini.blueprint.util.OsgiBundleUtils; >+import org.eclipse.gemini.blueprint.util.OsgiStringUtils; >+import org.osgi.framework.Bundle; >+import org.osgi.framework.BundleActivator; >+import org.osgi.framework.BundleContext; >+import org.osgi.framework.Version; >+ >+/** >+ * @author Bill Gallagher >+ * @author Andy Piper >+ * @author Hal Hildebrand >+ * @author Adrian Colyer >+ * @author Costin Leau >+ * @author Olaf Otto >+ */ >+public class NamespaceHandlerActivator implements BundleActivator { >+ /** >+ * Monitor used for dealing with the bundle activator and synchronous bundle threads >+ */ >+ private final Object monitor = new Object(); >+ private boolean stopped = false; >+ private final Log log = LogFactory.getLog(getClass()); >+ private NamespaceManager nsManager; >+ private BaseListener nsListener; >+ private long bundleId; >+ private BundleContext extenderBundleContext; >+ private DefaultVersionMatcher versionMatcher; >+ >+ public void start(BundleContext extenderBundleContext) { >+ this.extenderBundleContext = extenderBundleContext; >+ this.nsManager = new NamespaceManager(extenderBundleContext); >+ this.bundleId = extenderBundleContext.getBundle().getBundleId(); >+ Version extenderVersion = OsgiBundleUtils.getBundleVersion(extenderBundleContext.getBundle()); >+ this.versionMatcher = new DefaultVersionMatcher(getManagedBundleExtenderVersionHeader(), extenderVersion); >+ >+ initNamespaceHandlers(extenderBundleContext); >+ } >+ >+ public void stop(BundleContext context) throws Exception { >+ synchronized (monitor) { >+ if (stopped) { >+ return; >+ } >+ stopped = true; >+ } >+ >+ this.nsListener.close(); >+ this.extenderBundleContext.removeBundleListener(this.nsListener); >+ this.nsListener = null; >+ this.nsManager.destroy(); >+ } >+ >+ protected String getManagedBundleExtenderVersionHeader() { >+ return ConfigUtils.EXTENDER_VERSION; >+ } >+ >+ protected void initNamespaceHandlers(BundleContext extenderBundleContext) { >+ nsManager = new NamespaceManager(extenderBundleContext); >+ >+ // register listener first to make sure any bundles in INSTALLED state >+ // are not lost >+ >+ // if the property is defined and true, consider bundles in STARTED/LAZY-INIT state, otherwise use RESOLVED >+ boolean nsResolved = !Boolean.getBoolean("org.eclipse.gemini.blueprint.ns.bundles.started"); >+ nsListener = new NamespaceBundleLister(nsResolved, this); >+ extenderBundleContext.addBundleListener(nsListener); >+ >+ Bundle[] previousBundles = extenderBundleContext.getBundles(); >+ >+ for (Bundle bundle : previousBundles) { >+ // special handling for uber bundle being restarted >+ if ((nsResolved && OsgiBundleUtils.isBundleResolved(bundle)) || (!nsResolved && OsgiBundleUtils.isBundleActive(bundle)) || bundleId == bundle.getBundleId()) { >+ maybeAddNamespaceHandlerFor(bundle, false); >+ } else if (OsgiBundleUtils.isBundleLazyActivated(bundle)) { >+ maybeAddNamespaceHandlerFor(bundle, true); >+ } >+ } >+ >+ // discovery finished, publish the resolvers/parsers in the OSGi space >+ nsManager.afterPropertiesSet(); >+ } >+ >+ >+ public void maybeAddNamespaceHandlerFor(Bundle bundle, boolean isLazy) { >+ if (handlerBundleMatchesExtenderVersion(bundle)) { >+ nsManager.maybeAddNamespaceHandlerFor(bundle, isLazy); >+ } >+ } >+ >+ public void maybeRemoveNameSpaceHandlerFor(Bundle bundle) { >+ if (handlerBundleMatchesExtenderVersion(bundle)) >+ nsManager.maybeRemoveNameSpaceHandlerFor(bundle); >+ } >+ >+ /** >+ * Utility method that does extender range version check and appropriate logging. >+ */ >+ protected boolean handlerBundleMatchesExtenderVersion(Bundle bundle) { >+ if (!versionMatcher.matchVersion(bundle)) { >+ if (log.isDebugEnabled()) >+ log.debug("Ignoring handler bundle " + OsgiStringUtils.nullSafeNameAndSymName(bundle) >+ + "] due to mismatch in expected extender version"); >+ return false; >+ } >+ return true; >+ } >+} >Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/listeners/BaseListener.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/listeners/BaseListener.java (revision ) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/listeners/BaseListener.java (revision ) >@@ -0,0 +1,85 @@ >+package org.eclipse.gemini.blueprint.extender.internal.activator.listeners; >+ >+import org.apache.commons.logging.Log; >+import org.apache.commons.logging.LogFactory; >+import org.eclipse.gemini.blueprint.util.OsgiStringUtils; >+import org.osgi.framework.Bundle; >+import org.osgi.framework.BundleEvent; >+import org.osgi.framework.SynchronousBundleListener; >+ >+import java.util.Map; >+import java.util.WeakHashMap; >+ >+/** >+ * Common base class for {@link org.eclipse.gemini.blueprint.extender.internal.activator.ContextLoaderListener} listeners. >+ * >+ * @author Costin Leau >+ */ >+public abstract class BaseListener implements SynchronousBundleListener { >+ public static final int LAZY_ACTIVATION_EVENT_TYPE = 0x00000200; >+ >+ protected final Log log = LogFactory.getLog(getClass()); >+ >+ /** >+ * flag indicating whether the context is down or not - useful during shutdown >+ */ >+ private volatile boolean isClosed = false; >+ >+ /** >+ * common cache used for tracking down bundles started lazily so they don't get processed twice (once when >+ * started lazy, once when started fully) >+ */ >+ protected Map<Bundle, Object> lazyBundleCache = new WeakHashMap<Bundle, Object>(); >+ /** >+ * dummy value for the bundle cache >+ */ >+ private final Object VALUE = new Object(); >+ >+ // caches the bundle >+ protected void push(Bundle bundle) { >+ synchronized (lazyBundleCache) { >+ lazyBundleCache.put(bundle, VALUE); >+ } >+ } >+ >+ // checks the presence of the bundle as well as removing it >+ protected boolean pop(Bundle bundle) { >+ synchronized (lazyBundleCache) { >+ return (lazyBundleCache.remove(bundle) != null); >+ } >+ } >+ >+ /** >+ * A bundle has been started, stopped, resolved, or unresolved. This method is a synchronous callback, do not do >+ * any long-running work in this thread. >+ * >+ * @see org.osgi.framework.SynchronousBundleListener#bundleChanged >+ */ >+ public void bundleChanged(BundleEvent event) { >+ >+ boolean trace = log.isTraceEnabled(); >+ >+ // check if the listener is still alive >+ if (isClosed) { >+ if (trace) >+ log.trace("Listener is closed; events are being ignored"); >+ return; >+ } >+ if (trace) { >+ log.trace("Processing bundle event [" + OsgiStringUtils.nullSafeToString(event) + "] for bundle [" >+ + OsgiStringUtils.nullSafeSymbolicName(event.getBundle()) + "]"); >+ } >+ try { >+ handleEvent(event); >+ } catch (Exception ex) { >+ /* log exceptions before swallowing */ >+ log.warn("Got exception while handling event " + event, ex); >+ } >+ } >+ >+ protected abstract void handleEvent(BundleEvent event); >+ >+ public void close() { >+ this.isClosed = true; >+ } >+} >\ No newline at end of file >Index: extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java >IDEA additional info: >Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP ><+>UTF-8 >Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP ><+>/******************************************************************************\r\n * Copyright (c) 2006, 2010 VMware Inc.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * and Apache License v2.0 which accompanies this distribution. \r\n * The Eclipse Public License is available at \r\n * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0\r\n * is available at http://www.opensource.org/licenses/apache2.0.php.\r\n * You may elect to redistribute this code under either of these licenses. \r\n * \r\n * Contributors:\r\n * VMware Inc.\r\n *****************************************************************************/\r\n\r\npackage org.eclipse.gemini.blueprint.extender.internal.activator;\r\n\r\nimport java.util.ArrayList;\r\nimport java.util.Collection;\r\nimport java.util.Collections;\r\nimport java.util.List;\r\nimport java.util.Map;\r\nimport java.util.Timer;\r\nimport java.util.concurrent.ConcurrentHashMap;\r\n\r\nimport org.apache.commons.logging.Log;\r\nimport org.apache.commons.logging.LogFactory;\r\nimport org.eclipse.gemini.blueprint.context.ConfigurableOsgiBundleApplicationContext;\r\nimport org.eclipse.gemini.blueprint.context.DelegatedExecutionOsgiBundleApplicationContext;\r\nimport org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEventMulticaster;\r\nimport org.eclipse.gemini.blueprint.extender.OsgiApplicationContextCreator;\r\nimport org.eclipse.gemini.blueprint.extender.OsgiBeanFactoryPostProcessor;\r\nimport org.eclipse.gemini.blueprint.extender.internal.dependencies.shutdown.ShutdownSorter;\r\nimport org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor;\r\nimport org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;\r\nimport org.eclipse.gemini.blueprint.extender.internal.support.OsgiBeanFactoryPostProcessorAdapter;\r\nimport org.eclipse.gemini.blueprint.extender.internal.util.concurrent.Counter;\r\nimport org.eclipse.gemini.blueprint.extender.internal.util.concurrent.RunnableTimedExecution;\r\nimport org.eclipse.gemini.blueprint.extender.support.ApplicationContextConfiguration;\r\nimport org.eclipse.gemini.blueprint.util.OsgiBundleUtils;\r\nimport org.eclipse.gemini.blueprint.util.OsgiStringUtils;\r\nimport org.osgi.framework.Bundle;\r\nimport org.osgi.framework.BundleContext;\r\nimport org.springframework.beans.factory.DisposableBean;\r\nimport org.springframework.beans.factory.config.BeanFactoryPostProcessor;\r\nimport org.springframework.core.task.SyncTaskExecutor;\r\nimport org.springframework.core.task.TaskExecutor;\r\n\r\n/**\r\n * Manager handling the startup/shutdown threading issues regarding OSGi contexts. Used by {@link ContextLoaderListener}\r\n * .\r\n * \r\n * @author Costin Leau\r\n */\r\nclass LifecycleManager implements DisposableBean {\r\n\r\n\t/** logger */\r\n\tprivate static final Log log = LogFactory.getLog(LifecycleManager.class);\r\n\r\n\t/**\r\n\t * The contexts we are currently managing. Keys are bundle ids, values are ServiceDependentOsgiApplicationContexts\r\n\t * for the application context\r\n\t */\r\n\tprivate final Map<Long, ConfigurableOsgiBundleApplicationContext> managedContexts =\r\n\t\t\tnew ConcurrentHashMap<Long, ConfigurableOsgiBundleApplicationContext>(16);\r\n\r\n\t/** listener counter - used to properly synchronize shutdown */\r\n\tprivate Counter contextsStarted = new Counter(\"contextsStarted\");\r\n\r\n\t// \"Spring Application Context Creation Timer\"\r\n\tprivate final Timer timer = new Timer(\"Spring DM Context Creation Timer\", true);\r\n\r\n\t/** Task executor used for bootstraping the Spring contexts in async mode */\r\n\tprivate final TaskExecutor taskExecutor;\r\n\r\n\t/** ApplicationContext Creator */\r\n\tprivate final OsgiApplicationContextCreator contextCreator;\r\n\r\n\t/** BFPP list */\r\n\tprivate final List<OsgiBeanFactoryPostProcessor> postProcessors;\r\n\r\n\t/** shutdown task executor */\r\n\tprivate final TaskExecutor shutdownTaskExecutor;\r\n\r\n\t/**\r\n\t * Task executor which uses the same thread for running tasks. Used when doing a synchronous wait-for-dependencies.\r\n\t */\r\n\tprivate final TaskExecutor sameThreadTaskExecutor = new SyncTaskExecutor();\r\n\r\n\tprivate final OsgiBundleApplicationContextEventMulticaster multicaster;\r\n\r\n\tprivate final ExtenderConfiguration extenderConfiguration;\r\n\r\n\tprivate final BundleContext bundleContext;\r\n\r\n\tprivate final OsgiContextProcessor processor;\r\n\r\n\tprivate final ApplicationContextConfigurationFactory contextConfigurationFactory;\r\n\r\n\tprivate final VersionMatcher versionMatcher;\r\n\tprivate final TypeCompatibilityChecker typeChecker;\r\n\r\n\tLifecycleManager(ExtenderConfiguration extenderConfiguration, VersionMatcher versionMatcher,\r\n\t\t\tApplicationContextConfigurationFactory appCtxCfgFactory, OsgiContextProcessor processor,\r\n\t\t\tTypeCompatibilityChecker checker, BundleContext context) {\r\n\r\n\t\tthis.versionMatcher = versionMatcher;\r\n\t\tthis.extenderConfiguration = extenderConfiguration;\r\n\t\tthis.contextConfigurationFactory = appCtxCfgFactory;\r\n\r\n\t\tthis.processor = processor;\r\n\r\n\t\tthis.taskExecutor = extenderConfiguration.getTaskExecutor();\r\n\t\tthis.shutdownTaskExecutor = extenderConfiguration.getShutdownTaskExecutor();\r\n\r\n\t\tthis.multicaster = extenderConfiguration.getEventMulticaster();\r\n\r\n\t\tthis.contextCreator = extenderConfiguration.getContextCreator();\r\n\t\tthis.postProcessors = extenderConfiguration.getPostProcessors();\r\n\t\tthis.typeChecker = checker;\r\n\r\n\t\tthis.bundleContext = context;\r\n\t}\r\n\r\n\t/**\r\n\t * Context creation is a potentially long-running activity (certainly more than we want to do on the synchronous\r\n\t * event callback).\r\n\t * \r\n\t * <p/> Based on our configuration, the context can be started on the same thread or on a different one.\r\n\t * \r\n\t * <p/> Kick off a background activity to create an application context for the given bundle if needed.\r\n\t * \r\n\t * <b>Note:</b> Make sure to do the fastest filtering first to avoid slow-downs on platforms with a big number of\r\n\t * plugins and wiring (i.e. Eclipse platform).\r\n\t * \r\n\t * @param bundle\r\n\t */\r\n\tprotected void maybeCreateApplicationContextFor(Bundle bundle) {\r\n\r\n\t\tboolean debug = log.isDebugEnabled();\r\n\t\tString bundleString = \"[\" + OsgiStringUtils.nullSafeNameAndSymName(bundle) + \"]\";\r\n\r\n\t\tfinal Long bundleId = new Long(bundle.getBundleId());\r\n\r\n\t\tif (managedContexts.containsKey(bundleId)) {\r\n\t\t\tif (debug) {\r\n\t\t\t\tlog.debug(\"Bundle \" + bundleString + \" is already managed; ignoring...\");\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!versionMatcher.matchVersion(bundle)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tBundleContext localBundleContext = OsgiBundleUtils.getBundleContext(bundle);\r\n\r\n\t\t// initialize context\r\n\t\tfinal DelegatedExecutionOsgiBundleApplicationContext localApplicationContext;\r\n\r\n\t\tif (debug)\r\n\t\t\tlog.debug(\"Inspecting bundle \" + bundleString);\r\n\r\n\t\ttry {\r\n\t\t\tlocalApplicationContext = contextCreator.createApplicationContext(localBundleContext);\r\n\t\t} catch (Exception ex) {\r\n\t\t\tlog.error(\"Cannot create application context for bundle \" + bundleString, ex);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (localApplicationContext == null) {\r\n\t\t\tlog.debug(\"No application context created for bundle \" + bundleString);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (typeChecker != null) {\r\n\t\t\tif (!typeChecker.isTypeCompatible(localBundleContext)) {\r\n\t\t\t\tlog.info(\"Bundle \" + OsgiStringUtils.nullSafeName(bundle) + \" is not type compatible with extender \"\r\n\t\t\t\t\t\t+ OsgiStringUtils.nullSafeName(bundleContext.getBundle()) + \"; ignoring bundle...\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tlog.debug(\"Bundle \" + OsgiStringUtils.nullSafeName(bundle) + \" is type compatible with extender \"\r\n\t\t\t\t+ OsgiStringUtils.nullSafeName(bundleContext.getBundle()) + \"; processing bundle...\");\r\n\r\n\t\t// create a dedicated hook for this application context\r\n\t\tBeanFactoryPostProcessor processingHook =\r\n\t\t\t\tnew OsgiBeanFactoryPostProcessorAdapter(localBundleContext, postProcessors);\r\n\r\n\t\t// add in the post processors\r\n\t\tlocalApplicationContext.addBeanFactoryPostProcessor(processingHook);\r\n\r\n\t\t// add the context to the tracker\r\n\t\tmanagedContexts.put(bundleId, localApplicationContext);\r\n\r\n\t\tlocalApplicationContext.setDelegatedEventMulticaster(multicaster);\r\n\r\n\t\tApplicationContextConfiguration config = contextConfigurationFactory.createConfiguration(bundle);\r\n\r\n\t\tfinal boolean asynch = config.isCreateAsynchronously();\r\n\r\n\t\t// create refresh runnable\r\n\t\tRunnable contextRefresh = new Runnable() {\r\n\r\n\t\t\tpublic void run() {\r\n\t\t\t\t// post refresh events are caught through events\r\n\t\t\t\tif (log.isTraceEnabled()) {\r\n\t\t\t\t\tlog.trace(\"Calling pre-refresh on processor \" + processor);\r\n\t\t\t\t}\r\n\t\t\t\tprocessor.preProcessRefresh(localApplicationContext);\r\n\t\t\t\tlocalApplicationContext.refresh();\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\t// executor used for creating the appCtx\r\n\t\t// chosen based on the sync/async configuration\r\n\t\tTaskExecutor executor = null;\r\n\r\n\t\tString creationType;\r\n\r\n\t\t// synch/asynch context creation\r\n\t\tif (asynch) {\r\n\t\t\t// for the async stuff use the executor\r\n\t\t\texecutor = taskExecutor;\r\n\t\t\tcreationType = \"Asynchronous\";\r\n\t\t} else {\r\n\t\t\t// for the sync stuff, use this thread\r\n\t\t\texecutor = sameThreadTaskExecutor;\r\n\t\t\tcreationType = \"Synchronous\";\r\n\t\t}\r\n\r\n\t\tif (debug) {\r\n\t\t\tlog.debug(creationType + \" context creation for bundle \" + bundleString);\r\n\t\t}\r\n\r\n\t\t// wait/no wait for dependencies behaviour\r\n\t\tif (config.isWaitForDependencies()) {\r\n\t\t\tDependencyWaiterApplicationContextExecutor appCtxExecutor =\r\n\t\t\t\t\tnew DependencyWaiterApplicationContextExecutor(localApplicationContext, !asynch,\r\n\t\t\t\t\t\t\textenderConfiguration.getDependencyFactories());\r\n\r\n\t\t\tlong timeout;\r\n\t\t\t// check whether a timeout has been defined\r\n\r\n\t\t\tif (config.isTimeoutDeclared()) {\r\n\t\t\t\ttimeout = config.getTimeout();\r\n\t\t\t\tif (debug)\r\n\t\t\t\t\tlog.debug(\"Setting bundle-defined, wait-for-dependencies/graceperiod timeout value=\" + timeout\r\n\t\t\t\t\t\t\t+ \" ms, for bundle \" + bundleString);\r\n\r\n\t\t\t} else {\r\n\t\t\t\ttimeout = extenderConfiguration.getDependencyWaitTime();\r\n\t\t\t\tif (debug)\r\n\t\t\t\t\tlog.debug(\"Setting globally defined wait-for-dependencies/graceperiod timeout value=\" + timeout\r\n\t\t\t\t\t\t\t+ \" ms, for bundle \" + bundleString);\r\n\t\t\t}\r\n\r\n\t\t\tappCtxExecutor.setTimeout(timeout);\r\n\t\t\tappCtxExecutor.setWatchdog(timer);\r\n\t\t\tappCtxExecutor.setTaskExecutor(executor);\r\n\t\t\tappCtxExecutor.setMonitoringCounter(contextsStarted);\r\n\t\t\t// set events publisher\r\n\t\t\tappCtxExecutor.setDelegatedMulticaster(this.multicaster);\r\n\r\n\t\t\tcontextsStarted.increment();\r\n\t\t} else {\r\n\t\t\t// do nothing; by default contexts do not wait for services.\r\n\t\t}\r\n\r\n\t\texecutor.execute(contextRefresh);\r\n\t}\r\n\r\n\t/**\r\n\t * Closing an application context is a potentially long-running activity, however, we *have* to do it synchronously\r\n\t * during the event process as the BundleContext object is not valid once we return from this method.\r\n\t * \r\n\t * @param bundle\r\n\t */\r\n\tprotected void maybeCloseApplicationContextFor(Bundle bundle) {\r\n\t\tfinal ConfigurableOsgiBundleApplicationContext context =\r\n\t\t\t\t(ConfigurableOsgiBundleApplicationContext) managedContexts.remove(Long.valueOf(bundle.getBundleId()));\r\n\t\tif (context == null) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tRunnableTimedExecution.execute(new Runnable() {\r\n\r\n\t\t\tprivate final String toString = \"Closing runnable for context \" + context.getDisplayName();\r\n\r\n\t\t\tpublic void run() {\r\n\t\t\t\tcloseApplicationContext(context);\r\n\t\t\t}\r\n\r\n\t\t\tpublic String toString() {\r\n\t\t\t\treturn toString;\r\n\t\t\t}\r\n\r\n\t\t}, extenderConfiguration.getShutdownWaitTime(), shutdownTaskExecutor);\r\n\t}\r\n\r\n\t/**\r\n\t * Closes an application context. This is a convenience methods that invokes the event notification as well.\r\n\t * \r\n\t * @param ctx\r\n\t */\r\n\tprivate void closeApplicationContext(ConfigurableOsgiBundleApplicationContext ctx) {\r\n\t\tif (log.isDebugEnabled()) {\r\n\t\t\tlog.debug(\"Closing application context \" + ctx.getDisplayName());\r\n\t\t}\r\n\r\n\t\tif (log.isTraceEnabled()) {\r\n\t\t\tlog.trace(\"Calling pre-close on processor \" + processor);\r\n\t\t}\r\n\t\tprocessor.preProcessClose(ctx);\r\n\t\ttry {\r\n\t\t\tctx.close();\r\n\t\t} finally {\r\n\t\t\tif (log.isTraceEnabled()) {\r\n\t\t\t\tlog.trace(\"Calling post close on processor \" + processor);\r\n\t\t\t}\r\n\t\t\tprocessor.postProcessClose(ctx);\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void destroy() {\r\n\t\t// first stop the watchdog\r\n\t\tstopTimer();\r\n\r\n\t\t// get hold of the needed bundles\r\n\t\tList<Bundle> bundles = new ArrayList<Bundle>(managedContexts.size());\r\n\r\n\t\tfor (ConfigurableOsgiBundleApplicationContext context : managedContexts.values()) {\r\n\t\t\tbundles.add(context.getBundle());\r\n\t\t}\r\n\r\n\t\tboolean debug = log.isDebugEnabled();\r\n\r\n\t\tif (debug) {\r\n\t\t\tlog.debug(\"Starting shutdown procedure for bundles \" + bundles);\r\n\t\t}\r\n\t\twhile (!bundles.isEmpty()) {\r\n\t\t\tCollection<Bundle> candidates = ShutdownSorter.getBundles(bundles);\r\n\t\t\tif (debug)\r\n\t\t\t\tlog.debug(\"Staging shutdown for bundles \" + candidates);\r\n\r\n\t\t\tfinal List<Runnable> taskList = new ArrayList<Runnable>(candidates.size());\r\n\t\t\tfinal List<ConfigurableOsgiBundleApplicationContext> closedContexts =\r\n\t\t\t\t\tCollections.synchronizedList(new ArrayList<ConfigurableOsgiBundleApplicationContext>());\r\n\t\t\tfinal Object[] contextClosingDown = new Object[1];\r\n\r\n\t\t\tfor (Bundle shutdownBundle : candidates) {\r\n\t\t\t\tfinal ConfigurableOsgiBundleApplicationContext context = getManagedContext(shutdownBundle);\r\n\t\t\t\tif (context != null) {\r\n\t\t\t\t\tclosedContexts.add(context);\r\n\t\t\t\t\t// add a new runnable\r\n\t\t\t\t\ttaskList.add(new Runnable() {\r\n\r\n\t\t\t\t\t\tprivate final String toString = \"Closing runnable for context \" + context.getDisplayName();\r\n\r\n\t\t\t\t\t\tpublic void run() {\r\n\t\t\t\t\t\t\tcontextClosingDown[0] = context;\r\n\t\t\t\t\t\t\t// eliminate context\r\n\t\t\t\t\t\t\tclosedContexts.remove(context);\r\n\t\t\t\t\t\t\tcloseApplicationContext(context);\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tpublic String toString() {\r\n\t\t\t\t\t\t\treturn toString;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// tasks\r\n\t\t\tfinal Runnable[] tasks = (Runnable[]) taskList.toArray(new Runnable[taskList.size()]);\r\n\r\n\t\t\t// start the ripper >:)\r\n\t\t\tfor (int j = 0; j < tasks.length; j++) {\r\n\t\t\t\tif (RunnableTimedExecution.execute(tasks[j], extenderConfiguration.getShutdownWaitTime(),\r\n\t\t\t\t\t\tshutdownTaskExecutor)) {\r\n\t\t\t\t\tif (debug) {\r\n\t\t\t\t\t\tlog.debug(contextClosingDown[0] + \" context did not close successfully; forcing shutdown...\");\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.managedContexts.clear();\r\n\r\n\t\t// before bailing out; wait for the threads that might be left by\r\n\t\t// the task executor\r\n\t\tstopTaskExecutor();\r\n\t}\r\n\r\n public ConfigurableOsgiBundleApplicationContext getManagedContext(Bundle bundle) {\r\n ConfigurableOsgiBundleApplicationContext context = null;\r\n try {\r\n Long id = new Long(bundle.getBundleId());\r\n context = (ConfigurableOsgiBundleApplicationContext) managedContexts.get(id);\r\n } catch (IllegalStateException _) {\r\n // ignore\r\n }\r\n return context;\r\n }\r\n\r\n\t/**\r\n\t * Do some additional waiting so the service dependency listeners detect the shutdown.\r\n\t */\r\n\tprivate void stopTaskExecutor() {\r\n\t\tboolean debug = log.isDebugEnabled();\r\n\r\n\t\tif (debug)\r\n\t\t\tlog.debug(\"Waiting for \" + contextsStarted + \" service dependency listener(s) to stop...\");\r\n\r\n\t\tcontextsStarted.waitForZero(extenderConfiguration.getShutdownWaitTime());\r\n\r\n\t\tif (!contextsStarted.isZero()) {\r\n\t\t\tif (debug)\r\n\t\t\t\tlog.debug(contextsStarted.getValue()\r\n\t\t\t\t\t\t+ \" service dependency listener(s) did not responded in time; forcing them to shutdown...\");\r\n\t\t\textenderConfiguration.setForceThreadShutdown(true);\r\n\t\t}\r\n\r\n\t\telse\r\n\t\t\tlog.debug(\"All listeners closed\");\r\n\t}\r\n\r\n\t/**\r\n\t * Cancel any tasks scheduled for the timer.\r\n\t */\r\n\tprivate void stopTimer() {\r\n\t\tif (log.isDebugEnabled())\r\n\t\t\tlog.debug(\"Canceling timer tasks\");\r\n\t\ttimer.cancel();\r\n\t}\r\n} >=================================================================== >--- extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java (date 1346404121000) >+++ extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java (revision ) >@@ -14,14 +14,6 @@ > > package org.eclipse.gemini.blueprint.extender.internal.activator; > >-import java.util.ArrayList; >-import java.util.Collection; >-import java.util.Collections; >-import java.util.List; >-import java.util.Map; >-import java.util.Timer; >-import java.util.concurrent.ConcurrentHashMap; >- > import org.apache.commons.logging.Log; > import org.apache.commons.logging.LogFactory; > import org.eclipse.gemini.blueprint.context.ConfigurableOsgiBundleApplicationContext; >@@ -45,6 +37,9 @@ > import org.springframework.core.task.SyncTaskExecutor; > import org.springframework.core.task.TaskExecutor; > >+import java.util.*; >+import java.util.concurrent.ConcurrentHashMap; >+ > /** > * Manager handling the startup/shutdown threading issues regarding OSGi contexts. Used by {@link ContextLoaderListener} > * . >@@ -100,13 +95,13 @@ > private final TypeCompatibilityChecker typeChecker; > > LifecycleManager(ExtenderConfiguration extenderConfiguration, VersionMatcher versionMatcher, >- ApplicationContextConfigurationFactory appCtxCfgFactory, OsgiContextProcessor processor, >+ ApplicationContextConfigurationFactory appCtxCfgFactory, OsgiApplicationContextCreator osgiApplicationContextCreator, OsgiContextProcessor processor, >- TypeCompatibilityChecker checker, BundleContext context) { >+ TypeCompatibilityChecker checker, BundleContext context) { > > this.versionMatcher = versionMatcher; > this.extenderConfiguration = extenderConfiguration; > this.contextConfigurationFactory = appCtxCfgFactory; >- >+ this.contextCreator = osgiApplicationContextCreator; > this.processor = processor; > > this.taskExecutor = extenderConfiguration.getTaskExecutor(); >@@ -114,7 +109,6 @@ > > this.multicaster = extenderConfiguration.getEventMulticaster(); > >- this.contextCreator = extenderConfiguration.getContextCreator(); > this.postProcessors = extenderConfiguration.getPostProcessors(); > this.typeChecker = checker; > >\ No newline at end of file
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 356683
:
202722
|
202769
|
223184
|
223222
|
223234
|
223379