Author: iocanel Date: Thu Nov 24 21:16:04 2011 New Revision: 1205981 URL: http://svn.apache.org/viewvc?rev=1205981&view=rev Log: [KARAF-1035] Modified config commands to accept pid as an option, in order make single command interactions possible.
Added: karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/ConfigPropertyCommandSupport.java Modified: karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/ConfigCommandSupport.java karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropAppendCommand.java karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropDelCommand.java karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropListCommand.java karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropSetCommand.java karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/UpdateCommand.java Modified: karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/ConfigCommandSupport.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/ConfigCommandSupport.java?rev=1205981&r1=1205980&r2=1205981&view=diff ============================================================================== --- karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/ConfigCommandSupport.java (original) +++ karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/ConfigCommandSupport.java Thu Nov 24 21:16:04 2011 @@ -18,9 +18,13 @@ package org.apache.karaf.shell.config; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Dictionary; +import java.util.Enumeration; +import org.apache.felix.utils.properties.Properties; import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.osgi.framework.Constants; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.service.cm.Configuration; @@ -42,7 +46,7 @@ public abstract class ConfigCommandSuppo private static final String FACTORY_SEPARATOR = "-"; private static final String FILEINSTALL_FILE_NAME="felix.fileinstall.filename"; - private File storage; + protected File storage; protected Object doExecute() throws Exception { // Get config admin service. @@ -51,23 +55,35 @@ public abstract class ConfigCommandSuppo System.out.println("ConfigurationAdmin service is unavailable."); return null; } + ConfigurationAdmin admin = getConfigurationAdmin(); + if (admin == null) { + System.out.println("ConfigAdmin service is unavailable."); + return null; + } + + doExecute(admin); + return null; + } + + protected Dictionary getEditedProps() throws Exception { + return (Dictionary) this.session.get(PROPERTY_CONFIG_PROPS); + } + + protected ConfigurationAdmin getConfigurationAdmin() { + ServiceReference ref = getBundleContext().getServiceReference(ConfigurationAdmin.class.getName()); + if (ref == null) { + return null; + } try { ConfigurationAdmin admin = (ConfigurationAdmin) getBundleContext().getService(ref); if (admin == null) { - System.out.println("ConfigAdmin service is unavailable."); return null; + } else { + return admin; } - - doExecute(admin); - } - finally { + } finally { getBundleContext().ungetService(ref); } - return null; - } - - protected Dictionary getEditedProps() throws Exception { - return (Dictionary) this.session.get(PROPERTY_CONFIG_PROPS); } protected abstract void doExecute(ConfigurationAdmin admin) throws Exception; @@ -99,6 +115,101 @@ public abstract class ConfigCommandSuppo return null; } + /** + * Saves config to storage or ConfigurationAdmin. + * @param admin + * @param pid + * @param props + * @param bypassStorage + * @throws IOException + */ + protected void update(ConfigurationAdmin admin, String pid, Dictionary props, boolean bypassStorage) throws IOException { + if (!bypassStorage && storage != null) { + persistConfiguration(admin, pid, props); + } else { + updateConfiguration(admin, pid, props); + } + } + + /** + * Persists configuration to storage. + * @param admin + * @param pid + * @param props + * @throws IOException + */ + protected void persistConfiguration(ConfigurationAdmin admin,String pid, Dictionary props) throws IOException { + File storageFile = new File(storage, pid + ".cfg"); + Configuration cfg = admin.getConfiguration(pid, null); + if (cfg != null && cfg.getProperties() != null) { + Object val = cfg.getProperties().get(FILEINSTALL_FILE_NAME); + if (val instanceof String) { + if (((String) val).startsWith("file:")) { + val = ((String) val).substring("file:".length()); + } + storageFile = new File((String) val); + } + } + Properties p = new Properties(storageFile); + for (Enumeration keys = props.keys(); keys.hasMoreElements();) { + Object key = keys.nextElement(); + if (!Constants.SERVICE_PID.equals(key) + && !ConfigurationAdmin.SERVICE_FACTORYPID.equals(key) + && !FILEINSTALL_FILE_NAME.equals(key)) { + p.put((String) key, (String) props.get(key)); + } + } + // remove "removed" properties from the file + ArrayList<String> propertiesToRemove = new ArrayList<String>(); + for (Object key : p.keySet()) { + if (props.get(key) == null + && !Constants.SERVICE_PID.equals(key) + && !ConfigurationAdmin.SERVICE_FACTORYPID.equals(key) + && !FILEINSTALL_FILE_NAME.equals(key)) { + propertiesToRemove.add(key.toString()); + } + } + for (String key : propertiesToRemove) { + p.remove(key); + } + // save the cfg file + storage.mkdirs(); + p.save(); + + } + + /** + * Updates the configuration to the {@link ConfigurationAdmin} service. + * @param admin + * @param pid + * @param props + * @throws IOException + */ + public void updateConfiguration(ConfigurationAdmin admin,String pid, Dictionary props) throws IOException { + Configuration cfg = admin.getConfiguration(pid, null); + if (cfg.getProperties() == null) { + String[] pids = parsePid(pid); + if (pids[1] != null) { + cfg = admin.createFactoryConfiguration(pids[0], null); + } + } + if (cfg.getBundleLocation() != null) { + cfg.setBundleLocation(null); + } + cfg.update(props); + } + + protected String[] parsePid(String pid) { + int n = pid.indexOf('-'); + if (n > 0) { + String factoryPid = pid.substring(n + 1); + pid = pid.substring(0, n); + return new String[] { pid, factoryPid }; + } else { + return new String[] { pid, null }; + } + } + protected void deleteStorage(String pid) throws Exception { File cfgFile = new File(storage, pid + ".cfg"); cfgFile.delete(); Added: karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/ConfigPropertyCommandSupport.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/ConfigPropertyCommandSupport.java?rev=1205981&view=auto ============================================================================== --- karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/ConfigPropertyCommandSupport.java (added) +++ karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/ConfigPropertyCommandSupport.java Thu Nov 24 21:16:04 2011 @@ -0,0 +1,71 @@ +package org.apache.karaf.shell.config; + +import java.util.Dictionary; +import org.apache.felix.gogo.commands.Option; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; + +/** + * 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) + protected String pid; + + @Option(name = "-b", aliases = { "--bypass-storage" }, multiValued = false, required = false, description = "Do not store the configuration in a properties file, but feed it directly to ConfigAdmin") + protected boolean bypassStorage; + + + protected void doExecute(ConfigurationAdmin admin) throws Exception { + Dictionary props = getEditedProps(); + if (props == null) { + System.err.println("No configuration is being edited--run the edit command first"); + } else { + propertyAction(props); + if(requiresUpdate(pid)) { + update(admin, pid, props, bypassStorage); + } + } + } + + /** + * Perform an action on the properties. + * @param props + */ + 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 + */ + @Override + protected Dictionary getEditedProps() throws Exception { + if(pid != null) { + ConfigurationAdmin configurationAdmin = getConfigurationAdmin(); + if(configurationAdmin != null) { + Configuration configuration = configurationAdmin.getConfiguration(pid); + if(configuration != null) { + return configuration.getProperties(); + } + } + } + return super.getEditedProps(); + } +} Modified: karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropAppendCommand.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropAppendCommand.java?rev=1205981&r1=1205980&r2=1205981&view=diff ============================================================================== --- karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropAppendCommand.java (original) +++ karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropAppendCommand.java Thu Nov 24 21:16:04 2011 @@ -26,29 +26,23 @@ import org.osgi.service.cm.Configuration * Appends a value to the current property value. */ @Command(scope = "config", name = "append-property", description = "Appends the given value to an existing property or creates the property with the specified name and value.") -public class PropAppendCommand extends ConfigCommandSupport { +public class PropAppendCommand extends ConfigPropertyCommandSupport { @Argument(index = 0, name = "name", description = "The name of the property", required = true, multiValued = false) String prop; @Argument(index = 1, name = "value", description = "The value to append to the property", required = true, multiValued = false) String value; - - @Override - protected void doExecute(ConfigurationAdmin admin) throws Exception { - Dictionary props = getEditedProps(); - if (props == null) { - System.err.println("No configuration is being edited--run the edit command first"); + + @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 { - 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."); - } + System.err.println("Append Failed: current value is not a String."); } - } - + } } Modified: karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropDelCommand.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropDelCommand.java?rev=1205981&r1=1205980&r2=1205981&view=diff ============================================================================== --- karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropDelCommand.java (original) +++ karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropDelCommand.java Thu Nov 24 21:16:04 2011 @@ -23,18 +23,13 @@ import org.apache.karaf.shell.commands.C import org.osgi.service.cm.ConfigurationAdmin; @Command(scope = "config", name = "delete-property", description = "Deletes a property from the configuration being edited.") -public class PropDelCommand extends ConfigCommandSupport { +public class PropDelCommand extends ConfigPropertyCommandSupport { @Argument(index = 0, name = "property", description = "The name of the property to delete", required = true, multiValued = false) String prop; - protected void doExecute(ConfigurationAdmin admin) throws Exception { - Dictionary props = getEditedProps(); - if (props == null) { - System.err.println("No configuration is being edited--run the edit command first"); - } else { - props.remove(prop); - } + @Override + public void propertyAction(Dictionary props) { + props.remove(prop); } - } Modified: karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropListCommand.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropListCommand.java?rev=1205981&r1=1205980&r2=1205981&view=diff ============================================================================== --- karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropListCommand.java (original) +++ karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropListCommand.java Thu Nov 24 21:16:04 2011 @@ -18,23 +18,27 @@ package org.apache.karaf.shell.config; import java.util.Dictionary; import java.util.Enumeration; - import org.apache.karaf.shell.commands.Command; -import org.osgi.service.cm.ConfigurationAdmin; + @Command(scope = "config", name = "list-property", description = "Lists properties from the currently edited configuration.") -public class PropListCommand extends ConfigCommandSupport { +public class PropListCommand extends ConfigPropertyCommandSupport { - protected void doExecute(ConfigurationAdmin admin) throws Exception { - Dictionary props = getEditedProps(); - if (props == null) { - System.err.println("No configuration is being edited--run the edit command first"); - } else { - for (Enumeration e = props.keys(); e.hasMoreElements();) { - Object key = e.nextElement(); - System.out.println(" " + key + " = " + props.get(key)); - } + @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; + } } Modified: karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropSetCommand.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropSetCommand.java?rev=1205981&r1=1205980&r2=1205981&view=diff ============================================================================== --- karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropSetCommand.java (original) +++ karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/PropSetCommand.java Thu Nov 24 21:16:04 2011 @@ -20,10 +20,9 @@ import java.util.Dictionary; import org.apache.karaf.shell.commands.Argument; import org.apache.karaf.shell.commands.Command; -import org.osgi.service.cm.ConfigurationAdmin; @Command(scope = "config", name = "set-property", description = "Sets a property in the currently edited configuration.") -public class PropSetCommand extends ConfigCommandSupport { +public class PropSetCommand extends ConfigPropertyCommandSupport { @Argument(index = 0, name = "property", description = "The name of the property to set", required = true, multiValued = false) String prop; @@ -31,13 +30,8 @@ public class PropSetCommand extends Conf @Argument(index = 1, name = "value", description = "The value of the property", required = true, multiValued = false) String value; - protected void doExecute(ConfigurationAdmin admin) throws Exception { - Dictionary props = getEditedProps(); - if (props == null) { - System.err.println("No configuration is being edited. Run the edit command first"); - } else { - props.put(prop, value); - } + @Override + public void propertyAction(Dictionary props) { + props.put(prop, value); } - } Modified: karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/UpdateCommand.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/UpdateCommand.java?rev=1205981&r1=1205980&r2=1205981&view=diff ============================================================================== --- karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/UpdateCommand.java (original) +++ karaf/trunk/shell/config/src/main/java/org/apache/karaf/shell/config/UpdateCommand.java Thu Nov 24 21:16:04 2011 @@ -16,35 +16,17 @@ */ package org.apache.karaf.shell.config; -import java.io.File; -import java.util.ArrayList; import java.util.Dictionary; -import java.util.Enumeration; import org.apache.karaf.shell.commands.Command; import org.apache.karaf.shell.commands.Option; -import org.apache.felix.utils.properties.Properties; -import org.osgi.framework.Constants; -import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; @Command(scope = "config", name = "update", description = "Saves and propagates changes from the configuration being edited.") public class UpdateCommand extends ConfigCommandSupport { - private final String FELIX_FILEINSTALL_FILENAME = "felix.fileinstall.filename"; - @Option(name = "-b", aliases = { "--bypass-storage" }, multiValued = false, required = false, description = "Do not store the configuration in a properties file, but feed it directly to ConfigAdmin") - private boolean bypassStorage; - - private File storage; - - public File getStorage() { - return storage; - } - - public void setStorage(File storage) { - this.storage = storage; - } + protected boolean bypassStorage; protected void doExecute(ConfigurationAdmin admin) throws Exception { Dictionary props = getEditedProps(); @@ -54,70 +36,8 @@ public class UpdateCommand extends Confi } String pid = (String) this.session.get(PROPERTY_CONFIG_PID); - if (!bypassStorage && storage != null) { - File storageFile = new File(storage, pid + ".cfg"); - Configuration cfg = admin.getConfiguration(pid, null); - if (cfg != null && cfg.getProperties() != null) { - Object val = cfg.getProperties().get(FELIX_FILEINSTALL_FILENAME); - if (val instanceof String) { - if (((String) val).startsWith("file:")) { - val = ((String) val).substring("file:".length()); - } - storageFile = new File((String) val); - } - } - Properties p = new Properties(storageFile); - for (Enumeration keys = props.keys(); keys.hasMoreElements();) { - Object key = keys.nextElement(); - if (!Constants.SERVICE_PID.equals(key) - && !ConfigurationAdmin.SERVICE_FACTORYPID.equals(key) - && !FELIX_FILEINSTALL_FILENAME.equals(key)) { - p.put((String) key, (String) props.get(key)); - } - } - // remove "removed" properties from the file - ArrayList<String> propertiesToRemove = new ArrayList<String>(); - for (Object key : p.keySet()) { - if (props.get(key) == null - && !Constants.SERVICE_PID.equals(key) - && !ConfigurationAdmin.SERVICE_FACTORYPID.equals(key) - && !FELIX_FILEINSTALL_FILENAME.equals(key)) { - propertiesToRemove.add(key.toString()); - } - } - for (String key : propertiesToRemove) { - p.remove(key); - } - // save the cfg file - storage.mkdirs(); - p.save(); - } else { - Configuration cfg = admin.getConfiguration(pid, null); - if (cfg.getProperties() == null) { - String[] pids = parsePid(pid); - if (pids[1] != null) { - cfg = admin.createFactoryConfiguration(pids[0], null); - } - } - if (cfg.getBundleLocation() != null) { - cfg.setBundleLocation(null); - } - cfg.update(props); - } + update(admin, pid, props, bypassStorage); this.session.put(PROPERTY_CONFIG_PID, null); this.session.put(PROPERTY_CONFIG_PROPS, null); } - - private String[] parsePid(String pid) { - int n = pid.indexOf('-'); - if (n > 0) { - String factoryPid = pid.substring(n + 1); - pid = pid.substring(0, n); - return new String[] { pid, factoryPid }; - } else { - return new String[] { pid, null }; - } - } - - }