X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;ds=sidebyside;f=runtime%2Forg.argeo.slc.support.osgi%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Fosgi%2FMultipleServiceExporterPostProcessor.java;fp=runtime%2Forg.argeo.slc.support.osgi%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Fosgi%2FMultipleServiceExporterPostProcessor.java;h=928afe23511dcb27d980f1058389cd023e0363ab;hb=9e11f73baa256ba66457e82fc02bbc5f0851b1ef;hp=d457c3b4b8a5234c99ac7119c19460492bd962e7;hpb=4561bb7f9576886492d195fbe0a6f393c8ded349;p=gpl%2Fargeo-slc.git diff --git a/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/MultipleServiceExporterPostProcessor.java b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/MultipleServiceExporterPostProcessor.java index d457c3b4b..928afe235 100644 --- a/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/MultipleServiceExporterPostProcessor.java +++ b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/MultipleServiceExporterPostProcessor.java @@ -17,87 +17,129 @@ package org.argeo.slc.osgi; import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; +import java.util.HashMap; import java.util.List; -import java.util.Set; +import java.util.Map; +import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.springframework.beans.BeansException; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.RootBeanDefinition; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.core.Ordered; -import org.springframework.osgi.service.exporter.support.ExportContextClassLoader; -import org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean; -@SuppressWarnings(value = { "unchecked" }) +/** Publishes beans of the application context as OSGi services. */ +@SuppressWarnings(value = { "unchecked", "rawtypes" }) public class MultipleServiceExporterPostProcessor implements - BeanFactoryPostProcessor, Ordered { + ApplicationListener, Ordered { private final static Log log = LogFactory .getLog(MultipleServiceExporterPostProcessor.class); private List interfaces = new ArrayList(); - private Class osgiServiceFactoryClass = OsgiServiceFactoryBean.class; - - private Boolean useServiceProviderContextClassLoader = false; - private int order = Ordered.LOWEST_PRECEDENCE; - public void postProcessBeanFactory( - ConfigurableListableBeanFactory beanFactory) throws BeansException { - if (!(beanFactory instanceof BeanDefinitionRegistry)) { - throw new SlcException("Can only work on " - + BeanDefinitionRegistry.class); - } - - long begin = System.currentTimeMillis(); - - // Merge all beans implementing these interfaces - Set beanNames = new HashSet(); - for (Class clss : interfaces) { - String[] strs = beanFactory.getBeanNamesForType(clss, true, false); - beanNames.addAll(Arrays.asList(strs)); - } - - // Register service factory beans for them - for (String beanName : beanNames) { - MutablePropertyValues mpv = new MutablePropertyValues(); - mpv.addPropertyValue("interfaces", interfaces.toArray()); - mpv.addPropertyValue("targetBeanName", beanName); - if (useServiceProviderContextClassLoader) - mpv.addPropertyValue("contextClassLoader", - ExportContextClassLoader.SERVICE_PROVIDER); - RootBeanDefinition bd = new RootBeanDefinition( - osgiServiceFactoryClass, mpv); - - String exporterBeanName = "osgiService." + beanName; - if (log.isTraceEnabled()) - log.debug("Registering OSGi service exporter " - + exporterBeanName); - ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition( - exporterBeanName, bd); + private BundleContext bundleContext = null; + + // private Class osgiServiceFactoryClass = OsgiServiceFactoryBean.class; + // private Boolean useServiceProviderContextClassLoader = false; + + public void onApplicationEvent(ApplicationEvent event) { + Map beans = new HashMap(); + if (event instanceof ContextRefreshedEvent) { + if (bundleContext != null) { + for (Class clss : interfaces) { + ApplicationContext ac = ((ContextRefreshedEvent) event) + .getApplicationContext(); + beans.putAll(ac.getBeansOfType(clss, false, false)); + } + + int count = 0; + for (String beanName : beans.keySet()) { + Object bean = beans.get(beanName); + List classes = new ArrayList(); + for (Class clss : interfaces) { + if (clss.isAssignableFrom(bean.getClass())) { + classes.add(clss.getName()); + } + } + Properties props = new Properties(); + Bundle bundle = bundleContext.getBundle(); + props.put(Constants.BUNDLE_SYMBOLICNAME, + bundle.getSymbolicName()); + props.put(Constants.BUNDLE_VERSION, bundle.getVersion()); + // retrocompatibility with pre-1.0: + props.put("org.springframework.osgi.bean.name", beanName); + bundleContext.registerService( + classes.toArray(new String[classes.size()]), bean, + props); + count++; + } + if (log.isTraceEnabled()) + log.trace("Published " + count + " " + interfaces + + " as OSGi services from bundle " + + bundleContext.getBundle().getSymbolicName() + " " + + bundleContext.getBundle().getVersion()); + // note: the services will be automatically unregistered when + // the bundle will be stopped + } } - - long end = System.currentTimeMillis(); - if (log.isTraceEnabled()) - log.debug("Multiple services exported in " + (end - begin) - + " ms in bundle."); - } + // public void postProcessBeanFactory( + // ConfigurableListableBeanFactory beanFactory) throws BeansException { + // if (!(beanFactory instanceof BeanDefinitionRegistry)) { + // throw new SlcException("Can only work on " + // + BeanDefinitionRegistry.class); + // } + // + // long begin = System.currentTimeMillis(); + // + // // Merge all beans implementing these interfaces + // Set beanNames = new HashSet(); + // for (Class clss : interfaces) { + // String[] strs = beanFactory.getBeanNamesForType(clss, true, false); + // beanNames.addAll(Arrays.asList(strs)); + // } + // + // // Register service factory beans for them + // for (String beanName : beanNames) { + // MutablePropertyValues mpv = new MutablePropertyValues(); + // mpv.addPropertyValue("interfaces", interfaces.toArray()); + // mpv.addPropertyValue("targetBeanName", beanName); + // if (useServiceProviderContextClassLoader) + // mpv.addPropertyValue("contextClassLoader", + // ExportContextClassLoader.SERVICE_PROVIDER); + // RootBeanDefinition bd = new RootBeanDefinition( + // osgiServiceFactoryClass, mpv); + // + // String exporterBeanName = "osgiService." + beanName; + // if (log.isTraceEnabled()) + // log.debug("Registering OSGi service exporter " + // + exporterBeanName); + // ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition( + // exporterBeanName, bd); + // } + // + // long end = System.currentTimeMillis(); + // if (log.isTraceEnabled()) + // log.debug("Multiple services exported in " + (end - begin) + // + " ms in bundle."); + // + // } + public void setInterfaces(List interfaces) { this.interfaces = interfaces; } - public void setOsgiServiceFactoryClass(Class osgiServiceFactoryClass) { - this.osgiServiceFactoryClass = osgiServiceFactoryClass; - } + // public void setOsgiServiceFactoryClass(Class osgiServiceFactoryClass) { + // this.osgiServiceFactoryClass = osgiServiceFactoryClass; + // } public int getOrder() { return order; @@ -107,9 +149,13 @@ public class MultipleServiceExporterPostProcessor implements this.order = order; } - public void setUseServiceProviderContextClassLoader( - Boolean useServiceProviderContextClassLoader) { - this.useServiceProviderContextClassLoader = useServiceProviderContextClassLoader; - } + // public void setUseServiceProviderContextClassLoader( + // Boolean useServiceProviderContextClassLoader) { + // this.useServiceProviderContextClassLoader = + // useServiceProviderContextClassLoader; + // } + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } }