/******************************************************************************
* 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.compendium.internal.cm;
import java.io.IOException;
import java.util.Dictionary;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.gemini.blueprint.util.OsgiServiceUtils;
import org.eclipse.gemini.blueprint.util.internal.MapBasedDictionary;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.DisposableBean;
/**
* Class responsible for interacting with the Configuration Admin service. It handles the retrieval and updates for a
* given persistent id.
*
* @author Costin Leau
* @see org.osgi.service.cm.ConfigurationAdmin
* @see ManagedService
*/
class ConfigurationAdminManager implements DisposableBean {
/**
* Configuration Admin whiteboard 'listener'.
*
* @author Costin Leau
*
*/
private class ConfigurationWatcher implements ManagedService {
public void updated(Dictionary props) throws ConfigurationException {
if (log.isTraceEnabled())
log.trace("Configuration [" + pid + "] has been updated with properties " + props);
synchronized (monitor) {
// update properties
properties = new MapBasedDictionary(props);
// invoke callback
if (beanManager != null)
beanManager.updated(properties);
}
}
}
/** logger */
private static final Log log = LogFactory.getLog(ConfigurationAdminManager.class);
private final BundleContext bundleContext;
private final String pid;
// up to date configuration
private Map properties = null;
private boolean initialized = false;
private ManagedServiceBeanManager beanManager;
private final Object monitor = new Object();
private ServiceRegistration registration;
/**
* Constructs a new <code>ConfigurationAdminManager</code> instance.
*
*/
public ConfigurationAdminManager(String pid, BundleContext bundleContext) {
this.pid = pid;
this.bundleContext = bundleContext;
}
public void setBeanManager(ManagedServiceBeanManager beanManager) {
synchronized (monitor) {
this.beanManager = beanManager;
}
}
/**
* Returns the configuration 'monitored' by this managed.
*
* @return monitored configuration
*/
public Map getConfiguration() {
initialize();
synchronized (monitor) {
return properties;
}
}
/**
* Initializes the conversation with the configuration admin. This method allows for lazy service registration to
* avoid notification being sent w/o any beans requesting it.
*/
private void initialize() {
synchronized (monitor) {
if (initialized)
return;
initialized = true;
// initialize the properties
initProperties();
}
if (log.isTraceEnabled())
log.trace("Initial properties for pid [" + pid + "] are " + properties);
ServiceRegistration reg = CMUtils.registerManagedService(bundleContext, new ConfigurationWatcher(), pid);
synchronized (monitor) {
this.registration = reg;
}
}
private void initProperties() {
try {
//TODO: allow timeout for managed-properties as well
properties = CMUtils.getConfiguration(bundleContext, pid, 0);
} catch (IOException ioe) {
// FIXME: consider adding a custom/different exception
throw new BeanInitializationException("Cannot retrieve configuration for pid=" + pid, ioe);
}
}
public void destroy() {
ServiceRegistration reg = null;
synchronized (monitor) {
reg = this.registration;
this.registration = null;
}
if (OsgiServiceUtils.unregisterService(reg)) {
log.trace("Shutting down CM tracker for pid [" + pid + "]");
}
}
}