Author: norman
Date: Thu Jul  7 06:39:31 2011
New Revision: 1143674

URL: http://svn.apache.org/viewvc?rev=1143674&view=rev
Log:
Make sure we register services in the BeanDefinationRegistry and in the 
OSGI-Registry. So spring can do its job and wire everything together. See 
JAMES-835

Modified:
    
james/server/trunk/container-spring/src/main/java/org/apache/james/container/spring/osgi/AbstractServiceTracker.java

Modified: 
james/server/trunk/container-spring/src/main/java/org/apache/james/container/spring/osgi/AbstractServiceTracker.java
URL: 
http://svn.apache.org/viewvc/james/server/trunk/container-spring/src/main/java/org/apache/james/container/spring/osgi/AbstractServiceTracker.java?rev=1143674&r1=1143673&r2=1143674&view=diff
==============================================================================
--- 
james/server/trunk/container-spring/src/main/java/org/apache/james/container/spring/osgi/AbstractServiceTracker.java
 (original)
+++ 
james/server/trunk/container-spring/src/main/java/org/apache/james/container/spring/osgi/AbstractServiceTracker.java
 Thu Jul  7 06:39:31 2011
@@ -19,10 +19,7 @@
 package org.apache.james.container.spring.osgi;
 
 import java.net.URL;
-import java.util.ArrayList;
 import java.util.Enumeration;
-import java.util.List;
-import java.util.Properties;
 
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.container.spring.lifecycle.ConfigurationProvider;
@@ -30,38 +27,37 @@ import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
 import org.osgi.framework.BundleListener;
-import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.BeanFactory;
 import org.springframework.beans.factory.BeanFactoryAware;
 import org.springframework.beans.factory.DisposableBean;
 import org.springframework.beans.factory.InitializingBean;
-import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
 import org.springframework.context.ApplicationContext;
 import org.springframework.osgi.context.BundleContextAware;
+import 
org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext;
 import org.springframework.osgi.service.exporter.OsgiServicePropertiesResolver;
-import 
org.springframework.osgi.service.exporter.support.BeanNameServicePropertiesResolver;
+import 
org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean;
 
 /**
  * This {@link BundleListener} use the extender pattern to scan all loaded
  * bundles if a class name with a given name is present. If so it register in
- * the {@link BeanDefinitionRegistry} and also register it to
- * {@link BundleContext} as service. This allows to dynamic load and unload 
OSGI
- * bundles
+ * the {@link BeanDefinitionRegistry} and also register it to the OSG-Registry 
via an {@link OsgiServiceFactoryBean}
  * 
  */
 public abstract class AbstractServiceTracker implements BeanFactoryAware, 
BundleListener, BundleContextAware, InitializingBean, DisposableBean {
 
     private BundleContext context;
     private String configuredClass;
-    private final List<ServiceRegistration> reg = new 
ArrayList<ServiceRegistration>();
+    private volatile OsgiServiceFactoryBean osgiFactoryBean;
     private BeanFactory factory;
-
+    private Logger logger = 
LoggerFactory.getLogger(AbstractServiceTracker.class);
+    
     @Override
     public void setBeanFactory(BeanFactory factory) throws BeansException {
         this.factory = factory;
@@ -72,7 +68,6 @@ public abstract class AbstractServiceTra
         this.context = context;
     }
 
-    @SuppressWarnings("unchecked")
     @Override
     public void bundleChanged(BundleEvent event) {
         Bundle b = event.getBundle();
@@ -87,49 +82,45 @@ public abstract class AbstractServiceTra
             Enumeration<?> entrs = b.findEntries("/", "*.class", true);
             if (entrs != null) {
 
-                // Loop over all the classes 
+                // Loop over all the classes
                 while (entrs.hasMoreElements()) {
                     URL e = (URL) entrs.nextElement();
                     String file = e.getFile();
 
                     String className = file.replaceAll("/", 
".").replaceAll(".class", "").replaceFirst(".", "");
                     if (className.equals(configuredClass)) {
-                        BeanFactory bFactory = 
getBeanFactory(b.getBundleContext());
-                        // Get the right service properties from the resolver
-                        Properties p = new Properties();
-
-                        // Setup a resolver
-                        BeanNameServicePropertiesResolver resolver = new 
BeanNameServicePropertiesResolver();
-                        resolver.setBundleContext(b.getBundleContext());
-
-                        
-                        
p.putAll(resolver.getServiceProperties(getComponentName()));
-                        Class<?> clazz = getServiceClass();
-                        
-                        // Create the definition and register it
-                        BeanDefinitionRegistry registry = 
(BeanDefinitionRegistry) bFactory;
-                        BeanDefinition def = 
BeanDefinitionBuilder.genericBeanDefinition(className).getBeanDefinition();
-                        registry.registerBeanDefinition(getComponentName(), 
def);
+                        try {
+
+                            BeanFactory bFactory = 
getBeanFactory(b.getBundleContext());
+                            Class<?> clazz = getServiceClass();
 
-                        // register the bean as service in the BundleContext
-                        
reg.add(b.getBundleContext().registerService(clazz.getName(), 
bFactory.getBean(getComponentName(), clazz), p));
+                            // Create the definition and register it
+                            BeanDefinitionRegistry registry = 
(BeanDefinitionRegistry) bFactory;
+                            BeanDefinition def = 
BeanDefinitionBuilder.genericBeanDefinition(className).getBeanDefinition();
+                            
registry.registerBeanDefinition(getComponentName(), def);
+
+                            // register the bean as service in the 
OSGI-Registry
+                            osgiFactoryBean = new OsgiServiceFactoryBean();
+                            
osgiFactoryBean.setTargetBeanName(getComponentName());
+                            osgiFactoryBean.setBeanFactory(bFactory);
+                            
osgiFactoryBean.setBundleContext(b.getBundleContext());
+                            osgiFactoryBean.setInterfaces(new Class[] { clazz 
});
+                            osgiFactoryBean.afterPropertiesSet();
+                            logger.debug("Registered " + configuredClass + " 
in the OSGI-Registry with interface " + clazz.getName());
+                        } catch (Exception e1) {
+                            logger.error("Unable to register " + 
configuredClass + " in the OSGI-Registry", e1);
+                        }
                     }
                 }
             }
             break;
         case BundleEvent.STOPPED:
-            if (reg != null) {
-                List<ServiceRegistration> removed = new 
ArrayList<ServiceRegistration>();
-                for (int i = 0; i < reg.size(); i++) {
-                    ServiceRegistration sr = reg.get(i);
-                    // Check if we need to unregister the service
-                    if (b.equals(sr.getReference().getBundle())) {
-                        sr.unregister();
-                        removed.add(sr);
-                    } 
-                }
-                reg.removeAll(removed);
-               
+            // check if we need to destroy the OsgiFactoryBean. This also 
include the unregister from the OSGI-Registry
+            if (osgiFactoryBean != null) {
+                osgiFactoryBean.destroy();
+                osgiFactoryBean = null;
+                logger.debug("Unregistered " + configuredClass + " in the 
OSGI-Registry with interface " + getServiceClass().getName());
+
             }
             break;
         default:
@@ -138,20 +129,33 @@ public abstract class AbstractServiceTra
 
     }
 
-    private static AutowireCapableBeanFactory getBeanFactory(final 
BundleContext bundleContext) {
+    
+    /**
+     * Return the {@link BeanFactory} for the given {@link BundleContext}. If 
none can be found we just create a new {@link 
AbstractDelegatedExecutionApplicationContext} and return the {@link 
BeanFactory} of it
+     * 
+     * 
+     * @param bundleContext
+     * @return factory
+     * @throws Exception
+     */
+    private BeanFactory getBeanFactory(final BundleContext bundleContext) 
throws Exception {
         final String filter = "(" + 
OsgiServicePropertiesResolver.BEAN_NAME_PROPERTY_KEY + "=" + 
bundleContext.getBundle().getSymbolicName() + ")";
-        final ServiceReference[] applicationContextRefs;       
-        try {
-            applicationContextRefs = 
bundleContext.getServiceReferences(ApplicationContext.class.getName(), filter);
-        } catch (final InvalidSyntaxException e) {
-            throw new RuntimeException(e);
-        }
-       
-        if(applicationContextRefs.length != 1) {
-            return null;
+        final ServiceReference[] applicationContextRefs = 
bundleContext.getServiceReferences(ApplicationContext.class.getName(), filter);
+        
+        // Check if we found an ApplicationContext. If not create one
+        if(applicationContextRefs == null || applicationContextRefs.length != 
1) {
+            
+            // Create a new context which just serve as registry later
+            AbstractDelegatedExecutionApplicationContext context = new 
AbstractDelegatedExecutionApplicationContext() {
+            };
+            context.setBundleContext(bundleContext);
+            context.setPublishContextAsService(true);
+            context.refresh();
+            return context.getBeanFactory();
+        } else {
+            return ((ApplicationContext) 
bundleContext.getService(applicationContextRefs[0])).getAutowireCapableBeanFactory();
         }
        
-        return ((ApplicationContext) 
bundleContext.getService(applicationContextRefs[0])).getAutowireCapableBeanFactory();
        
     }
 



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to