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; + } + +}