You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by da...@apache.org on 2006/04/15 14:26:02 UTC
svn commit: r394283 - in /cocoon/trunk/core:
cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/BeanFactoryUtil.java
cocoon-core/src/main/java/org/apache/cocoon/core/osgi/OSGiSpringECMFactory.java
cocoon-webapp/src/main/webapp/Manifest.mf
Author: danielf
Date: Sat Apr 15 05:26:00 2006
New Revision: 394283
URL: http://svn.apache.org/viewcvs?rev=394283&view=rev
Log:
Register Spring managed beans as OSGi services. Singletons and poolable are handled, although I don't know if the later are correctly handled. Ordinary components and selectors are not registered as services yet.
Modified:
cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/BeanFactoryUtil.java
cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/osgi/OSGiSpringECMFactory.java
cocoon/trunk/core/cocoon-webapp/src/main/webapp/Manifest.mf
Modified: cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/BeanFactoryUtil.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/BeanFactoryUtil.java?rev=394283&r1=394282&r2=394283&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/BeanFactoryUtil.java (original)
+++ cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/BeanFactoryUtil.java Sat Apr 15 05:26:00 2006
@@ -76,6 +76,25 @@
BeanFactory parent,
boolean addCocoon)
throws Exception {
+ return createBeanFactory(env, info, resolver, parent, addCocoon, true);
+ }
+
+ /**
+ * Create a new (sub) bean factory.
+ *
+ * @param env The avalon environment.
+ * @param info The avalon configuration.
+ * @param parent The parent factory or null.
+ * @return A new bean factory.
+ * @throws Exception
+ */
+ public static ConfigurableListableBeanFactory createBeanFactory(AvalonEnvironment env,
+ ConfigurationInfo info,
+ SourceResolver resolver,
+ BeanFactory parent,
+ boolean addCocoon,
+ boolean preInstantiateSingletons)
+ throws Exception {
final String xmlConfig = (new XmlConfigCreator(env.logger)).createConfig(info, addCocoon);
Resource rsc = new ByteArrayResource(xmlConfig.getBytes("utf-8"));
Logger logger = env.logger;
@@ -96,7 +115,9 @@
factory.registerSingleton(SourceResolver.ROLE + "/Local", resolver);
}
prepareBeanFactory(factory, info);
- factory.preInstantiateSingletons();
+ if (preInstantiateSingletons) {
+ factory.preInstantiateSingletons();
+ }
return factory;
}
Modified: cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/osgi/OSGiSpringECMFactory.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/osgi/OSGiSpringECMFactory.java?rev=394283&r1=394282&r2=394283&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/osgi/OSGiSpringECMFactory.java (original)
+++ cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/core/osgi/OSGiSpringECMFactory.java Sat Apr 15 05:26:00 2006
@@ -17,10 +17,14 @@
import java.beans.PropertyEditor;
import java.net.URL;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
import java.util.Map;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceSelector;
import org.apache.cocoon.core.CoreUtil;
import org.apache.cocoon.core.Settings;
import org.apache.cocoon.core.container.spring.AvalonEnvironment;
@@ -29,13 +33,19 @@
import org.apache.cocoon.core.container.spring.ConfigurationInfo;
import org.apache.cocoon.environment.Context;
import org.apache.excalibur.store.Store;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
/**
* The @link {@link OSGiSpringECMFactory} gives access to all Spring beans via the
@@ -54,6 +64,7 @@
private Logger logger;
private Settings settings;
private ConfigurableListableBeanFactory beanFactory;
+ private ComponentContext componentContext;
protected Settings getSettings() {
return this.settings;
@@ -75,6 +86,7 @@
* TODO (DF/RP) move activation into a seperate thread
*/
protected void activate(ComponentContext componentContext) throws Exception {
+ this.componentContext = componentContext;
URL manifestUrl = componentContext.getBundleContext().getBundle().getEntry(MANIFEST_FILE);
String contextPath = manifestUrl.toString();
contextPath = manifestUrl.toString().substring(0, contextPath.length() - (MANIFEST_FILE.length() - 1));
@@ -103,11 +115,142 @@
ConfigurableListableBeanFactory rootBeanFactory = BeanFactoryUtil.createRootBeanFactory(avalonEnvironment);
ConfigurationInfo springBeanConfiguration = ConfigReader.readConfiguration(configFile, avalonEnvironment);
this.beanFactory = BeanFactoryUtil.createBeanFactory(avalonEnvironment, springBeanConfiguration,
- null, rootBeanFactory, true);
+ null, rootBeanFactory, false, false);
+ this.beanFactory.addBeanPostProcessor(new ServiceRegistrationPostProcessor());
+ this.beanFactory.preInstantiateSingletons();
Store store = (Store) beanFactory.getBean(Store.ROLE);
this.logger.debug("Store: " + store);
}
-
+
+ protected void deactivate(ComponentContext componentContext) {
+ this.beanFactory.destroySingletons();
+ }
+
+ public static String getServiceInterface(String role) {
+ int pos = role.indexOf('/');
+
+ return pos == -1 ? role : role.substring(0, pos);
+ }
+
+ public static String getServiceHint(String role) {
+ int pos = role.indexOf('/');
+ return pos == -1 ? null : role.substring(pos+1);
+ }
+
+ private class ServiceRegistrationPostProcessor implements DestructionAwareBeanPostProcessor {
+ private static final String HINT_PROPERTY = "component.hint";
+ private BundleContext bundleContext =
+ OSGiSpringECMFactory.this.componentContext.getBundleContext();
+ /** Mapping from service instance to ServiceReference */
+ private Map serviceRegistrations = new HashMap();
+
+ public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
+ if (isServiceSelector(bean)) {
+ info("ServiceSelector destruction: ", bean, beanName);
+ } else if (isSingleton(beanName)) {
+ synchronized (this) {
+ ServiceRegistration registration =
+ (ServiceRegistration) this.serviceRegistrations.remove(beanName);
+ if (registration != null)
+ registration.unregister();
+ }
+ info("Singleton destruction: ", bean, beanName);
+ } else if (isFactoryBean(bean)) {
+ synchronized (this) {
+ ServiceRegistration registration =
+ (ServiceRegistration) this.serviceRegistrations.remove(beanName);
+ if (registration != null)
+ registration.unregister();
+ }
+ info("Factory bean destruction: ", bean, beanName);
+ } else {
+ info("========= destruction: ", bean, beanName);
+ }
+ }
+
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ String itfName = getServiceInterface(beanName);
+ String hint = getServiceHint(beanName);
+ Dictionary properties = null;
+ if (hint != null) {
+ properties = new Hashtable();
+ properties.put(HINT_PROPERTY, hint);
+ }
+ if (isServiceSelector(bean)) {
+ // TODO implement
+ info("ServiceSelector initialization: ", bean, beanName);
+ } else if (isSingleton(beanName)) {
+ // register the bean into the OSGi service registry
+ logger.debug("Register interface=" + itfName + " hint=" + hint + " service=" + bean);
+ ServiceRegistration registration =
+ this.bundleContext.registerService(itfName, bean, properties);
+ synchronized (this) {
+ // keep track on registred services
+ this.serviceRegistrations.put(beanName, registration);
+ }
+ info("Singleton initialization: ", bean, beanName);
+ } else if (isFactoryBean(bean)) {
+ Object service = new FactoryBeanServiceFactory((FactoryBean) bean);
+ ServiceRegistration registration =
+ this.bundleContext.registerService(beanName, service, properties);
+ synchronized (this) {
+ // keep track on registred services
+ this.serviceRegistrations.put(beanName, registration);
+ }
+ info("Factory bean initialization: ", bean, beanName);
+ } else {
+ // TODO some kind of proxy or factory is needed for components that
+ // are not singletons
+ info("========= initialization: ", bean, beanName);
+ }
+ return bean;
+ }
+
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ return bean;
+ }
+
+ public boolean isFactoryBean(Object bean) {
+ return bean instanceof FactoryBean;
+ }
+
+ public boolean isServiceSelector(Object bean) {
+ return bean instanceof ServiceSelector;
+ }
+
+ private void info(String info, Object bean, String beanName) {
+ Class beanClass = getType(beanName);
+ logger.debug(info + beanName +
+ " singleton=" + isSingleton(beanName) +
+ " beanFactory=" + isFactoryBean(bean) +
+ " class=" + beanClass);
+ }
+
+ // Embed a Spring FactoryBean as an OSGi ServiceFactory
+ public class FactoryBeanServiceFactory implements ServiceFactory {
+ private FactoryBean factoryBean;
+
+ public FactoryBeanServiceFactory(FactoryBean factoryBean) {
+ this.factoryBean = factoryBean;
+ }
+
+ public Object getService(Bundle bundle, ServiceRegistration registration) {
+ try {
+ // FIXME the OSGi contracts require IIUC, that the returned object is
+ // a singleton that can be cached, don't know if this is fullfilled.
+ return this.factoryBean.getObject();
+ } catch (Exception e) {
+ throw new RuntimeException("Cannot get service", e);
+ }
+ }
+
+ // The FactoryBean have no method for returning the bean to the manager
+ public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
+
+ }
+ }
+ }
+
// ~~~~~~~~~~~~~~~ delegating to this.beanFactory ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
Modified: cocoon/trunk/core/cocoon-webapp/src/main/webapp/Manifest.mf
URL: http://svn.apache.org/viewcvs/cocoon/trunk/core/cocoon-webapp/src/main/webapp/Manifest.mf?rev=394283&r1=394282&r2=394283&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-webapp/src/main/webapp/Manifest.mf (original)
+++ cocoon/trunk/core/cocoon-webapp/src/main/webapp/Manifest.mf Sat Apr 15 05:26:00 2006
@@ -4,6 +4,7 @@
Bundle-Name: cocoon_webapp
Bundle-SymbolicName: org.apache.cocoon:cocoon_webapp:1.0.0
Bundle-Version: 1.0.0
+Service-Component: META-INF/components.xml
Bundle-Description: Cocoon webapp
Bundle-Vendor: Apache
Bundle-DocURL: http://cocoon.apache.org