Java tutorial
/* * Copyright 1999-2008 University of Chicago * * 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.globus.workspace; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.BufferedWriter; import java.io.OutputStreamWriter; import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService; import edu.emory.mathcs.backport.java.util.concurrent.Executors; import edu.emory.mathcs.backport.java.util.concurrent.Callable; import edu.emory.mathcs.backport.java.util.concurrent.FutureTask; import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit; public class WorkspaceUtil { private static final Log logger = LogFactory.getLog(WorkspaceUtil.class.getName()); // TODO: shutdown if container is asking for exit private static ExecutorService executor = Executors.newCachedThreadPool(); public static boolean isInvalidState(int newstate) { if (newstate == WorkspaceConstants.STATE_DESTROY_SUCCEEDED || newstate == WorkspaceConstants.STATE_DESTROY_FAILED) { return false; } return newstate < WorkspaceConstants.STATE_FIRST_LEGAL || newstate > WorkspaceConstants.STATE_LAST_LEGAL; } // Ceilings to nearest minute. public static long secondsToMinutes(long seconds) { if (seconds == 0) { return 0; } else { long minutes = seconds / 60; if (seconds % 60 > 0) { minutes += 1; } return minutes; } } /** * @param command * Array of command + arguments, to fork a process * @param eventLog log events to info? * @param traceLog alternatively, log events to trace? * @return String * The output of the process on to stdout * @throws WorkspaceException exc * @throws ReturnException * Exception containing return code other than zero and also the * stdin/stdout/stderr if needed. */ public static String runCommand(String[] command, boolean eventLog, boolean traceLog) throws WorkspaceException, ReturnException { return runCommand(command, true, null, eventLog, traceLog); } /** * @param command * Array of command + arguments, to fork a process * @param eventLog log events to info? * @param traceLog alternatively, log events to trace? * @param trackingID optional for event logging, an id > 0? * @return String * The output of the process on to stdout * @throws WorkspaceException exc * @throws ReturnException * Exception containing return code other than zero and also the * stdin/stdout/stderr if needed. */ public static String runCommand(String[] command, boolean eventLog, boolean traceLog, int trackingID) throws WorkspaceException, ReturnException { return runCommand(command, true, null, eventLog, traceLog, trackingID); } /** * @param command command array * @param event passing in false disables the event log * @param stdin stdin for process * @param eventLog log events to info? * @param traceLog alternatively, log events to trace? * @return stdout * @throws WorkspaceException exc * @throws ReturnException if exit code != 0, will contain return code * as well as stdout and stderr if they exist. */ public static String runCommand(String[] command, boolean event, String stdin, boolean eventLog, boolean traceLog) throws WorkspaceException, ReturnException { return runCommand(command, event, stdin, eventLog, traceLog, -1); } /** * @param command command array * @param event passing in false disables the event log * @param stdin stdin for process * @param eventLog log events to info? * @param traceLog alternatively, log events to trace? * @param trackingID optional for event logging, an id > 0? * @return stdout * @throws WorkspaceException exc * @throws ReturnException if exit code != 0, will contain return code * as well as stdout and stderr if they exist. */ public static String runCommand(String[] command, boolean event, String stdin, boolean eventLog, boolean traceLog, int trackingID) throws WorkspaceException, ReturnException { if (command == null) { logger.error("Command cannot be null"); throw new WorkspaceException("Command cannot be null"); } if (eventLog && event) { logger.info(Lager.ev(trackingID) + printCmd(command)); } else if (traceLog && event) { logger.trace(printCmd(command)); } final Runtime runtime = Runtime.getRuntime(); String stdout = null; String stderr = null; InputStream processStdoutStream = null; InputStream processStderrStream = null; try { final Process process = runtime.exec(command); // Unfortunately there can be buffer overflow problems if there are // not threads consuming stdout/stderr, seen that with workspace- // control create commands on certain platforms. processStderrStream = process.getErrorStream(); final FutureTask stderrConsumer = new FutureTask(new StreamConsumer(processStderrStream)); processStdoutStream = process.getInputStream(); final FutureTask stdoutConsumer = new FutureTask(new StreamConsumer(processStdoutStream)); executor.submit(stdoutConsumer); executor.submit(stderrConsumer); if (stdin != null) { if (traceLog) { logger.trace("stdin provided"); } BufferedWriter in = null; OutputStreamWriter osw = null; OutputStream os = null; try { os = process.getOutputStream(); osw = new OutputStreamWriter(os); in = new BufferedWriter(osw); in.write(stdin); in.newLine(); in.flush(); } finally { if (in != null) { in.close(); } if (osw != null) { osw.close(); } if (os != null) { os.close(); } } if (traceLog) { logger.trace("stdin sent"); } } else { OutputStream os = null; try { os = process.getOutputStream(); } finally { if (os != null) { os.close(); } } } final int returnCode; try { returnCode = process.waitFor(); } catch (InterruptedException exp) { logger.error("Interupped exp thrown ", exp); throw new WorkspaceException("Interrupted: ", exp); } if (eventLog && event) { logger.info(Lager.ev(trackingID) + "Return code is " + returnCode); } else if (traceLog && event) { logger.trace("Return code is " + returnCode); } try { stdout = (String) stdoutConsumer.get(60L, TimeUnit.SECONDS); } catch (Exception e) { logger.error(e.getMessage()); } try { stderr = (String) stderrConsumer.get(60L, TimeUnit.SECONDS); } catch (Exception e) { logger.error(e.getMessage()); } if (returnCode != 0) { if (stderr != null && stdout != null) { logger.error(Lager.ev(trackingID) + "system command FAILURE" + "\nSTDOUT:\n" + stdout + "\n\nSTDERR:\n" + stderr); throw new ReturnException(returnCode, stderr, stdout); } else if (stderr != null) { logger.error(Lager.ev(trackingID) + "system command FAILURE" + "\nSTDERR:\n" + stderr); throw new ReturnException(returnCode, stderr); } else { logger.error(Lager.ev(trackingID) + "system command FAILURE, no stdout or stderr"); throw new ReturnException(returnCode); } } else { if (stdout != null) { if (eventLog && event) { logger.info(Lager.ev(trackingID) + "\n" + "STDOUT:\n" + stdout); } else if (traceLog && event) { logger.trace("\nSTDOUT:\n" + stdout); } } } } catch (IOException ioe) { logger.error(ioe); throw new WorkspaceException("", ioe); } finally { try { if (processStdoutStream != null) { processStdoutStream.close(); } if (processStderrStream != null) { processStderrStream.close(); } } catch (IOException exp) { logger.error("Could not close stream", exp); } } // may be null return stdout; } public static String printCmd(String[] exe) { if (exe == null) { return "null"; } final StringBuffer buf = new StringBuffer(exe.length * 16); for (int i = 0; i < exe.length; i++) { buf.append(exe[i]); buf.append(" "); } return buf.toString(); } public static String scrubDEBUG(String msg) { if (msg == null) { return null; } final StringBuffer buf = new StringBuffer(msg.length()); final String[] lines = msg.split("\n"); final boolean addNewLine = (lines.length > 1); for (int i = 0; i < lines.length; i++) { if (!lines[i].matches(".*DEBUG.*")) { buf.append(lines[i]); if (addNewLine) { buf.append("\n"); } } } return buf.toString(); } private static class StreamConsumer implements Callable { final InputStream is; StreamConsumer(InputStream stream) { if (stream == null) { throw new IllegalArgumentException("stream may not be null"); } this.is = stream; } public Object call() throws Exception { InputStreamReader isr = null; BufferedReader br = null; StringBuffer output = null; try { isr = new InputStreamReader(this.is); br = new BufferedReader(isr); String line = br.readLine(); if (line != null) { output = new StringBuffer(line); while (line != null) { line = br.readLine(); if (line != null) { output.append("\n").append(line); } } } } catch (IOException e) { logger.error(e.getMessage()); } finally { try { if (br != null) { br.close(); } if (isr != null) { isr.close(); } // this.is closed at end of runCommand } catch (IOException e) { logger.error(e.getMessage()); } } if (output == null || output.length() == 0) { return null; } else { return output.toString(); } } } }