You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by sg...@apache.org on 2007/12/07 17:38:28 UTC
svn commit: r602145 - in /commons/sandbox/exec/trunk/src:
main/java/org/apache/commons/exec/
main/java/org/apache/commons/exec/environment/
main/java/org/apache/commons/exec/util/ test/java/org/apache/commons/exec/
test/java/org/apache/commons/exec/util/
Author: sgoeschl
Date: Fri Dec 7 08:38:27 2007
New Revision: 602145
URL: http://svn.apache.org/viewvc?rev=602145&view=rev
Log:
Adding command line expansion based on user-supplied map
Added:
commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/util/
commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/util/MapUtils.java
commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/util/
commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/util/MapUtilTest.java
Modified:
commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/CommandLine.java
commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/environment/DefaultProcessingEnvironment.java
commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/environment/EnvironmentUtil.java
commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/CommandLineTest.java
Modified: commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/CommandLine.java
URL: http://svn.apache.org/viewvc/commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/CommandLine.java?rev=602145&r1=602144&r2=602145&view=diff
==============================================================================
--- commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/CommandLine.java (original)
+++ commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/CommandLine.java Fri Dec 7 08:38:27 2007
@@ -18,10 +18,13 @@
package org.apache.commons.exec;
+import org.apache.commons.exec.util.StringUtils;
+
import java.io.File;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;
+import java.util.Map;
/**
* CommandLine objects help handling command lines specifying processes to
@@ -44,6 +47,11 @@
private String executable = null;
/**
+ * A map of name value pairs used to expand command line arguments
+ */
+ private Map substitutionMap;
+
+ /**
* Create a command line from a string.
*
* @param line
@@ -53,6 +61,21 @@
* @throws IllegalArgumentException If line is null or all whitespace
*/
public static CommandLine parse(final String line) {
+ return parse(line, null);
+ }
+
+ /**
+ * Create a command line from a string.
+ *
+ * @param line
+ * the line: the first element becomes the executable, the rest
+ * the arguments
+ * @param substitutionMap the name/value pairs used for substitution
+ * @return the parsed command line
+ * @throws IllegalArgumentException If line is null or all whitespace
+ */
+ public static CommandLine parse(final String line, Map substitutionMap) {
+
if (line == null) {
throw new IllegalArgumentException("Command line can not be null");
} else if (line.trim().length() == 0) {
@@ -61,6 +84,7 @@
String[] tmp = translateCommandline(line);
CommandLine cl = new CommandLine(tmp[0]);
+ cl.setSubstitutionMap(substitutionMap);
for (int i = 1; i < tmp.length; i++) {
cl.addArgument(tmp[i]);
}
@@ -93,7 +117,7 @@
* @return The executable
*/
public String getExecutable() {
- return executable;
+ return this.expandArgument(executable);
}
/**
@@ -185,8 +209,25 @@
* @return The quoted arguments
*/
public String[] getArguments() {
- String[] res = new String[arguments.size()];
- return (String[]) arguments.toArray(res);
+ String[] result = new String[arguments.size()];
+ result = (String[]) arguments.toArray(result);
+ return this.expandArguments(result);
+ }
+
+ /**
+ * @return the substitution map
+ */
+ public Map getSubstitutionMap() {
+ return substitutionMap;
+ }
+
+ /**
+ * Set the substitutionMap to expand variables in the
+ * command line
+ * @param substitutionMap the map
+ */
+ public void setSubstitutionMap(Map substitutionMap) {
+ this.substitutionMap = substitutionMap;
}
// --- Implementation ---------------------------------------------------
@@ -232,6 +273,31 @@
}
}
+ /**
+ * Expand variables in a command line argument.
+ *
+ * @param argument the argument
+ * @return the expanded string
+ */
+ private String expandArgument(final String argument) {
+ StringBuffer stringBuffer = StringUtils.stringSubstitution(argument, this.getSubstitutionMap(), true);
+ return stringBuffer.toString();
+ }
+
+ /**
+ * Expand variables in a command line arguments.
+ *
+ * @param arguments the arguments to be expadedn
+ * @return the expanded string
+ */
+ private String[] expandArguments(final String[] arguments) {
+ String[] result = new String[arguments.length];
+ for(int i=0; i<result.length; i++) {
+ result[i] = this.expandArgument(arguments[i]);
+ }
+ return result;
+ }
+
/**
* Returns the command line as an array of strings, correctly quoted
@@ -249,7 +315,7 @@
index++;
}
- return result;
+ return expandArguments(result);
}
/**
Modified: commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/environment/DefaultProcessingEnvironment.java
URL: http://svn.apache.org/viewvc/commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/environment/DefaultProcessingEnvironment.java?rev=602145&r1=602144&r2=602145&view=diff
==============================================================================
--- commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/environment/DefaultProcessingEnvironment.java (original)
+++ commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/environment/DefaultProcessingEnvironment.java Fri Dec 7 08:38:27 2007
@@ -33,6 +33,7 @@
import org.apache.commons.exec.Executor;
import org.apache.commons.exec.OS;
import org.apache.commons.exec.PumpStreamHandler;
+import org.apache.commons.exec.util.MapUtils;
/**
* Helper class to determine the environment variable
@@ -57,24 +58,15 @@
*/
public synchronized Map getProcEnvironment() throws IOException {
- HashMap result = new HashMap();
-
if(procEnvironment == null) {
procEnvironment = this.createProcEnvironment();
}
- // create a clone of the map just in case that
+ // create a copy of the map just in case that
// anyone is going to modifiy it, e.g. removing
// or setting an evironment variable
- Iterator iter = procEnvironment.keySet().iterator();
- while(iter.hasNext()) {
- Object key = iter.next();
- Object value = procEnvironment.get(key);
- result.put(key, value);
- }
-
- return result;
+ return MapUtils.copy(procEnvironment);
}
/**
Modified: commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/environment/EnvironmentUtil.java
URL: http://svn.apache.org/viewvc/commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/environment/EnvironmentUtil.java?rev=602145&r1=602144&r2=602145&view=diff
==============================================================================
--- commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/environment/EnvironmentUtil.java (original)
+++ commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/environment/EnvironmentUtil.java Fri Dec 7 08:38:27 2007
@@ -88,7 +88,14 @@
String[] parsedVarible = parseEnvironmentVariable(keyAndValue);
environment.put(parsedVarible[0], parsedVarible[1]);
}
-
+
+ /**
+ * Split a key/value pair into a String[]. It is assumed
+ * that the ky/value pair contains a '=' character.
+ *
+ * @param keyAndValue the key/value pair
+ * @return a String[] containing the key and value
+ */
private static String[] parseEnvironmentVariable(final String keyAndValue) {
int index = keyAndValue.indexOf('=');
if (index == -1) {
Added: commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/util/MapUtils.java
URL: http://svn.apache.org/viewvc/commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/util/MapUtils.java?rev=602145&view=auto
==============================================================================
--- commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/util/MapUtils.java (added)
+++ commons/sandbox/exec/trunk/src/main/java/org/apache/commons/exec/util/MapUtils.java Fri Dec 7 08:38:27 2007
@@ -0,0 +1,84 @@
+package org.apache.commons.exec.util;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * Helper classes to manipulate maps to pass substition map to the
+ * CommandLine.
+ *
+ * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
+ */
+public class MapUtils
+{
+ /**
+ * Clones a map.
+ *
+ * @param source the source map
+ * @return the clone of the source map
+ */
+ public static Map copy(Map source) {
+
+ if(source == null) {
+ return null;
+ }
+
+ Map result = new HashMap();
+ result.putAll(source);
+ return result;
+ }
+
+ /**
+ * Clones a map and prefixes the keys in the clone, e.g.
+ * for mapping "JAVA_HOME" to "env.JAVA_HOME" to simulate
+ * the behaviour of ANT.
+ *
+ * @param source the source map
+ * @return the clone of the source map
+ */
+ public static Map prefix(Map source, String prefix) {
+
+ Map result = new HashMap();
+
+ if(source == null) {
+ return null;
+ }
+
+ Iterator iter = source.keySet().iterator();
+
+ while(iter.hasNext()) {
+ Object key = iter.next();
+ Object value = source.get(key);
+ result.put(prefix + '.' + key.toString(), value);
+ }
+
+ return result;
+ }
+
+ /**
+ * Clones the lhs map and add all things from the
+ * rhs map.
+ *
+ * @param lhs the first map
+ * @param rhs the second map
+ * @return the merged map
+ */
+ public static Map merge(Map lhs, Map rhs) {
+
+ Map result = null;
+
+ if((lhs == null) || (lhs.size() == 0)) {
+ result = copy(rhs);
+ }
+ else if((rhs == null) || (rhs.size() == 0)) {
+ result = copy(lhs);
+ }
+ else {
+ result = copy(lhs);
+ result.putAll(rhs);
+ }
+
+ return result;
+ }
+}
Modified: commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/CommandLineTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/CommandLineTest.java?rev=602145&r1=602144&r2=602145&view=diff
==============================================================================
--- commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/CommandLineTest.java (original)
+++ commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/CommandLineTest.java Fri Dec 7 08:38:27 2007
@@ -19,6 +19,7 @@
package org.apache.commons.exec;
import java.util.Arrays;
+import java.util.HashMap;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
@@ -242,4 +243,46 @@
assertEquals(new String[] {"runMemorySud.cmd", "10", "30", "-XX:+UseParallelGC", "\"-XX:ParallelGCThreads=2\""}, cmdl.toStrings());
}
+ /**
+ * Test expanding the command line based on a user-supplied map.
+ */
+ public void testCommandLineParsingWithExpansion() {
+
+ CommandLine cmdl = null;
+
+ HashMap substitutionMap = new HashMap();
+ substitutionMap.put("JAVA_HOME", "/usr/local/java");
+ substitutionMap.put("appMainClass", "foo.bar.Main");
+
+ HashMap incompleteMap = new HashMap();
+ incompleteMap.put("JAVA_HOME", "/usr/local/java");
+
+ // do not pass substitution map
+ cmdl = CommandLine.parse("${JAVA_HOME}/bin/java ${appMainClass}");
+ assertEquals("${JAVA_HOME}/bin/java", cmdl.getExecutable());
+ assertEquals(new String[] {"${appMainClass}"}, cmdl.getArguments());
+ assertEquals("${JAVA_HOME}/bin/java ${appMainClass}", cmdl.toString());
+ assertEquals(new String[] {"${JAVA_HOME}/bin/java", "${appMainClass}"}, cmdl.toStrings());
+
+ // pass arguments with an empty map
+ cmdl = CommandLine.parse("${JAVA_HOME}/bin/java ${appMainClass}", new HashMap());
+ assertEquals("${JAVA_HOME}/bin/java", cmdl.getExecutable());
+ assertEquals(new String[] {"${appMainClass}"}, cmdl.getArguments());
+ assertEquals("${JAVA_HOME}/bin/java ${appMainClass}", cmdl.toString());
+ assertEquals(new String[] {"${JAVA_HOME}/bin/java", "${appMainClass}"}, cmdl.toStrings());
+
+ // pass an complete substitution map
+ cmdl = CommandLine.parse("${JAVA_HOME}/bin/java ${appMainClass}", substitutionMap);
+ assertEquals("/usr/local/java/bin/java", cmdl.getExecutable());
+ assertEquals(new String[] {"foo.bar.Main"}, cmdl.getArguments());
+ assertEquals("/usr/local/java/bin/java foo.bar.Main", cmdl.toString());
+ assertEquals(new String[] {"/usr/local/java/bin/java", "foo.bar.Main"}, cmdl.toStrings());
+
+ // pass an incomplete substitution map resulting in unresolved variables
+ cmdl = CommandLine.parse("${JAVA_HOME}/bin/java ${appMainClass}", incompleteMap);
+ assertEquals("/usr/local/java/bin/java", cmdl.getExecutable());
+ assertEquals(new String[] {"${appMainClass}"}, cmdl.getArguments());
+ assertEquals("/usr/local/java/bin/java ${appMainClass}", cmdl.toString());
+ assertEquals(new String[] {"/usr/local/java/bin/java", "${appMainClass}"}, cmdl.toStrings());
+ }
}
Added: commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/util/MapUtilTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/util/MapUtilTest.java?rev=602145&view=auto
==============================================================================
--- commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/util/MapUtilTest.java (added)
+++ commons/sandbox/exec/trunk/src/test/java/org/apache/commons/exec/util/MapUtilTest.java Fri Dec 7 08:38:27 2007
@@ -0,0 +1,75 @@
+/*
+ * 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.commons.exec.util;
+
+import org.apache.commons.exec.CommandLine;
+import org.apache.commons.exec.environment.EnvironmentUtil;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+public class MapUtilTest extends TestCase
+{
+ /**
+ * Test copying of map
+ */
+ public void testCopyMap() throws Exception {
+
+ HashMap procEnvironment = new HashMap();
+ procEnvironment.put("JAVA_HOME", "/usr/opt/java");
+
+ Map result = MapUtils.copy(procEnvironment);
+ assertTrue(result.size() == 1);
+ assertTrue(procEnvironment.size() == 1);
+ assertEquals("/usr/opt/java", result.get("JAVA_HOME"));
+
+ result.remove("JAVA_HOME");
+ assertTrue(result.size() == 0);
+ assertTrue(procEnvironment.size() == 1);
+ }
+
+ /**
+ * Test merging of maps
+ */
+ public void testMergeMap() throws Exception {
+
+ Map procEnvironment = EnvironmentUtil.getProcEnvironment();
+ HashMap applicationEnvironment = new HashMap();
+
+ applicationEnvironment.put("appMainClass", "foo.bar.Main");
+ Map result = MapUtils.merge(procEnvironment, applicationEnvironment);
+ assertTrue((procEnvironment.size() + applicationEnvironment.size()) == result.size());
+ assertEquals("foo.bar.Main", result.get("appMainClass"));
+ }
+
+ /**
+ * Test prefixing of map
+ */
+ public void testPrefixMap() throws Exception {
+
+ HashMap procEnvironment = new HashMap();
+ procEnvironment.put("JAVA_HOME", "/usr/opt/java");
+
+ Map result = MapUtils.prefix(procEnvironment, "env");
+ assertTrue(procEnvironment.size() == result.size());
+ assertEquals("/usr/opt/java", result.get("env.JAVA_HOME"));
+ }
+}
\ No newline at end of file