/******************************************************************************
* 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;
}
}