org.stanwood.podcaster.util.AbstractExecutable.java Source code

Java tutorial

Introduction

Here is the source code for org.stanwood.podcaster.util.AbstractExecutable.java

Source

/*
 *  Copyright (C) 2008  John-Paul.Stanford <dev@stanwood.org.uk>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.stanwood.podcaster.util;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.stanwood.podcaster.config.ConfigReader;

/**
 * This should be extended by classes that wrap around executables. It has methods
 * to execute the executable and get the resulting error and output streams.
 *
 */
public class AbstractExecutable {

    private final static Log log = LogFactory.getLog(AbstractExecutable.class);

    private StreamGobbler errorGobbler;
    private StreamGobbler outputGobbler;
    private Process proc;

    private ConfigReader config;

    /**
     * The constructor
     * @param config The application configuration
     */
    public AbstractExecutable(ConfigReader config) {
        this.config = config;
    }

    /**
     * Used to get the application configuration
     * @return the application configuration
     */
    public ConfigReader getConfig() {
        return config;
    }

    /**
     * Execute the command with a list of arguments. The this argument should be the application.
     * @param args The arguments. The first is the application been executed.
     * @return The exit code of the application that is executed.
     * @throws IOException Thrown if their is a IO related problem.
     * @throws InterruptedException Thrown if the thread is interrupted.
     */
    protected int execute(List<String> args) throws IOException, InterruptedException {
        proc = createProcess(args);
        errorGobbler = new StreamGobbler(proc.getErrorStream(), "stderr reader"); //$NON-NLS-1$
        outputGobbler = new StreamGobbler(proc.getInputStream(), "stdout reader"); //$NON-NLS-1$

        return AbstractExecutable.execute(proc, outputGobbler, errorGobbler);
    }

    /**
     * Used to execute a process and capture the output. This method will return when the process has finished
     * @param proc The process
     * @param outputGobbler The standard output gobbler
     * @param errorGobbler The standard error gobbler
     * @return The exit code of the process
     * @throws IOException Thrown if their are any problems
     * @throws InterruptedException Thrown if the threads are intruppted
     */
    public static int execute(Process proc, IStreamGobbler outputGobbler, IStreamGobbler errorGobbler)
            throws IOException, InterruptedException {
        outputGobbler.start();
        errorGobbler.start();
        int exitCode = proc.waitFor();
        while (!errorGobbler.isDone() || !outputGobbler.isDone()) {
        }

        errorGobbler.done();
        outputGobbler.done();

        proc.getErrorStream().close();
        proc.getInputStream().close();
        proc.getOutputStream().close();

        return exitCode;
    }

    protected Process createProcess(List<String> args) throws IOException {
        List<String> newArgs = new ArrayList<String>();
        if (System.getProperty("os.name").toLowerCase().equals("Windows 95")) { //$NON-NLS-1$ //$NON-NLS-2$
            newArgs.add("command.com"); //$NON-NLS-1$
            newArgs.add("/C"); //$NON-NLS-1$
        } else if (System.getProperty("os.name").toLowerCase().startsWith("windows")) { //$NON-NLS-1$ //$NON-NLS-2$
            newArgs.add("cmd.exe"); //$NON-NLS-1$
            newArgs.add("/C"); //$NON-NLS-1$
        }
        newArgs.addAll(args);

        if (log.isDebugEnabled()) {
            StringBuilder debugOutput = new StringBuilder();
            for (String arg : newArgs) {
                debugOutput.append(arg);
                debugOutput.append(" "); //$NON-NLS-1$
            }
            log.debug(debugOutput.toString());
        }

        ProcessBuilder pb = new ProcessBuilder(newArgs);
        return pb.start();
    }

    /**
     * Used to kill the running executable
     */
    public void kill() {
        proc.destroy();
        errorGobbler.done();
        outputGobbler.done();
    }

    /**
     * Returns the output stream generated by executing the application.
     * @return The output stream
     */
    public String getOutputStream() {
        return outputGobbler.getResult();
    }

    /**
     * Returns the error stream generated by executing the application.
     * @return The error stream
     */
    public String getErrorStream() {
        return errorGobbler.getResult();
    }

}