Author: cschneider
Date: Tue Mar 13 16:05:10 2012
New Revision: 1300211

URL: http://svn.apache.org/viewvc?rev=1300211&view=rev
Log:
KARAF-963 restructuring of config to new module layout

Added:
    karaf/trunk/config/command/src/main/resources/org/apache/karaf/config/
    
karaf/trunk/config/command/src/main/resources/org/apache/karaf/config/command/
    
karaf/trunk/config/command/src/main/resources/org/apache/karaf/config/command/edit.txt
    karaf/trunk/config/command/src/test/java/org/apache/karaf/config/
    karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/
    
karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/EditCommandTest.java
    
karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/MockCommandSession.java
    
karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/UpdateCommandTest.java
    karaf/trunk/config/management/src/main/java/org/apache/karaf/config/
    
karaf/trunk/config/management/src/main/java/org/apache/karaf/config/management/
    
karaf/trunk/config/management/src/main/java/org/apache/karaf/config/management/ConfigMBean.java
    
karaf/trunk/config/management/src/main/java/org/apache/karaf/config/management/internal/
    
karaf/trunk/config/management/src/main/java/org/apache/karaf/config/management/internal/ConfigMBeanImpl.java
Modified:
    karaf/trunk/config/management/pom.xml

Added: 
karaf/trunk/config/command/src/main/resources/org/apache/karaf/config/command/edit.txt
URL: 
http://svn.apache.org/viewvc/karaf/trunk/config/command/src/main/resources/org/apache/karaf/config/command/edit.txt?rev=1300211&view=auto
==============================================================================
--- 
karaf/trunk/config/command/src/main/resources/org/apache/karaf/config/command/edit.txt
 (added)
+++ 
karaf/trunk/config/command/src/main/resources/org/apache/karaf/config/command/edit.txt
 Tue Mar 13 16:05:10 2012
@@ -0,0 +1,13 @@
+The edit command can be used to create or edit a configuration by passing its 
pid as argument.
+  > config:edit org.apache.karaf.sample.pid
+The command above will create a file etc/org.apache.karaf.sample.pid which 
corresponds to a configuration object with pid org.apache.karaf.sample.pid
+
+In case of Managed Service Factories the user can create or edit the 
configuration of a specific instance of a managed service.
+  > config:edit org.apache.karaf.sample.service.factory.pid-instanceid
+The command above will create a file 
etc/org.apache.karaf.sample.service.factory.pid-instanceid but in this case the 
pid is generated, according to the specification.
+
+This makes further editing to the configuration difficult because the 
generated pid is not known to the user. To make things simple config:edit 
provides a special flag -f or --use-file which allows editing a configuration 
using the filename instead of the pid.
+So the user can simply edit again the configuration by typing:
+  > config:edit org.apache.karaf.sample.service.factory.pid-instanceid.
+
+The --factory option can be used to create a new configuration for a given 
factory pid.  The parameter will be used as the factory pid and the 
configuration pid will be generated.  Note that this option
\ No newline at end of file

Added: 
karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/EditCommandTest.java
URL: 
http://svn.apache.org/viewvc/karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/EditCommandTest.java?rev=1300211&view=auto
==============================================================================
--- 
karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/EditCommandTest.java
 (added)
+++ 
karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/EditCommandTest.java
 Tue Mar 13 16:05:10 2012
@@ -0,0 +1,107 @@
+/*
+ * 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 static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+import java.util.Dictionary;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.apache.felix.service.command.CommandSession;
+import org.apache.karaf.config.command.ConfigCommandSupport;
+import org.apache.karaf.config.command.EditCommand;
+import org.apache.karaf.config.core.impl.ConfigRepositoryImpl;
+import org.easymock.EasyMock;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * Test cases for {@link EditCommand}
+ */
+public class EditCommandTest extends TestCase {
+
+    private static final String PID = "my.test.persistent.id";
+
+    private EditCommand command;
+    private BundleContext context;
+    private ConfigurationAdmin admin;
+    private CommandSession session;
+
+    @Override
+    protected void setUp() throws Exception {
+        command = new EditCommand();
+
+        
+        context = EasyMock.createMock(BundleContext.class);
+        command.setBundleContext(context);
+        
+        admin = createMock(ConfigurationAdmin.class);
+        command.setConfigRepository(new ConfigRepositoryImpl(null, admin, 
null));
+        expect(context.getBundle(0)).andReturn(null).anyTimes();
+
+        replay(context);
+        
+        session = new MockCommandSession();
+    }
+    
+    public void testExecuteOnExistingPid() throws Exception {        
+        Configuration config = createMock(Configuration.class);
+        expect(admin.getConfiguration(PID)).andReturn(config);
+        replay(admin);
+        
+        // the ConfigAdmin service returns a Dictionary for an existing PID
+        Properties props = new Properties();
+        expect(config.getProperties()).andReturn(props);
+        replay(config);
+        
+        command.pid = PID; 
+        command.execute(session);
+        
+        // the PID and Dictionary should have been set on the session
+        assertEquals("The PID should be set on the session",
+                     PID, 
session.get(ConfigCommandSupport.PROPERTY_CONFIG_PID));
+        assertSame("The Dictionary returned by the ConfigAdmin service should 
be set on the session",
+                   props, 
session.get(ConfigCommandSupport.PROPERTY_CONFIG_PROPS));
+    }
+    
+    @SuppressWarnings("rawtypes")
+    public void testExecuteOnNewPid() throws Exception {        
+        Configuration config = createMock(Configuration.class);
+        expect(admin.getConfiguration(PID)).andReturn(config);
+        replay(admin);
+        
+        // the ConfigAdmin service does not return a Dictionary for a new PID
+        expect(config.getProperties()).andReturn(null);
+        replay(config);
+        
+        command.pid = PID; 
+        command.execute(session);
+
+        // the PID and an empty Dictionary should have been set on the session 
       
+        assertEquals("The PID should be set on the session",
+                     PID, 
session.get(ConfigCommandSupport.PROPERTY_CONFIG_PID));
+        Dictionary props = (Dictionary) 
session.get(ConfigCommandSupport.PROPERTY_CONFIG_PROPS);
+        assertNotNull("Should have a Dictionary on the session", props);
+        assertTrue("Should have an empty Dictionary on the session", 
props.isEmpty());
+    }
+
+}

Added: 
karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/MockCommandSession.java
URL: 
http://svn.apache.org/viewvc/karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/MockCommandSession.java?rev=1300211&view=auto
==============================================================================
--- 
karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/MockCommandSession.java
 (added)
+++ 
karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/MockCommandSession.java
 Tue Mar 13 16:05:10 2012
@@ -0,0 +1,69 @@
+/*
+ * 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.io.InputStream;
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.felix.service.command.CommandSession;
+
+/*
+ * A mock CommandSession implementation that only cares about the properties 
set on the session
+ */
+class MockCommandSession implements CommandSession {
+
+    private Map<String, Object> properties = new HashMap<String, Object>();
+
+    public void close() {
+        // not implemented
+    }
+
+    public Object convert(Class<?> type, Object instance) {
+        // not implemented
+        return null;
+    }
+
+    public Object execute(CharSequence commandline) throws Exception {
+        // not implemented
+        return null;
+    }
+
+    public CharSequence format(Object target, int level) {
+        // not implemented
+        return null;
+    }
+
+    public Object get(String name) {
+        return properties.get(name);
+    }
+
+    public PrintStream getConsole() {
+        // not implemented
+        return null;
+    }
+
+    public InputStream getKeyboard() {
+        // not implemented
+        return null;
+    }
+
+    public void put(String name, Object value) {
+        properties.put(name, value);
+    }
+}

Added: 
karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/UpdateCommandTest.java
URL: 
http://svn.apache.org/viewvc/karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/UpdateCommandTest.java?rev=1300211&view=auto
==============================================================================
--- 
karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/UpdateCommandTest.java
 (added)
+++ 
karaf/trunk/config/command/src/test/java/org/apache/karaf/config/command/UpdateCommandTest.java
 Tue Mar 13 16:05:10 2012
@@ -0,0 +1,86 @@
+/*
+ * 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 static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.apache.felix.service.command.CommandSession;
+import org.apache.karaf.config.core.impl.ConfigRepositoryImpl;
+import org.easymock.EasyMock;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * Test cases for {@link EditCommand}
+ */
+public class UpdateCommandTest extends TestCase {
+
+    private static final String PID = "my.test.persistent.id-other";
+
+    private UpdateCommand command;
+    private BundleContext context;
+    private ConfigurationAdmin admin;
+    private CommandSession session;
+
+    @Override
+    protected void setUp() throws Exception {
+        command = new UpdateCommand();
+
+        context = EasyMock.createMock(BundleContext.class);
+        command.setBundleContext(context);
+
+        admin = createMock(ConfigurationAdmin.class);
+        command.setConfigRepository(new ConfigRepositoryImpl(null, admin, 
null));
+        expect(context.getBundle(0)).andReturn(null).anyTimes();
+
+        replay(context);
+
+        session = new MockCommandSession();
+    }
+
+    public void testupdateOnNewFactoryPid() throws Exception {
+        Properties props = new Properties();
+
+        session.put(ConfigCommandSupport.PROPERTY_CONFIG_PID, PID);
+        session.put(ConfigCommandSupport.PROPERTY_CONFIG_PROPS, props);
+
+        Configuration configNew = createMock(Configuration.class);
+        expect(admin.getConfiguration(PID, null)).andReturn(configNew);
+        expect(configNew.getProperties()).andReturn(null);
+
+
+        Configuration configFac = createMock(Configuration.class);
+        expect(admin.createFactoryConfiguration(PID.substring(0, 
PID.indexOf('-')), null)).andReturn(configFac);
+        configFac.update(props);
+        expect(configFac.getBundleLocation()).andReturn(null);
+        replay(admin);
+        replay(configNew);
+        replay(configFac);
+
+        command.execute(session);
+
+    }
+
+}

Modified: karaf/trunk/config/management/pom.xml
URL: 
http://svn.apache.org/viewvc/karaf/trunk/config/management/pom.xml?rev=1300211&r1=1300210&r2=1300211&view=diff
==============================================================================
--- karaf/trunk/config/management/pom.xml (original)
+++ karaf/trunk/config/management/pom.xml Tue Mar 13 16:05:10 2012
@@ -79,6 +79,11 @@
             <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        
<Export-Package>org.apache.karaf.config.management</Export-Package>
+                    </instructions>
+                </configuration>
             </plugin>
         </plugins>
     </build>

Added: 
karaf/trunk/config/management/src/main/java/org/apache/karaf/config/management/ConfigMBean.java
URL: 
http://svn.apache.org/viewvc/karaf/trunk/config/management/src/main/java/org/apache/karaf/config/management/ConfigMBean.java?rev=1300211&view=auto
==============================================================================
--- 
karaf/trunk/config/management/src/main/java/org/apache/karaf/config/management/ConfigMBean.java
 (added)
+++ 
karaf/trunk/config/management/src/main/java/org/apache/karaf/config/management/ConfigMBean.java
 Tue Mar 13 16:05:10 2012
@@ -0,0 +1,89 @@
+/*
+ * 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.management;
+
+import java.io.IOException;
+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 Exception;
+
+    /**
+     * Create a new configuration for the given PID.
+     *
+     * @param pid the configuration PID.
+     * @throws Exception
+     */
+    void create(String pid) throws Exception;
+    
+    void update(String pid, Map<String, String> properties) throws IOException;
+
+    /**
+     * Delete a configuration identified by the given PID.
+     *
+     * @param pid the configuration PID to delete.
+     * @throws Exception
+     */
+    void delete(String pid) throws Exception;
+
+    /**
+     * 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 Exception;
+
+    /**
+     * 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 Exception;
+
+    /**
+     * 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 Exception;
+
+    /**
+     * 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 Exception;
+
+}

Added: 
karaf/trunk/config/management/src/main/java/org/apache/karaf/config/management/internal/ConfigMBeanImpl.java
URL: 
http://svn.apache.org/viewvc/karaf/trunk/config/management/src/main/java/org/apache/karaf/config/management/internal/ConfigMBeanImpl.java?rev=1300211&view=auto
==============================================================================
--- 
karaf/trunk/config/management/src/main/java/org/apache/karaf/config/management/internal/ConfigMBeanImpl.java
 (added)
+++ 
karaf/trunk/config/management/src/main/java/org/apache/karaf/config/management/internal/ConfigMBeanImpl.java
 Tue Mar 13 16:05:10 2012
@@ -0,0 +1,140 @@
+/*
+ * 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.management.internal;
+
+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.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+
+import org.apache.karaf.config.core.ConfigRepository;
+import org.apache.karaf.config.management.ConfigMBean;
+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 Exception {
+        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;
+    }
+
+    @SuppressWarnings("rawtypes")
+    public void create(String pid) throws Exception {
+        configRepo.update(pid, new Hashtable());
+    }
+    
+
+    public void update(String pid, Map<String, String> properties) throws 
IOException {
+        if (properties == null) {
+            properties = new HashMap<String, String>();
+        }
+        Dictionary<String, String> dictionary = new Hashtable<String, 
String>();
+        for (String key : properties.keySet()) {
+            dictionary.put(key, properties.get(key));
+        }
+        configRepo.update(pid, dictionary);
+    }
+
+    public void delete(String pid) throws Exception {
+        this.configRepo.delete(pid);
+    }
+
+    @SuppressWarnings("rawtypes")
+    public Map<String, String> listProperties(String pid) throws Exception {
+        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;
+    }
+
+    @SuppressWarnings("rawtypes")
+    public void deleteProperty(String pid, String key) throws Exception {
+        Dictionary dictionary = getConfigProperties(pid);
+        dictionary.remove(key);
+        configRepo.update(pid, dictionary, false);
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public void appendProperty(String pid, String key, String value) throws 
Exception {
+        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, false);
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public void setProperty(String pid, String key, String value) throws 
Exception {
+        Dictionary dictionary = getConfigProperties(pid);
+        dictionary.put(key, value);
+        configRepo.update(pid, dictionary, false);
+    }
+
+    public void setConfigRepo(ConfigRepository configRepo) {
+        this.configRepo = configRepo;
+    }
+
+}


Reply via email to