/* * Copyright (c) 2006-2008, KNOPFLERFISH project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * - Neither the name of the KNOPFLERFISH project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.knopflerfish.bundle.component; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Dictionary; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleEvent; import org.osgi.framework.Constants; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.framework.SynchronousBundleListener; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.cm.ConfigurationEvent; import org.osgi.service.cm.ConfigurationListener; import org.osgi.service.component.ComponentConstants; class SCR implements SynchronousBundleListener { private Hashtable bundleConfigs = new Hashtable(); private Collection components = new ArrayList(); private Hashtable factoryConfigs = new Hashtable(); private Hashtable serviceConfigs = new Hashtable(); private static long componentId = 0; private static SCR instance; public static void init(BundleContext bc) { if (instance == null) { instance = new SCR(bc); Bundle[] bundles = bc.getBundles(); for(int i=0;i= 0; i--) { String pid = conf[i].getPid(); Component instance = (Component)table.get(pid); if (instance == null) { Config copy = config.copy(); instance = copy.createComponent(); instance.cmUpdated(conf[i].getProperties()); table.put(pid, instance); configs.add(copy); instance.enable(); } } // end factory configuration } else { // regular single configuration conf = admin.listConfigurations("(" + Constants.SERVICE_PID + "=" + name + ")"); if (conf != null && conf.length == 1) { component.cmUpdated(conf[0].getProperties()); } } } catch (InvalidSyntaxException e) { Activator.log.error("The name (" + name + ") must have screwed up the filter.", e); } catch (IOException e) { Activator.log.error("Declarative Services could not retrieve " + "the configuration for component " + name + ". Got IOException.", e); } } private class CMListener implements ConfigurationListener { private Configuration getConfiguration(Component component, String pid) { ConfigurationAdmin admin = getCM(component); if (admin == null) return null; try { Configuration[] conf = admin.listConfigurations("(" + Constants.SERVICE_PID + "=" + pid + ")"); return conf == null ? null : conf[0]; } catch (InvalidSyntaxException e) { Activator.log.error("The PID (" + pid + ") must have screwed up the filter.", e); return null; } catch (IOException e) { Activator.log.error("Declarative Services could not retrieve " + "the configuration for component with pid " + pid + ". Got IOException.", e); return null; } } private void restart(Component component) { restart(component, null); } private void restart(Component component, Configuration configuration) { component.deactivate(); component.unregisterService(); if (configuration != null) { component.cmUpdated(configuration.getProperties()); } else { component.cmDeleted(); removeConfig(component); } component.registerService(); component.activate(); } public void configurationEvent(ConfigurationEvent evt) { String factoryPid = evt.getFactoryPid(); String pid = evt.getPid(); synchronized(SCR.getInstance()){ if (factoryPid != null) { Dictionary table = (Dictionary) factoryConfigs.get(factoryPid); if (table != null) { Component component = (Component)table.get(pid); if (component != null) { if (evt.getType() == ConfigurationEvent.CM_DELETED) { table.remove(pid); if (table.isEmpty()) { factoryConfigs.remove(factoryPid); restart(component); } else { component.disable(); } } else { Configuration conf = getConfiguration(component, pid); if (conf == null) return ; restart(component, conf); } } else { // we need to create a new component Object key = table.keys().nextElement(); Component src = (Component)table.get(key); Config config = src.getConfig(); Config copy = config.copy(); Component instance = copy.createComponent(); Configuration conf = getConfiguration(instance, pid); if (conf == null) return ; instance.cmUpdated(conf.getProperties()); Collection collection = (Collection)bundleConfigs.get(copy.getBundle()); collection.add(copy); instance.enable(); } } else { for (Iterator i = components.iterator(); i.hasNext(); ) { // start looking for a potential target. Component component = (Component)i.next(); Config config = component.getConfig(); if (factoryPid.equals(config.getName())) { // this is a new factory configuration (and has a corresponding component) Configuration conf = getConfiguration(component, pid); if (conf == null) continue; // does not have permission. table = new Hashtable(); factoryConfigs.put(factoryPid, table); table.put(evt.getPid(), component); restart(component, conf); // } } } } } else { // just a regular Single Configuration. for (Iterator i = components.iterator(); i.hasNext(); ) { // start looking for a potential target. Component component = (Component)i.next(); Config config = component.getConfig(); if (pid.equals(config.getName())) { if (evt.getType() == ConfigurationEvent.CM_DELETED) { restart(component); } Configuration conf = getConfiguration(component, pid); if (conf == null) continue ; // might not have permission restart(component, conf); // note that there might be other that matches as well.. } } } } } } }