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