/****************************************************************************** * 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 + "]"); } } }