org.globus.workspace.WorkspaceUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.globus.workspace.WorkspaceUtil.java

Source

/*
 * 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();
            }
        }
    }
}