blob: 3f057863e3fc75f5fdc93b7b18f18384974e7090 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.karaf.config.core.impl;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Map;
import org.apache.felix.cm.json.Configurations;
import org.apache.felix.utils.properties.TypedProperties;
import org.apache.karaf.config.core.ConfigRepository;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ConfigRepositoryImpl implements ConfigRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigRepositoryImpl.class);
private static final String FILEINSTALL_FILE_NAME = "felix.fileinstall.filename";
private ConfigurationAdmin configAdmin;
public ConfigRepositoryImpl(ConfigurationAdmin configAdmin) {
this.configAdmin = configAdmin;
}
@Override
public void update(String pid, Map<String, Object> properties) throws IOException {
update(pid, properties, "cfg");
}
/* (non-Javadoc)
* @see org.apache.karaf.shell.config.impl.ConfigRepository#update(java.lang.String, java.util.Dictionary, boolean)
*/
@Override
public void update(String pid, Map<String, Object> properties, String suffix) throws IOException {
try {
LOGGER.trace("Updating configuration {}", pid);
Configuration cfg = configAdmin.getConfiguration(pid, "?");
Dictionary<String, Object> dict = cfg.getProcessedProperties(null);
TypedProperties props = new TypedProperties();
File file = getCfgFileFromProperties(dict);
if (file != null) {
props = load(file);
props.putAll(properties);
props.keySet().retainAll(properties.keySet());
store(props, file);
props.clear();
props = load(file);
props.put(FILEINSTALL_FILE_NAME, file.toURI().toString());
} else {
if (properties.containsKey(FILEINSTALL_FILE_NAME)) {
file = getCfgFileFromProperty(properties.get(FILEINSTALL_FILE_NAME));
}
if (file == null) {
file = generateConfigFilename(cfg, suffix);
}
props.putAll(properties);
props.keySet().retainAll(properties.keySet());
store(props, file);
props.put(FILEINSTALL_FILE_NAME, file.toURI().toString());
}
cfg.update(new Hashtable<>(props));
} catch (URISyntaxException e) {
throw new IOException("Error updating config", e);
}
}
private static File generateConfigFilename(Configuration cfg, String suffix) {
final String pid = cfg.getPid();
final String factoryPid = cfg.getFactoryPid();
String fName;
if(factoryPid!=null) {
//pid = <factoryPid>.<identifier>
String identifier = pid.substring(factoryPid.length()+1);
fName = cfg.getFactoryPid() + "-"+identifier+ "." + suffix;
}
else {
fName = pid + "." + suffix;
}
return new File(System.getProperty("karaf.etc"), fName);
}
/* (non-Javadoc)
* @see org.apache.karaf.shell.config.impl.ConfigRepository#delete(java.lang.String)
*/
@Override
public void delete(String pid) throws Exception {
LOGGER.trace("Deleting configuration {}", pid);
Configuration configuration = configAdmin.getConfiguration(pid, null);
configuration.delete();
}
@Override
public boolean exists(String pid) throws Exception {
Configuration[] configurations = configAdmin.listConfigurations("(service.pid=" + pid + ")");
if (configurations == null || configurations.length == 0) {
return false;
}
return true;
}
private File getCfgFileFromProperties(Dictionary<String, Object> properties) throws URISyntaxException, MalformedURLException {
if (properties != null) {
Object val = properties.get(FILEINSTALL_FILE_NAME);
return getCfgFileFromProperty(val);
}
return null;
}
private File getCfgFileFromProperty(Object val) throws URISyntaxException, MalformedURLException {
if (val instanceof URL) {
return new File(((URL) val).toURI());
}
if (val instanceof URI) {
return new File((URI) val);
}
if (val instanceof String) {
return new File(new URL((String) val).toURI());
}
return null;
}
@Override
public TypedProperties getConfig(String pid) throws IOException, InvalidSyntaxException {
if (pid != null && configAdmin != null) {
Configuration configuration = configAdmin.getConfiguration(pid, null);
if (configuration != null) {
TypedProperties tp = new TypedProperties();
Dictionary<String, Object> props = configuration.getProcessedProperties(null);
if (props != null) {
File file;
try {
file = getCfgFileFromProperties(props);
} catch (URISyntaxException e) {
throw new IOException(e);
}
if (file != null && file.exists()) {
tp = load(file);
Object fileInstallFileName = props.get(FILEINSTALL_FILE_NAME);
if (fileInstallFileName != null && !"".equals(fileInstallFileName)) {
tp.put(FILEINSTALL_FILE_NAME, fileInstallFileName);
}
} else {
for (Enumeration<String> e = props.keys(); e.hasMoreElements();) {
String key = e.nextElement();
Object val = props.get(key);
tp.put(key, val);
}
tp.remove(Constants.SERVICE_PID);
tp.remove(ConfigurationAdmin.SERVICE_FACTORYPID);
}
}
return tp;
}
}
return null;
}
@Override
public String createFactoryConfiguration(String factoryPid, Map<String, Object> properties) throws IOException {
return createFactoryConfiguration(factoryPid, null, properties, "cfg");
}
@Override
public String createFactoryConfiguration(String factoryPid, Map<String, Object> properties, String suffix) throws IOException {
return createFactoryConfiguration(factoryPid, null, properties, suffix);
}
@Override
public String createFactoryConfiguration(String factoryPid, String alias, Map<String, Object> properties) throws IOException {
return createFactoryConfiguration(factoryPid, alias, properties, "cfg");
}
@Override
public String createFactoryConfiguration(String factoryPid, String alias, Map<String, Object> properties, String suffix) throws IOException {
Configuration config = configAdmin.createFactoryConfiguration(factoryPid, "?");
TypedProperties props = new TypedProperties();
File file = null;
if (alias != null && !"".equals(alias.trim())) {
file = new File(new File(System.getProperty("karaf.etc")), factoryPid + "-" + alias + "." + suffix);
} else {
file = Files.createTempFile(new File(System.getProperty("karaf.etc")).toPath(), factoryPid + "-", "." + suffix).toFile();
}
props.putAll(properties);
store(props, file);
props.put(FILEINSTALL_FILE_NAME, file.toURI().toString());
config.update(new Hashtable<>(props));
return config.getPid();
}
@Override
public ConfigurationAdmin getConfigAdmin() {
return configAdmin;
}
static TypedProperties load(File file) throws IOException {
TypedProperties props = new TypedProperties();
if (file.toURI().toString().endsWith(".json")) {
Hashtable<String, Object> configuration = Configurations.buildReader().build(new FileReader(file)).readConfiguration();
for (String key : configuration.keySet()) {
props.put(key, configuration.get(key));
}
} else {
props.load(file);
}
return props;
}
void store(TypedProperties properties, File file) throws IOException {
if (file.toURI().toString().endsWith(".json")) {
Configurations.buildWriter().build(new FileWriter(file)).writeConfiguration(new Hashtable<>(properties));
} else {
properties.save(file);
}
}
}