/****************************************************************************** * 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.blueprint.container.support; import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Dictionary; import java.util.Hashtable; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.gemini.blueprint.context.support.internal.security.SecurityUtils; import org.eclipse.gemini.blueprint.util.OsgiBundleUtils; import org.eclipse.gemini.blueprint.util.OsgiServiceUtils; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceRegistration; import org.osgi.framework.Version; import org.osgi.service.blueprint.container.BlueprintContainer; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ApplicationContextEvent; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.util.ObjectUtils; /** * Infrastructure bean that automatically publishes the given ModuleContext as an OSGi service. The bean listens for the * start/stop events inside an {@link ApplicationContext} to register/unregister the equivalent service. * * <b>Note:</b> This component is stateful and should not be shared by multiple threads. * * @author Costin Leau * */ public class BlueprintContainerServicePublisher implements ApplicationListener<ApplicationContextEvent> { /** logger */ private static final Log log = LogFactory.getLog(BlueprintContainerServicePublisher.class); private static final String BLUEPRINT_SYMNAME = "osgi.blueprint.container.symbolicname"; private static final String BLUEPRINT_VERSION = "osgi.blueprint.container.version"; private final BlueprintContainer blueprintContainer; private final BundleContext bundleContext; /** registration */ private volatile ServiceRegistration registration; /** * Constructs a new <code>ModuleContextServicePublisher</code> instance. * * @param blueprintContainer * @param bundleContext */ public BlueprintContainerServicePublisher(BlueprintContainer blueprintContainer, BundleContext bundleContext) { this.blueprintContainer = blueprintContainer; this.bundleContext = bundleContext; } public void onApplicationEvent(ApplicationContextEvent event) { // publish if (event instanceof ContextRefreshedEvent) { registerService(event.getApplicationContext()); } else if (event instanceof ContextClosedEvent) { unregisterService(); } } private void registerService(ApplicationContext applicationContext) { final Dictionary<String, Object> serviceProperties = new Hashtable<String, Object>(); Bundle bundle = bundleContext.getBundle(); String symName = bundle.getSymbolicName(); serviceProperties.put(Constants.BUNDLE_SYMBOLICNAME, symName); serviceProperties.put(BLUEPRINT_SYMNAME, symName); Version version = OsgiBundleUtils.getBundleVersion(bundle); serviceProperties.put(Constants.BUNDLE_VERSION, version); serviceProperties.put(BLUEPRINT_VERSION, version); log.info("Publishing BlueprintContainer as OSGi service with properties " + serviceProperties); // export just the interface final String[] serviceNames = new String[] { BlueprintContainer.class.getName() }; if (log.isDebugEnabled()) log.debug("Publishing service under classes " + ObjectUtils.nullSafeToString(serviceNames)); AccessControlContext acc = SecurityUtils.getAccFrom(applicationContext); // publish service if (System.getSecurityManager() != null) { registration = AccessController.doPrivileged(new PrivilegedAction<ServiceRegistration>() { public ServiceRegistration run() { return bundleContext.registerService(serviceNames, blueprintContainer, serviceProperties); } }, acc); } else { registration = bundleContext.registerService(serviceNames, blueprintContainer, serviceProperties); } } private void unregisterService() { OsgiServiceUtils.unregisterService(registration); registration = null; } }