You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2014/04/10 16:15:45 UTC
[23/59] [abbrv] [KARAF-2852] Merge config/core and config/command
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java
----------------------------------------------------------------------
diff --git a/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java b/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java
deleted file mode 100644
index a8b8090..0000000
--- a/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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.karaf.config.core.impl;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-
-import javax.management.MBeanException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.StandardMBean;
-
-import org.apache.karaf.config.core.ConfigMBean;
-import org.apache.karaf.config.core.ConfigRepository;
-import org.osgi.service.cm.Configuration;
-
-/**
- * Implementation of the ConfigMBean.
- */
-public class ConfigMBeanImpl extends StandardMBean implements ConfigMBean {
-
- private ConfigRepository configRepo;
-
- public ConfigMBeanImpl() throws NotCompliantMBeanException {
- super(ConfigMBean.class);
- }
-
- private Configuration getConfiguration(String pid) throws IOException {
- Configuration configuration = configRepo.getConfigAdmin().getConfiguration(pid);
- if (configuration == null) {
- throw new IllegalArgumentException("Configuration PID " + pid + " doesn't exist");
- }
- return configuration;
- }
-
- @SuppressWarnings("rawtypes")
- private Dictionary getConfigProperties(String pid) throws IOException {
- Configuration configuration = getConfiguration(pid);
-
- Dictionary dictionary = configuration.getProperties();
- if (dictionary == null) {
- dictionary = new java.util.Properties();
- }
- return dictionary;
- }
-
- /**
- * Get all config pids
- */
- public List<String> getConfigs() throws MBeanException {
- try {
- Configuration[] configurations = this.configRepo.getConfigAdmin().listConfigurations(null);
- List<String> pids = new ArrayList<String>();
- for (int i = 0; i < configurations.length; i++) {
- pids.add(configurations[i].getPid());
- }
- return pids;
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- @SuppressWarnings("rawtypes")
- public void create(String pid) throws MBeanException {
- try {
- configRepo.update(pid, new Hashtable());
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- public void delete(String pid) throws MBeanException {
- try {
- this.configRepo.delete(pid);
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- @SuppressWarnings("rawtypes")
- public Map<String, String> listProperties(String pid) throws MBeanException {
- try {
- Dictionary dictionary = getConfigProperties(pid);
-
- Map<String, String> propertiesMap = new HashMap<String, String>();
- for (Enumeration e = dictionary.keys(); e.hasMoreElements(); ) {
- Object key = e.nextElement();
- Object value = dictionary.get(key);
- propertiesMap.put(key.toString(), value.toString());
- }
- return propertiesMap;
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- @SuppressWarnings("rawtypes")
- public void deleteProperty(String pid, String key) throws MBeanException {
- try {
- Dictionary dictionary = getConfigProperties(pid);
- dictionary.remove(key);
- configRepo.update(pid, dictionary);
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- @SuppressWarnings({"rawtypes", "unchecked"})
- public void appendProperty(String pid, String key, String value) throws MBeanException {
- try {
- Dictionary dictionary = getConfigProperties(pid);
- Object currentValue = dictionary.get(key);
- if (currentValue == null) {
- dictionary.put(key, value);
- } else if (currentValue instanceof String) {
- dictionary.put(key, currentValue + value);
- } else {
- throw new IllegalStateException("Current value is not a String");
- }
- configRepo.update(pid, dictionary);
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- @SuppressWarnings({"rawtypes", "unchecked"})
- public void setProperty(String pid, String key, String value) throws MBeanException {
- try {
- Dictionary dictionary = getConfigProperties(pid);
- dictionary.put(key, value);
- configRepo.update(pid, dictionary);
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- public void update(String pid, Map<String, String> properties) throws MBeanException {
- try {
- if (properties == null) {
- properties = new HashMap<String, String>();
- }
- Dictionary<String, String> dictionary = toDictionary(properties);
- configRepo.update(pid, dictionary);
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- private Dictionary<String, String> toDictionary(
- Map<String, String> properties) {
- Dictionary<String, String> dictionary = new Hashtable<String, String>();
- for (String key : properties.keySet()) {
- dictionary.put(key, properties.get(key));
- }
- return dictionary;
- }
-
-
- public void setConfigRepo(ConfigRepository configRepo) {
- this.configRepo = configRepo;
- }
-
- @Override
- public String createFactoryConfiguration(String factoryPid,
- Map<String, String> properties) throws MBeanException {
- Dictionary<String, String> dict = toDictionary(properties);
- return configRepo.createFactoryConfiguration(factoryPid, dict);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java b/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
deleted file mode 100644
index 11bb720..0000000
--- a/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.IOException;
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.apache.karaf.config.core.ConfigRepository;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-public class ConfigRepositoryImpl implements ConfigRepository {
- private ConfigurationAdmin configAdmin;
-
- private File storage;
-
- public ConfigRepositoryImpl(ConfigurationAdmin configAdmin) {
- this.configAdmin = configAdmin;
- }
-
- /* (non-Javadoc)
- * @see org.apache.karaf.shell.config.impl.ConfigRepository#update(java.lang.String, java.util.Dictionary, boolean)
- */
- @Override
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public void update(String pid, Dictionary props) throws IOException {
- Configuration cfg = this.configAdmin.getConfiguration(pid, null);
- if (cfg.getBundleLocation() != null) {
- cfg.setBundleLocation(null);
- }
- cfg.update(props);
- }
-
- /* (non-Javadoc)
- * @see org.apache.karaf.shell.config.impl.ConfigRepository#delete(java.lang.String)
- */
- @Override
- public void delete(String pid) throws Exception {
- Configuration configuration = this.configAdmin.getConfiguration(pid);
- configuration.delete();
- deleteStorage(pid);
- }
-
- protected void deleteStorage(String pid) throws Exception {
- if (storage != null) {
- File cfgFile = new File(storage, pid + ".cfg");
- cfgFile.delete();
- }
- }
-
- /* (non-Javadoc)
- * @see org.apache.karaf.shell.config.impl.ConfigRepository#getConfigProperties(java.lang.String)
- */
- @Override
- @SuppressWarnings("rawtypes")
- public Dictionary getConfigProperties(String pid) throws IOException, InvalidSyntaxException {
- if(pid != null && configAdmin != null) {
- Configuration configuration = this.configAdmin.getConfiguration(pid);
- if(configuration != null) {
- Dictionary props = configuration.getProperties();
- return (props != null) ? props : new Hashtable<String, String>();
- }
- }
- return null;
- }
-
- public ConfigurationAdmin getConfigAdmin() {
- return this.configAdmin;
- }
-
- @Override
- public String createFactoryConfiguration(String factoryPid, Dictionary<String, ?> properties) {
- try {
- Configuration config = configAdmin.createFactoryConfiguration(factoryPid);
- config.update(properties);
- return config.getPid();
- } catch (IOException e) {
- throw new RuntimeException(e.getMessage(), e);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/config/core/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java b/config/core/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
deleted file mode 100644
index bdfab09..0000000
--- a/config/core/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.osgi;
-
-import org.apache.karaf.config.core.ConfigRepository;
-import org.apache.karaf.config.core.impl.ConfigMBeanImpl;
-import org.apache.karaf.config.core.impl.ConfigRepositoryImpl;
-import org.apache.karaf.util.tracker.BaseActivator;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-public class Activator extends BaseActivator {
-
- @Override
- protected void doOpen() throws Exception {
- trackService(ConfigurationAdmin.class);
- }
-
- protected void doStart() throws Exception {
- ConfigurationAdmin configurationAdmin = getTrackedService(ConfigurationAdmin.class);
- if (configurationAdmin == null) {
- return;
- }
-
- ConfigRepository configRepository = new ConfigRepositoryImpl(configurationAdmin);
- register(ConfigRepository.class, configRepository);
-
- ConfigMBeanImpl configMBean = new ConfigMBeanImpl();
- configMBean.setConfigRepo(configRepository);
- registerMBean(configMBean, "type=config");
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/config/core/src/main/resources/OSGI-INF/bundle.info b/config/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 3cd35da..0000000
--- a/config/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,27 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides Karaf shell commands to manipulate the ConfigAdmin OSGi service.
-
-The following commands are available:
-* config:cancel - Cancels the changes to the configuration being edited.
-* config:edit - Creates or edits a configuration.
-* config:list - Lists existing configurations.
-* config:propappend - Appends the given value to an existing property or creates
- the property with the specified name and value.
-* config:propdel - Deletes a property from the edited configuration.
-* config:proplist - Lists properties from the currently edited configuration.
-* config:propset - Sets a property in the currently edited configuration.
-* config:update - Saves and propagates changes from the configuration being edited.
-
-h1. See also
-
-Commands - section of the Karaf User Guide.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/resources/OSGI-INF/metatype/metatype.properties
----------------------------------------------------------------------
diff --git a/config/core/src/main/resources/OSGI-INF/metatype/metatype.properties b/config/core/src/main/resources/OSGI-INF/metatype/metatype.properties
deleted file mode 100644
index 3bce187..0000000
--- a/config/core/src/main/resources/OSGI-INF/metatype/metatype.properties
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# 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.
-#
-
-#
-# This file contains localization strings for configuration labels and
-# descriptions as used in the metatype.xml descriptor
-
-config.name = Apache Karaf Shell Config
-config.description = Configuration of Apache Karaf Shell Config
-
-storage.name = Storage directory
-storage.description = the directory used as a storage for configurations
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/resources/OSGI-INF/metatype/metatype.xml
----------------------------------------------------------------------
diff --git a/config/core/src/main/resources/OSGI-INF/metatype/metatype.xml b/config/core/src/main/resources/OSGI-INF/metatype/metatype.xml
deleted file mode 100644
index 83d3242..0000000
--- a/config/core/src/main/resources/OSGI-INF/metatype/metatype.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<metatype:MetaData xmlns:metatype="http://www.osgi.org/xmlns/metatype/v1.0.0" localization="OSGI-INF/metatype/metatype">
- <OCD id="org.apache.karaf.config" name="%config.name" description="%config.description">
- <AD id="storage" type="String" default="${karaf.etc}/"
- name="%storage.name" description="%storage.description"/>
- </OCD>
- <Designate pid="org.apache.karaf.config">
- <Object ocdref="org.apache.karaf.config"/>
- </Designate>
-</metatype:MetaData>
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/pom.xml
----------------------------------------------------------------------
diff --git a/config/pom.xml b/config/pom.xml
index 10cc1af..af0de85 100644
--- a/config/pom.xml
+++ b/config/pom.xml
@@ -10,7 +10,7 @@
(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
+ 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,
@@ -29,13 +29,92 @@
</parent>
<groupId>org.apache.karaf.config</groupId>
- <artifactId>config</artifactId>
- <packaging>pom</packaging>
- <name>Apache Karaf :: ConfigAdmin</name>
-
- <modules>
- <module>core</module>
- <module>command</module>
- </modules>
+ <artifactId>org.apache.karaf.config.core</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Karaf :: ConfigAdmin :: Core</name>
+ <description>This bundle provides Karaf services</description>
+
+ <properties>
+ <appendedResourcesDirectory>${basedir}/../etc/appended-resources</appendedResourcesDirectory>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.karaf</groupId>
+ <artifactId>org.apache.karaf.util</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.core</artifactId>
+ <optional>true</optional>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <filtering>true</filtering>
+ <includes>
+ <include>**/*.info</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.apache.karaf.config.command*,
+ org.apache.karaf.config.core
+ </Export-Package>
+ <Import-Package>
+ *
+ </Import-Package>
+ <Private-Package>
+ org.apache.karaf.config.core.impl,
+ org.apache.karaf.config.core.impl.osgi,
+ org.apache.karaf.util.tracker
+ </Private-Package>
+ <Bundle-Activator>
+ org.apache.karaf.config.core.impl.osgi.Activator
+ </Bundle-Activator>
+ <Karaf-Commands>org.apache.karaf.config.command.*</Karaf-Commands>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/CancelCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/CancelCommand.java b/config/src/main/java/org/apache/karaf/config/command/CancelCommand.java
new file mode 100644
index 0000000..dff43fa
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/CancelCommand.java
@@ -0,0 +1,32 @@
+/*
+ * 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.command;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "config", name = "cancel", description = "Cancels the changes to the configuration being edited.")
+@Service
+public class CancelCommand extends ConfigCommandSupport {
+
+ protected Object doExecute() throws Exception {
+ session.put(PROPERTY_CONFIG_PID, null);
+ session.put(PROPERTY_CONFIG_PROPS, null);
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/ConfigCommandSupport.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/ConfigCommandSupport.java b/config/src/main/java/org/apache/karaf/config/command/ConfigCommandSupport.java
new file mode 100644
index 0000000..fe0ca93
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/ConfigCommandSupport.java
@@ -0,0 +1,63 @@
+/*
+ * 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.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.config.core.ConfigRepository;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.console.Session;
+
+/**
+ * Abstract class from which all commands related to the ConfigurationAdmin
+ * service should derive.
+ * This command retrieves a reference to the ConfigurationAdmin service before
+ * calling another method to actually process the command.
+ */
+public abstract class ConfigCommandSupport implements Action {
+
+ public static final String PROPERTY_CONFIG_PID = "ConfigCommand.PID";
+ public static final String PROPERTY_CONFIG_PROPS = "ConfigCommand.Props";
+ public static final String PROPERTY_FACTORY = "ConfigCommand.Factory";
+
+ @Reference
+ protected ConfigRepository configRepository;
+
+ @Reference
+ protected Session session;
+
+ @Override
+ public Object execute() throws Exception {
+ return doExecute();
+ }
+
+ protected abstract Object doExecute() throws Exception;
+
+ @SuppressWarnings("rawtypes")
+ protected Dictionary getEditedProps() throws Exception {
+ return (Dictionary) this.session.get(PROPERTY_CONFIG_PROPS);
+ }
+
+ public void setConfigRepository(ConfigRepository configRepository) {
+ this.configRepository = configRepository;
+ }
+
+ public void setSession(Session session) {
+ this.session = session;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/ConfigPropertyCommandSupport.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/ConfigPropertyCommandSupport.java b/config/src/main/java/org/apache/karaf/config/command/ConfigPropertyCommandSupport.java
new file mode 100644
index 0000000..619c224
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/ConfigPropertyCommandSupport.java
@@ -0,0 +1,85 @@
+/*
+ * 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.command;
+
+import java.util.Dictionary;
+import java.util.Properties;
+
+import org.apache.karaf.config.command.completers.ConfigurationCompleter;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+
+/**
+ * Abstract class which commands that are related to property processing should extend.
+ */
+public abstract class ConfigPropertyCommandSupport extends ConfigCommandSupport {
+
+ @Option(name = "-p", aliases = "--pid", description = "The configuration pid", required = false, multiValued = false)
+ @Completion(ConfigurationCompleter.class)
+ protected String pid;
+
+ @SuppressWarnings("rawtypes")
+ protected Object doExecute() throws Exception {
+ Dictionary props = getEditedProps();
+ if (props == null && pid == null) {
+ System.err.println("No configuration is being edited--run the edit command first");
+ } else {
+ if (props == null) {
+ props = new Properties();
+ }
+ propertyAction(props);
+ if(requiresUpdate(pid)) {
+ this.configRepository.update(pid, props);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Perform an action on the properties.
+ * @param props
+ */
+ @SuppressWarnings("rawtypes")
+ protected abstract void propertyAction(Dictionary props);
+
+ /**
+ * Checks if the configuration requires to be updated.
+ * The default behavior is to update if a valid pid has been passed to the method.
+ * @param pid
+ * @return
+ */
+ protected boolean requiresUpdate(String pid) {
+ if (pid != null) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Retrieves confguration from the pid, if used or delegates to session from getting the configuration.
+ * @return
+ * @throws Exception
+ */
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected Dictionary getEditedProps() throws Exception {
+ Dictionary props = this.configRepository.getConfigProperties(pid);
+ return (props != null) ? props : super.getEditedProps();
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/DeleteCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/DeleteCommand.java b/config/src/main/java/org/apache/karaf/config/command/DeleteCommand.java
new file mode 100644
index 0000000..6953ef0
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/DeleteCommand.java
@@ -0,0 +1,52 @@
+/*
+ * 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.command;
+
+import org.apache.karaf.config.command.completers.ConfigurationCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "config", name = "delete", description = "Delete a configuration.")
+@Service
+public class DeleteCommand extends ConfigCommandSupport {
+
+ @Argument(index = 0, name = "pid", description = "PID of the configuration", required = true, multiValued = false)
+ @Completion(ConfigurationCompleter.class)
+ String pid;
+
+ @Option(name = "--force", aliases = {}, description = "Force the edition of this config, even if another one was under edition", required = false, multiValued = false)
+ boolean force;
+
+ protected Object doExecute() throws Exception {
+ String oldPid = (String) this.session.get(PROPERTY_CONFIG_PID);
+ if (oldPid != null && oldPid.equals(pid) && !force) {
+ System.err.println("This config is being edited. Cancel / update first, or use the --force option");
+ return null;
+ }
+
+ this.configRepository.delete(pid);
+ if (oldPid != null && oldPid.equals(pid) && !force) {
+ this.session.put(PROPERTY_CONFIG_PID, null);
+ this.session.put(PROPERTY_CONFIG_PROPS, null);
+ }
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/EditCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/EditCommand.java b/config/src/main/java/org/apache/karaf/config/command/EditCommand.java
new file mode 100644
index 0000000..8c48b83
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/EditCommand.java
@@ -0,0 +1,70 @@
+/*
+ * 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.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.config.command.completers.ConfigurationCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.service.cm.Configuration;
+
+@Command(scope = "config", name = "edit", description = "Creates or edits a configuration.", detailedDescription="classpath:edit.txt")
+@Service
+public class EditCommand extends ConfigCommandSupport {
+
+ @Argument(index = 0, name = "pid", description = "PID of the configuration or of the factory if --factory is given. Pid can also be specified as ldap query", required = true, multiValued = false)
+ @Completion(ConfigurationCompleter.class)
+ String pid;
+
+ @Option(name = "--force", aliases = {}, description = "Force the edition of this config, even if another one was under edition", required = false, multiValued = false)
+ boolean force;
+
+ @Option(name = "--factory", aliases = {}, description = "Define this config as a factory config. Will be crearted on calling update", required = false, multiValued = false)
+ boolean factory;
+
+ @SuppressWarnings("rawtypes")
+ protected Object doExecute() throws Exception {
+ String oldPid = (String) this.session.get(PROPERTY_CONFIG_PID);
+ if (oldPid != null && !oldPid.equals(pid) && !force) {
+ System.err.println("Another config is being edited. Cancel / update first, or use the --force option");
+ return null;
+ }
+
+ if (pid.startsWith("(")) {
+ Configuration[] configs = this.configRepository.getConfigAdmin().listConfigurations(pid);
+ if (configs.length == 0) {
+ throw new RuntimeException("Filter matches no config");
+ }
+ if (configs.length > 1) {
+ throw new RuntimeException("Filter matches more than one config");
+ }
+ pid = configs[0].getPid();
+ System.out.println("Editing config " + pid);
+ }
+
+ Dictionary props = this.configRepository.getConfigProperties(pid);
+ this.session.put(PROPERTY_CONFIG_PID, pid);
+ this.session.put(PROPERTY_FACTORY, factory);
+ this.session.put(PROPERTY_CONFIG_PROPS, props);
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/ListCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/ListCommand.java b/config/src/main/java/org/apache/karaf/config/command/ListCommand.java
new file mode 100644
index 0000000..bce8410
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/ListCommand.java
@@ -0,0 +1,68 @@
+/*
+ * 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.command;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.service.cm.Configuration;
+
+@Command(scope = "config", name = "list", description = "Lists existing configurations.")
+@Service
+public class ListCommand extends ConfigCommandSupport {
+
+ @Argument(index = 0, name = "query", description = "Query in LDAP syntax. Example: \"(service.pid=org.apache.karaf.log)\"", required = false, multiValued = false)
+ String query;
+
+ @SuppressWarnings("rawtypes")
+ protected Object doExecute() throws Exception {
+ Configuration[] configs = configRepository.getConfigAdmin().listConfigurations(query);
+ if (configs != null) {
+ Map<String, Configuration> sortedConfigs = new TreeMap<String, Configuration>();
+ for (Configuration config : configs) {
+ sortedConfigs.put(config.getPid(), config);
+ }
+ for (String pid : sortedConfigs.keySet()) {
+ Configuration config = sortedConfigs.get(pid);
+ System.out.println("----------------------------------------------------------------");
+ System.out.println("Pid: " + config.getPid());
+ if (config.getFactoryPid() != null) {
+ System.out.println("FactoryPid: " + config.getFactoryPid());
+ }
+ System.out.println("BundleLocation: " + config.getBundleLocation());
+ if (config.getProperties() != null) {
+ System.out.println("Properties:");
+ Dictionary props = config.getProperties();
+ Map<String, Object> sortedProps = new TreeMap<String, Object>();
+ for (Enumeration e = props.keys(); e.hasMoreElements();) {
+ Object key = e.nextElement();
+ sortedProps.put(key.toString(), props.get(key));
+ }
+ for (String key : sortedProps.keySet()) {
+ System.out.println(" " + key + " = " + sortedProps.get(key));
+ }
+ }
+ }
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/PropAppendCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/PropAppendCommand.java b/config/src/main/java/org/apache/karaf/config/command/PropAppendCommand.java
new file mode 100644
index 0000000..f021146
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/PropAppendCommand.java
@@ -0,0 +1,50 @@
+/*
+ * 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.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.config.command.completers.ConfigurationPropertyCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "config", name = "property-append", description = "Appends the given value to an existing property or creates the property with the specified name and value.")
+@Service
+public class PropAppendCommand extends ConfigPropertyCommandSupport {
+
+ @Argument(index = 0, name = "name", description = "The name of the property", required = true, multiValued = false)
+ @Completion(ConfigurationPropertyCompleter.class)
+ String prop;
+
+ @Argument(index = 1, name = "value", description = "The value to append to the property", required = true, multiValued = false)
+ String value;
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ @Override
+ public void propertyAction(Dictionary props) {
+ final Object currentValue = props.get(prop);
+ if (currentValue == null) {
+ props.put(prop, value);
+ } else if (currentValue instanceof String) {
+ props.put(prop, currentValue + value);
+ } else {
+ System.err.println("Append Failed: current value is not a String.");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/PropDelCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/PropDelCommand.java b/config/src/main/java/org/apache/karaf/config/command/PropDelCommand.java
new file mode 100644
index 0000000..e416cf6
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/PropDelCommand.java
@@ -0,0 +1,38 @@
+/*
+ * 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.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+
+@Command(scope = "config", name = "property-delete", description = "Deletes a property from the configuration being edited.")
+@Service
+public class PropDelCommand extends ConfigPropertyCommandSupport {
+
+ @Argument(index = 0, name = "property", description = "The name of the property to delete", required = true, multiValued = false)
+ String prop;
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public void propertyAction(Dictionary props) {
+ props.remove(prop);
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/PropListCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/PropListCommand.java b/config/src/main/java/org/apache/karaf/config/command/PropListCommand.java
new file mode 100644
index 0000000..a0d3a61
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/PropListCommand.java
@@ -0,0 +1,47 @@
+/*
+ * 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.command;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "config", name = "property-list", description = "Lists properties from the currently edited configuration.")
+@Service
+public class PropListCommand extends ConfigPropertyCommandSupport {
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public void propertyAction(Dictionary props) {
+ for (Enumeration e = props.keys(); e.hasMoreElements(); ) {
+ Object key = e.nextElement();
+ System.out.println(" " + key + " = " + props.get(key));
+ }
+ }
+
+ /**
+ * List commands never requires an update, so it always returns false.
+ * @param pid
+ * @return
+ */
+ @Override
+ protected boolean requiresUpdate(String pid) {
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/PropSetCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/PropSetCommand.java b/config/src/main/java/org/apache/karaf/config/command/PropSetCommand.java
new file mode 100644
index 0000000..8337f6a
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/PropSetCommand.java
@@ -0,0 +1,43 @@
+/*
+ * 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.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.config.command.completers.ConfigurationPropertyCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "config", name = "property-set", description = "Sets a property in the currently edited configuration.")
+@Service
+public class PropSetCommand extends ConfigPropertyCommandSupport {
+
+ @Argument(index = 0, name = "property", description = "The name of the property to set", required = true, multiValued = false)
+ @Completion(ConfigurationPropertyCompleter.class)
+ String prop;
+
+ @Argument(index = 1, name = "value", description = "The value of the property", required = true, multiValued = false)
+ String value;
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ @Override
+ public void propertyAction(Dictionary props) {
+ props.put(prop, value);
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/UpdateCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/UpdateCommand.java b/config/src/main/java/org/apache/karaf/config/command/UpdateCommand.java
new file mode 100644
index 0000000..cc368b8
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/UpdateCommand.java
@@ -0,0 +1,48 @@
+/*
+ * 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.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "config", name = "update", description = "Saves and propagates changes from the configuration being edited.")
+@Service
+public class UpdateCommand extends ConfigCommandSupport {
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ protected Object doExecute() throws Exception {
+ Dictionary props = getEditedProps();
+ if (props == null) {
+ System.err.println("No configuration is being edited--run the edit command first");
+ return null;
+ }
+
+ String pid = (String) this.session.get(PROPERTY_CONFIG_PID);
+ boolean isFactory = this.session.get(PROPERTY_FACTORY) != null && (Boolean) this.session.get(PROPERTY_FACTORY);
+ if (isFactory) {
+ this.configRepository.createFactoryConfiguration(pid, props);
+ } else {
+ this.configRepository.update(pid, props);
+ }
+ this.session.put(PROPERTY_CONFIG_PID, null);
+ this.session.put(PROPERTY_FACTORY, null);
+ this.session.put(PROPERTY_CONFIG_PROPS, null);
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationCompleter.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationCompleter.java b/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationCompleter.java
new file mode 100644
index 0000000..fe60c56
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationCompleter.java
@@ -0,0 +1,103 @@
+/*
+ * 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.command.completers;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.karaf.shell.api.action.lifecycle.Destroy;
+import org.apache.karaf.shell.api.action.lifecycle.Init;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationEvent;
+import org.osgi.service.cm.ConfigurationListener;
+
+/**
+ * {@link Completer} for Configuration Admin configurations.
+ *
+ * Displays a list of existing config instance configurations for completion.
+ *
+ */
+@Service
+public class ConfigurationCompleter implements Completer, ConfigurationListener {
+
+ private final StringsCompleter delegate = new StringsCompleter();
+
+ @Reference
+ private ConfigurationAdmin admin;
+
+ @Reference
+ private BundleContext bundleContext;
+
+ private ServiceRegistration<ConfigurationListener> registration;
+
+ public void setAdmin(ConfigurationAdmin admin) {
+ this.admin = admin;
+ }
+
+ @Init
+ public void init() {
+ registration = bundleContext.registerService(ConfigurationListener.class, this, null);
+
+ Configuration[] configs;
+ try {
+ configs = admin.listConfigurations(null);
+ if (configs == null) {
+ return;
+ }
+ } catch (Exception e) {
+ return;
+ }
+
+ Collection<String> pids = new ArrayList<String>();
+ for (Configuration config : configs) {
+ pids.add(config.getPid());
+ }
+
+ delegate.getStrings().addAll(pids);
+ }
+
+ @Destroy
+ public void destroy() {
+ registration.unregister();
+ }
+
+ public int complete(final Session session, final CommandLine commandLine, final List<String> candidates) {
+ return delegate.complete(session, commandLine, candidates);
+ }
+
+ public void configurationEvent(ConfigurationEvent configurationEvent) {
+ String pid = configurationEvent.getPid();
+ if (configurationEvent.getType() == ConfigurationEvent.CM_DELETED) {
+ delegate.getStrings().remove(pid);
+ } else if (configurationEvent.getType() == ConfigurationEvent.CM_UPDATED) {
+ delegate.getStrings().add(pid);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java b/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java
new file mode 100644
index 0000000..2b43fec
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java
@@ -0,0 +1,136 @@
+/*
+ * 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.command.completers;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.karaf.config.command.ConfigCommandSupport;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * {@link Completer} for Configuration Admin properties.
+ *
+ * Displays a list of existing properties based on the current configuration being edited.
+ *
+ */
+@Service
+public class ConfigurationPropertyCompleter implements Completer {
+
+ private final StringsCompleter delegate = new StringsCompleter();
+
+ private static final String OPTION = "-p";
+ private static final String ALIAS = "--pid";
+
+ @Reference
+ private ConfigurationAdmin configAdmin;
+
+ @SuppressWarnings("rawtypes")
+ public int complete(final Session session, final CommandLine commandLine, final List<String> candidates) {
+ if (session != null) {
+ String pid = getPid(session, commandLine);
+ Set<String> propertyNames = getPropertyNames(pid);
+ delegate.getStrings().clear();
+ if (propertyNames != null && !propertyNames.isEmpty()) {
+ delegate.getStrings().addAll(propertyNames);
+ }
+ }
+ return delegate.complete(session, commandLine, candidates);
+ }
+
+ /**
+ * Retrieves the pid stored in the {@link Session} or passed as an argument.
+ * Argument takes precedence from pid stored in the {@link Session}.
+ */
+ private String getPid(Session session, CommandLine commandLine) {
+ String pid = (String) session.get(ConfigCommandSupport.PROPERTY_CONFIG_PID);
+ if (commandLine.getArguments().length > 0) {
+ List<String> arguments = Arrays.asList(commandLine.getArguments());
+ if (arguments.contains(OPTION)) {
+ int index = arguments.indexOf(OPTION);
+ if (arguments.size() > index) {
+ return arguments.get(index + 1);
+ }
+ }
+
+ if (arguments.contains(ALIAS)) {
+ int index = arguments.indexOf(ALIAS);
+ if (arguments.size() > index) {
+ return arguments.get(index + 1);
+ }
+ }
+ }
+ return pid;
+ }
+
+ /**
+ * Returns the property names for the given pid.
+ * @param pid
+ * @return
+ */
+ @SuppressWarnings("rawtypes")
+ private Set<String> getPropertyNames(String pid) {
+ Set<String> propertyNames = new HashSet<String>();
+ if (pid != null) {
+ Configuration configuration = null;
+ try {
+ Configuration[] configs = configAdmin.listConfigurations("(service.pid="+pid+")");
+ if (configs != null && configs.length > 0) {
+ configuration = configs[0];
+ if (configuration != null) {
+ Dictionary properties = configuration.getProperties();
+ if (properties != null) {
+ Enumeration keys = properties.keys();
+ while (keys.hasMoreElements()) {
+ propertyNames.add(String.valueOf(keys.nextElement()));
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ //Ignore
+ } catch (InvalidSyntaxException e) {
+ //Ignore
+ }
+ }
+ return propertyNames;
+ }
+
+ public ConfigurationAdmin getConfigAdmin() {
+ return configAdmin;
+ }
+
+ public void setConfigAdmin(ConfigurationAdmin configAdmin) {
+ this.configAdmin = configAdmin;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/core/ConfigMBean.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/core/ConfigMBean.java b/config/src/main/java/org/apache/karaf/config/core/ConfigMBean.java
new file mode 100644
index 0000000..9cb9f7f
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/core/ConfigMBean.java
@@ -0,0 +1,107 @@
+/*
+ * 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.karaf.config.core;
+
+import javax.management.MBeanException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * MBean to manipulate the Config layer.
+ */
+public interface ConfigMBean {
+
+ /**
+ * Get the list of all configuration PIDs.
+ *
+ * @return the list of all configuration PIDs.
+ * @throws Exception
+ */
+ List<String> getConfigs() throws MBeanException;
+
+ /**
+ * Create a new configuration for the given PID.
+ *
+ * @param pid the configuration PID.
+ * @throws Exception
+ */
+ void create(String pid) throws MBeanException;
+
+ /**
+ * Delete a configuration identified by the given PID.
+ *
+ * @param pid the configuration PID to delete.
+ * @throws Exception
+ */
+ void delete(String pid) throws MBeanException;
+
+ /**
+ * Get the list of properties for a configuration PID.
+ *
+ * @param pid the configuration PID.
+ * @return the list of properties.
+ * @throws Exception
+ */
+ Map<String, String> listProperties(String pid) throws MBeanException;
+
+ /**
+ * Remove the configuration property identified by the given key.
+ *
+ * @param pid the configuration PID.
+ * @param key the property key.
+ * @throws Exception
+ */
+ void deleteProperty(String pid, String key) throws MBeanException;
+
+ /**
+ * Append (or add) a value for the given configuration key.
+ *
+ * @param pid the configuration PID.
+ * @param key the property key.
+ * @param value the value to append to the current property value.
+ * @throws Exception
+ */
+ void appendProperty(String pid, String key, String value) throws MBeanException;
+
+ /**
+ * Set a configuration property.
+ *
+ * @param pid the configuration PID.
+ * @param key the property key.
+ * @param value the property value.
+ * @throws Exception
+ */
+ void setProperty(String pid, String key, String value) throws MBeanException;
+
+ /**
+ * Update a complete configuration.
+ *
+ * @param pid the configuration PID.
+ * @param properties the new properties to set in the configuration.
+ * @throws MBeanException
+ */
+ void update(String pid, Map<String, String> properties) throws MBeanException;
+
+ /**
+ * Create a factory based configuration.
+ *
+ * @param factoryPid
+ * @param properties the new properties to set in the configuration.
+ * @return created pid
+ * @throws MBeanException
+ */
+ String createFactoryConfiguration(String factoryPid, Map<String, String> properties) throws MBeanException;
+
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/core/ConfigRepository.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/core/ConfigRepository.java b/config/src/main/java/org/apache/karaf/config/core/ConfigRepository.java
new file mode 100644
index 0000000..8121679
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/core/ConfigRepository.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.util.Dictionary;
+
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public interface ConfigRepository {
+
+ /**
+ * Saves config to storage or ConfigurationAdmin.
+ * @param pid
+ * @param props
+ * @throws IOException
+ */
+ @SuppressWarnings("rawtypes")
+ void update(String pid, Dictionary props) throws IOException;
+
+ void delete(String pid) throws Exception;
+
+ @SuppressWarnings("rawtypes")
+ Dictionary getConfigProperties(String pid) throws IOException, InvalidSyntaxException;
+
+ ConfigurationAdmin getConfigAdmin();
+
+ /**
+ * Create a factory based configuration.
+ *
+ * @param factoryPid
+ * @param properties the new properties to set in the configuration.
+ * @return created pid
+ */
+ String createFactoryConfiguration(String factoryPid, Dictionary<String, ?> properties);
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java b/config/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java
new file mode 100644
index 0000000..a8b8090
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java
@@ -0,0 +1,186 @@
+/*
+ * 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.karaf.config.core.impl;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.MBeanException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+
+import org.apache.karaf.config.core.ConfigMBean;
+import org.apache.karaf.config.core.ConfigRepository;
+import org.osgi.service.cm.Configuration;
+
+/**
+ * Implementation of the ConfigMBean.
+ */
+public class ConfigMBeanImpl extends StandardMBean implements ConfigMBean {
+
+ private ConfigRepository configRepo;
+
+ public ConfigMBeanImpl() throws NotCompliantMBeanException {
+ super(ConfigMBean.class);
+ }
+
+ private Configuration getConfiguration(String pid) throws IOException {
+ Configuration configuration = configRepo.getConfigAdmin().getConfiguration(pid);
+ if (configuration == null) {
+ throw new IllegalArgumentException("Configuration PID " + pid + " doesn't exist");
+ }
+ return configuration;
+ }
+
+ @SuppressWarnings("rawtypes")
+ private Dictionary getConfigProperties(String pid) throws IOException {
+ Configuration configuration = getConfiguration(pid);
+
+ Dictionary dictionary = configuration.getProperties();
+ if (dictionary == null) {
+ dictionary = new java.util.Properties();
+ }
+ return dictionary;
+ }
+
+ /**
+ * Get all config pids
+ */
+ public List<String> getConfigs() throws MBeanException {
+ try {
+ Configuration[] configurations = this.configRepo.getConfigAdmin().listConfigurations(null);
+ List<String> pids = new ArrayList<String>();
+ for (int i = 0; i < configurations.length; i++) {
+ pids.add(configurations[i].getPid());
+ }
+ return pids;
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void create(String pid) throws MBeanException {
+ try {
+ configRepo.update(pid, new Hashtable());
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ public void delete(String pid) throws MBeanException {
+ try {
+ this.configRepo.delete(pid);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ public Map<String, String> listProperties(String pid) throws MBeanException {
+ try {
+ Dictionary dictionary = getConfigProperties(pid);
+
+ Map<String, String> propertiesMap = new HashMap<String, String>();
+ for (Enumeration e = dictionary.keys(); e.hasMoreElements(); ) {
+ Object key = e.nextElement();
+ Object value = dictionary.get(key);
+ propertiesMap.put(key.toString(), value.toString());
+ }
+ return propertiesMap;
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void deleteProperty(String pid, String key) throws MBeanException {
+ try {
+ Dictionary dictionary = getConfigProperties(pid);
+ dictionary.remove(key);
+ configRepo.update(pid, dictionary);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public void appendProperty(String pid, String key, String value) throws MBeanException {
+ try {
+ Dictionary dictionary = getConfigProperties(pid);
+ Object currentValue = dictionary.get(key);
+ if (currentValue == null) {
+ dictionary.put(key, value);
+ } else if (currentValue instanceof String) {
+ dictionary.put(key, currentValue + value);
+ } else {
+ throw new IllegalStateException("Current value is not a String");
+ }
+ configRepo.update(pid, dictionary);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public void setProperty(String pid, String key, String value) throws MBeanException {
+ try {
+ Dictionary dictionary = getConfigProperties(pid);
+ dictionary.put(key, value);
+ configRepo.update(pid, dictionary);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ public void update(String pid, Map<String, String> properties) throws MBeanException {
+ try {
+ if (properties == null) {
+ properties = new HashMap<String, String>();
+ }
+ Dictionary<String, String> dictionary = toDictionary(properties);
+ configRepo.update(pid, dictionary);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ private Dictionary<String, String> toDictionary(
+ Map<String, String> properties) {
+ Dictionary<String, String> dictionary = new Hashtable<String, String>();
+ for (String key : properties.keySet()) {
+ dictionary.put(key, properties.get(key));
+ }
+ return dictionary;
+ }
+
+
+ public void setConfigRepo(ConfigRepository configRepo) {
+ this.configRepo = configRepo;
+ }
+
+ @Override
+ public String createFactoryConfiguration(String factoryPid,
+ Map<String, String> properties) throws MBeanException {
+ Dictionary<String, String> dict = toDictionary(properties);
+ return configRepo.createFactoryConfiguration(factoryPid, dict);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java b/config/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
new file mode 100644
index 0000000..11bb720
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
@@ -0,0 +1,99 @@
+/*
+ * 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.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.karaf.config.core.ConfigRepository;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public class ConfigRepositoryImpl implements ConfigRepository {
+ private ConfigurationAdmin configAdmin;
+
+ private File storage;
+
+ public ConfigRepositoryImpl(ConfigurationAdmin configAdmin) {
+ this.configAdmin = configAdmin;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.karaf.shell.config.impl.ConfigRepository#update(java.lang.String, java.util.Dictionary, boolean)
+ */
+ @Override
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public void update(String pid, Dictionary props) throws IOException {
+ Configuration cfg = this.configAdmin.getConfiguration(pid, null);
+ if (cfg.getBundleLocation() != null) {
+ cfg.setBundleLocation(null);
+ }
+ cfg.update(props);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.karaf.shell.config.impl.ConfigRepository#delete(java.lang.String)
+ */
+ @Override
+ public void delete(String pid) throws Exception {
+ Configuration configuration = this.configAdmin.getConfiguration(pid);
+ configuration.delete();
+ deleteStorage(pid);
+ }
+
+ protected void deleteStorage(String pid) throws Exception {
+ if (storage != null) {
+ File cfgFile = new File(storage, pid + ".cfg");
+ cfgFile.delete();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.karaf.shell.config.impl.ConfigRepository#getConfigProperties(java.lang.String)
+ */
+ @Override
+ @SuppressWarnings("rawtypes")
+ public Dictionary getConfigProperties(String pid) throws IOException, InvalidSyntaxException {
+ if(pid != null && configAdmin != null) {
+ Configuration configuration = this.configAdmin.getConfiguration(pid);
+ if(configuration != null) {
+ Dictionary props = configuration.getProperties();
+ return (props != null) ? props : new Hashtable<String, String>();
+ }
+ }
+ return null;
+ }
+
+ public ConfigurationAdmin getConfigAdmin() {
+ return this.configAdmin;
+ }
+
+ @Override
+ public String createFactoryConfiguration(String factoryPid, Dictionary<String, ?> properties) {
+ try {
+ Configuration config = configAdmin.createFactoryConfiguration(factoryPid);
+ config.update(properties);
+ return config.getPid();
+ } catch (IOException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java b/config/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
new file mode 100644
index 0000000..bdfab09
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
@@ -0,0 +1,46 @@
+/*
+ * 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.osgi;
+
+import org.apache.karaf.config.core.ConfigRepository;
+import org.apache.karaf.config.core.impl.ConfigMBeanImpl;
+import org.apache.karaf.config.core.impl.ConfigRepositoryImpl;
+import org.apache.karaf.util.tracker.BaseActivator;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public class Activator extends BaseActivator {
+
+ @Override
+ protected void doOpen() throws Exception {
+ trackService(ConfigurationAdmin.class);
+ }
+
+ protected void doStart() throws Exception {
+ ConfigurationAdmin configurationAdmin = getTrackedService(ConfigurationAdmin.class);
+ if (configurationAdmin == null) {
+ return;
+ }
+
+ ConfigRepository configRepository = new ConfigRepositoryImpl(configurationAdmin);
+ register(ConfigRepository.class, configRepository);
+
+ ConfigMBeanImpl configMBean = new ConfigMBeanImpl();
+ configMBean.setConfigRepo(configRepository);
+ registerMBean(configMBean, "type=config");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/config/src/main/resources/OSGI-INF/bundle.info b/config/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..3cd35da
--- /dev/null
+++ b/config/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,27 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle provides Karaf shell commands to manipulate the ConfigAdmin OSGi service.
+
+The following commands are available:
+* config:cancel - Cancels the changes to the configuration being edited.
+* config:edit - Creates or edits a configuration.
+* config:list - Lists existing configurations.
+* config:propappend - Appends the given value to an existing property or creates
+ the property with the specified name and value.
+* config:propdel - Deletes a property from the edited configuration.
+* config:proplist - Lists properties from the currently edited configuration.
+* config:propset - Sets a property in the currently edited configuration.
+* config:update - Saves and propagates changes from the configuration being edited.
+
+h1. See also
+
+Commands - section of the Karaf User Guide.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/resources/OSGI-INF/metatype/metatype.properties
----------------------------------------------------------------------
diff --git a/config/src/main/resources/OSGI-INF/metatype/metatype.properties b/config/src/main/resources/OSGI-INF/metatype/metatype.properties
new file mode 100644
index 0000000..3bce187
--- /dev/null
+++ b/config/src/main/resources/OSGI-INF/metatype/metatype.properties
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+#
+# This file contains localization strings for configuration labels and
+# descriptions as used in the metatype.xml descriptor
+
+config.name = Apache Karaf Shell Config
+config.description = Configuration of Apache Karaf Shell Config
+
+storage.name = Storage directory
+storage.description = the directory used as a storage for configurations
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/resources/OSGI-INF/metatype/metatype.xml
----------------------------------------------------------------------
diff --git a/config/src/main/resources/OSGI-INF/metatype/metatype.xml b/config/src/main/resources/OSGI-INF/metatype/metatype.xml
new file mode 100644
index 0000000..83d3242
--- /dev/null
+++ b/config/src/main/resources/OSGI-INF/metatype/metatype.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<metatype:MetaData xmlns:metatype="http://www.osgi.org/xmlns/metatype/v1.0.0" localization="OSGI-INF/metatype/metatype">
+ <OCD id="org.apache.karaf.config" name="%config.name" description="%config.description">
+ <AD id="storage" type="String" default="${karaf.etc}/"
+ name="%storage.name" description="%storage.description"/>
+ </OCD>
+ <Designate pid="org.apache.karaf.config">
+ <Object ocdref="org.apache.karaf.config"/>
+ </Designate>
+</metatype:MetaData>
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/resources/org/apache/karaf/config/command/edit.txt
----------------------------------------------------------------------
diff --git a/config/src/main/resources/org/apache/karaf/config/command/edit.txt b/config/src/main/resources/org/apache/karaf/config/command/edit.txt
new file mode 100644
index 0000000..88fa6d5
--- /dev/null
+++ b/config/src/main/resources/org/apache/karaf/config/command/edit.txt
@@ -0,0 +1,13 @@
+The edit command can be used to create or edit a configuration in three ways.
+
+Edit or create a config by pid:
+ > config:edit org.apache.karaf.sample.pid
+The command above will also create a file etc/org.apache.karaf.sample.pid which corresponds to a configuration object with pid org.apache.karaf.sample.pid.
+
+Create a factory config by factory pid:
+ > config:edit --factory myfactorypid
+In this case the config is created with a pid like myfactorypid.<generated id>. This config is not written to a file.
+
+Edit a config specified by an ldap query
+ > config:edit '(myattribute=myvalue)'
+This executes an ldap query like in config:list. If the result is exactly one config then it is edited.