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