17930 ProcessUtil.exec should provide easy access to stdout/stderr
authorStephen Talley <stephen.talley@oracle.com>
Wed, 23 Feb 2011 14:52:02 -0500
changeset 659 64f4f9dd81ee
parent 658 278fba81c0c1
child 660 e90bb790d26e
17930 ProcessUtil.exec should provide easy access to stdout/stderr
usr/src/java/util/org/opensolaris/os/vp/util/misc/ProcessResult.java
usr/src/java/util/org/opensolaris/os/vp/util/misc/ProcessUtil.java
usr/src/java/util/org/opensolaris/os/vp/util/misc/exception/CommandFailedException.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/util/misc/ProcessResult.java	Wed Feb 23 14:52:02 2011 -0500
@@ -0,0 +1,98 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ */
+
+package org.opensolaris.os.vp.util.misc;
+
+public class ProcessResult {
+    //
+    // Instance data
+    //
+
+    private String[] command;
+    private int exitValue;
+    private byte[] stdout;
+    private byte[] stderr;
+
+    //
+    // Constructors
+    //
+
+    public ProcessResult(String[] command, int exitValue, byte[] stdout,
+	byte[] stderr) {
+
+	this.command = command;
+	this.exitValue = exitValue;
+	this.stdout = stdout;
+	this.stderr = stderr;
+    }
+
+    //
+    // ProcessResult methods
+    //
+
+    public String[] getCommand() {
+	return command;
+    }
+
+    public int getExitValue() {
+	return exitValue;
+    }
+
+    public byte[] getStdout() {
+	return stdout;
+    }
+
+    public String getStdoutAsString() {
+	return getAsString(stdout);
+    }
+
+    public String[] getStdoutAsStrings() {
+	return getAsStrings(stdout);
+    }
+
+    public byte[] getStderr() {
+	return stderr;
+    }
+
+    public String getStderrAsString() {
+	return getAsString(stderr);
+    }
+
+    public String[] getStderrAsStrings() {
+	return getAsStrings(stderr);
+    }
+
+    //
+    // Private methods
+    //
+
+    private String getAsString(byte[] b) {
+	return new String(b).replaceFirst("(\r?\n)+$", "");
+    }
+
+    private String[] getAsStrings(byte[] b) {
+	return new String(b).split("\r?\n", -1);
+    }
+}
--- a/usr/src/java/util/org/opensolaris/os/vp/util/misc/ProcessUtil.java	Wed Feb 23 14:51:04 2011 -0500
+++ b/usr/src/java/util/org/opensolaris/os/vp/util/misc/ProcessUtil.java	Wed Feb 23 14:52:02 2011 -0500
@@ -20,17 +20,12 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
  */
 
 package org.opensolaris.os.vp.util.misc;
 
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.IOException;
-import java.util.List;
-import java.util.LinkedList;
+import java.io.*;
 import org.opensolaris.os.vp.util.misc.exception.CommandFailedException;
 
 public class ProcessUtil {
@@ -44,7 +39,7 @@
      * @param	    command
      *		    the command array
      *
-     * @return	    the exit code of the command
+     * @return	    the result of the command
      *
      * @exception   IOException
      *		    if an I/O error occurs
@@ -53,23 +48,30 @@
      *		    if the current thread is interrupted while
      *		    waiting for the process to finish
      */
-    public static int exec(String... command) throws IOException,
+    public static ProcessResult exec(String... command) throws IOException,
 	InterruptedException {
 
 	Process p = Runtime.getRuntime().exec(command);
 	p.waitFor();
-	return p.exitValue();
+
+	int exitValue = p.exitValue();
+	byte[] stdout = getBytes(p.getInputStream());
+	byte[] stderr = getBytes(p.getErrorStream());
+
+	return new ProcessResult(command, exitValue, stdout, stderr);
     }
 
     /**
      * Runs the given command and waits for it to complete.
      *
-     * @param	    expResult
-     *		    the expected exit code of the command
+     * @param	    expExitValue
+     *		    the expected exit value of the command
      *
      * @param	    command
      *		    the command array
      *
+     * @return	    the result of the command
+     *
      * @exception   IOException
      *		    if an I/O error occurs
      *
@@ -79,33 +81,33 @@
      *
      * @exception   CommandFailedException
      *		    if the command exits with a result other than {@code
-     *		    expResult}
+     *		    expExitValue}
      */
-    public static void exec(int expResult, String... command)
-	throws IOException, InterruptedException, CommandFailedException {
-
-	int result = exec(command);
-	if (result != expResult) {
-	    throw new CommandFailedException(command, result, expResult);
-	}
-    }
-
-    public static List<String> execOutput(int expResult, String... command)
+    public static ProcessResult exec(int expExitValue, String... command)
 	throws IOException, InterruptedException, CommandFailedException {
 
-	List<String> ret = new LinkedList<String>();
-	Process p = Runtime.getRuntime().exec(command);
-	p.waitFor();
-	if (p.exitValue() != expResult)
-	    throw new CommandFailedException(command, p.exitValue(), expResult);
+	ProcessResult result = exec(command);
+	if (result.getExitValue() != expExitValue) {
+	    throw new CommandFailedException(result);
+	}
+
+	return result;
+    }
+
+    //
+    // Private static methods
+    //
 
-        BufferedReader in =
-	    new BufferedReader(new InputStreamReader(p.getInputStream()));
-	String line = in.readLine();
-        while (line != null) {
-            ret.add(line);
-            line = in.readLine();
+    private static byte[] getBytes(InputStream in) {
+	ByteArrayOutputStream out = new ByteArrayOutputStream();
+	byte[] b = new byte[1024];
+	int n;
+	try {
+	    while ((n = in.read(b)) != -1) {
+		out.write(b, 0, n);
+	    }
+	} catch (IOException unlikely) {
 	}
-	return (ret);
+	return out.toByteArray();
     }
 }
--- a/usr/src/java/util/org/opensolaris/os/vp/util/misc/exception/CommandFailedException.java	Wed Feb 23 14:51:04 2011 -0500
+++ b/usr/src/java/util/org/opensolaris/os/vp/util/misc/exception/CommandFailedException.java	Wed Feb 23 14:52:02 2011 -0500
@@ -20,52 +20,42 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
  */
 
 package org.opensolaris.os.vp.util.misc.exception;
 
-import org.opensolaris.os.vp.util.misc.TextUtil;
+import org.opensolaris.os.vp.util.misc.*;
 
 public class CommandFailedException extends Exception {
     //
     // Instance data
     //
 
-    private String[] command;
-    private int expResult;
-    private int result;
+    private ProcessResult result;
 
     //
     // Constructors
     //
 
-    public CommandFailedException(String[] command, int result, int expResult) {
-	super(String.format(
-	    "command failed with status %d (expected %d): \"%s\"", result,
-	    expResult, TextUtil.join(" ", (Object[])command)));
-	this.command = command;
+    /**
+     * Constructs a {@code CommandFailedException}.
+     *
+     * @param	    result
+     *		    the result of the failed command
+     */
+    public CommandFailedException(ProcessResult result) {
+	super(String.format("\"%s\" failed with status %d: %s",
+	    TextUtil.join(" ", (Object[])result.getCommand()),
+	    result.getExitValue(), result.getStderrAsString()));
 	this.result = result;
     }
 
-    public CommandFailedException(String[] command, int result) {
-	this(command, result, 0);
-    }
-
     //
     // CommandFailedException methods
     //
 
-    public String[] getCommand() {
-	return command;
-    }
-
-    public int getExpectedResult() {
-	return expResult;
-    }
-
-    public int getResult() {
+    public ProcessResult getResult() {
 	return result;
     }
 }