Package org.syrup.functions

Source Code of org.syrup.functions.Shell

package org.syrup.functions;

import org.syrup.Context;
import org.syrup.Function;
import org.syrup.Result;
import org.syrup.helpers.DataImpl;
import org.syrup.helpers.ResultImpl;
import org.syrup.helpers.Writer;
import org.syrup.helpers.Utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.logging.Logger;

/**
* Executes a shell command provided by the first input. The second (optional)
* input provides the stdin. The first output connects to stdout and the second
* output to stderr. If the second input is not given the first (command) input
* is consumed. The second input is always consumed.
*
* @author Robbert van Dalen
*/
public class Shell extends Thread implements Function
{
    static final String COPYRIGHT = "Copyright 2005 Robbert van Dalen."
        + "At your option, you may copy, distribute, or make derivative works under "
        + "the terms of The Artistic License. This License may be found at "
        + "http://www.opensource.org/licenses/artistic-license.php. "
        + "THERE IS NO WARRANTY; USE THIS PRODUCT AT YOUR OWN RISK.";

    private final static Logger logger = Logger.getLogger("org.syrup.functions.Shell");

    /*
     * The shell process.
     */
    private java.lang.Process p = null;

    /**
     */
    public Result execute(Context context)
    {
        boolean consume_command = true;

        try
        {
            if (Utils.isFull(context.in_1_link()))
            {
                String command = new String(context.in_1_link().content().bytes());
                try
                {
                    // The following clutch is needed with JVM 1.4.2 and lower.
                    // For JVM 1.5 and higher it can be implemented much better.
                    String[] i = null;
                    String os = System.getProperty("os.name");
                    if (os.toLowerCase().indexOf("windows") >= 0)
                    {
                        String[] k =
                        {
                            "cmd.exe", "/C", command
                        };
                        i = k;
                    }
                    else
                    {
                        String[] k =
                        {
                            "sh", "-c", command
                        };
                        i = k;
                    }
                    /*
                     * Start the shell. Add shutdown hook to make sure that
                     * after JVM shutdown, the shell is also terminated.
                     */
                    p = Runtime.getRuntime().exec(i);
                    Runtime.getRuntime().addShutdownHook(this);
                }
                catch (Error e)
                {
                    if (p != null)
                    {
                        p.destroy();
                    }
                    throw new Exception("Shell died exceptionally");
                }

                ByteArrayInputStream input = new ByteArrayInputStream(new byte[0]);
                ;

                /*
                 * Create the shell's stdin buffer if the first input != null.
                 */
                if (Utils.isFull(context.in_2_link()))
                {
                    consume_command = false;
                    input = new ByteArrayInputStream(context.in_2_link().content().bytes());
                }

                /*
                 * Create the shell's stdout and stderr buffers.
                 */
                ByteArrayOutputStream output = new ByteArrayOutputStream();
                ByteArrayOutputStream error = new ByteArrayOutputStream();

                /*
                 * Connect each stream (stdin, stdout, stderr) to the buffers.
                 */
                Writer w1 = new Writer(input, p.getOutputStream());
                Writer w2 = new Writer(p.getInputStream(), output);
                Writer w3 = new Writer(p.getErrorStream(), error);

                /*
                 * Wait for all Writers to terminate.
                 */
                p.waitFor();

                w1.join();
                w2.join();
                w3.join();

                if (error.size() > 0
                    && output.size() == 0)
                {
                    /*
                     * This problably indicates an error.
                     */
                    return new ResultImpl(context, consume_command, true, null, new DataImpl(error.toByteArray()));
                }
                else
                {
                    if (error.size() > 0)
                    {
                        /*
                         * This indicates stdout + stderr Not clear how to
                         * handle this if it does indicate a real problem.
                         */
                        return new ResultImpl(context, consume_command, true, new DataImpl(output.toByteArray()), new DataImpl(error.toByteArray()));
                    }
                    else
                    {
                        /*
                         * This indicates stdout without stderr.
                         */
                        if (output.size() > 0)
                        {
                            return new ResultImpl(context, consume_command, true, new DataImpl(output.toByteArray()), null);
                        }
                        else
                        {
                            return new ResultImpl(context, consume_command, true, null, null);
                        }
                    }
                }
            }
            else
            {
                throw new Exception("first input is mandatory");
            }
        }
        catch (Throwable e1)
        {
            return new ResultImpl(context, true, true, null, org.syrup.helpers.Utils.manageError(logger, e1, "Shell error"));
        }
        finally
        {
            // Remove shutdown hook after execution.
            Runtime.getRuntime().removeShutdownHook(this);
        }
    }

    /**
     * Executed when the JVM is in shutdown.
     */
    public void run()
    {
        // Destroy shell.
        p.destroy();
    }
}
TOP

Related Classes of org.syrup.functions.Shell

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.