/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.aries.subsystem.core.content; import java.io.IOException; import java.io.InputStream; import java.util.Dictionary; import java.util.Map; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import org.apache.aries.subsystem.ContentHandler; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.coordinator.Coordination; import org.osgi.service.subsystem.Subsystem; import org.osgi.util.tracker.ServiceTracker; public class ConfigAdminContentHandler implements ContentHandler { public static final String FELIXCM_CONTENT_TYPE = "felix.cm.config"; public static final String PROPERTIES_CONTENT_TYPE = "osgi.config.properties"; public static final String[] CONTENT_TYPES = {PROPERTIES_CONTENT_TYPE, FELIXCM_CONTENT_TYPE}; private final ServiceTracker<ConfigurationAdmin,ConfigurationAdmin> cmTracker; private final BundleContext ctx; private Map<String, Dictionary<String, Object>> configurations = new ConcurrentHashMap<String, Dictionary<String, Object>>(); public ConfigAdminContentHandler(BundleContext ctx) { this.ctx = ctx; cmTracker = new ServiceTracker<ConfigurationAdmin, ConfigurationAdmin>( ctx, ConfigurationAdmin.class, null); cmTracker.open(); } public void shutDown() { cmTracker.close(); } @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public void install(InputStream is, String symbolicName, String contentType, Subsystem subsystem, Coordination coordination) { Dictionary configuration = null; try { if (PROPERTIES_CONTENT_TYPE.equals(contentType)) { Properties p = new Properties(); p.load(is); configuration = p; } else if (FELIXCM_CONTENT_TYPE.equals(contentType)) { configuration = ConfigurationHandler.read(is); } } catch (IOException e) { coordination.fail(new Exception("Problem loading configuration " + symbolicName + " for subsystem " + subsystem.getSymbolicName(), e)); return; } finally { try { is.close(); } catch (IOException ioe) {} } if (configuration != null) { configurations.put(symbolicName, configuration); } } @Override public void start(String symbolicName, String contentType, Subsystem subsystem, Coordination coordination) { Dictionary<String, Object> configuration = configurations.get(symbolicName); if (configuration == null) { coordination.fail(new Exception("Cannot start configuration " + symbolicName + " for subsystem " + subsystem.getSymbolicName() + " it was not previously loaded")); return; } try { ConfigurationAdmin cm = cmTracker.getService(); if (cm == null) { coordination.fail(new Exception("No Configuration Admin Service found. Cannot apply configuration " + symbolicName + " to subsystem " + subsystem.getSymbolicName())); return; } Configuration[] matchingConfs = cm.listConfigurations( ctx.createFilter("(service.pid=" + symbolicName + ")").toString()); if(matchingConfs == null || matchingConfs.length == 0) { // No configuration exists: create a new one. Configuration conf = cm.getConfiguration(symbolicName, "?"); conf.update(configuration); } // Update has happened, we can forget the configuration data now configurations.remove(symbolicName); } catch(InvalidSyntaxException e) { // Unlikely to happen. coordination.fail(new Exception("Failed to list existing configurations for " + symbolicName + " in subsystem " + subsystem.getSymbolicName(), e)); } catch (IOException e) { coordination.fail(new Exception("Problem applying configuration " + symbolicName + " in subsystem " + subsystem.getSymbolicName(), e)); } } @Override public void stop(String symbolicName, String contentType, Subsystem subsystem) { // We don't remove the configuration on stop, as this is generally not desired. // Specifically, other changes may have been made to the configuration that we // don't want to wipe out. } @Override public void uninstall(String symbolicName, String contentType, Subsystem subsystem) { // Nothing to uninstall } }