Package ro.redeul.google.go.util

Source Code of ro.redeul.google.go.util.ProcessUtil

package ro.redeul.google.go.util;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;

import java.io.*;
import java.nio.CharBuffer;
import java.util.List;

@SuppressWarnings({"SynchronizationOnLocalVariableOrMethodParameter"})
public class ProcessUtil {

    private static final Logger LOG = Logger.getInstance("ro.redeul.google.go.util.ProcessUtil");

    public interface StreamParser<T> {
        T parseStream(String data);
    }

    public static StreamParser<String> NULL_PARSER = new StreamParser<String>() {
        public String parseStream(String data) {
            return data;
        }
    };

    @SuppressWarnings({"SynchronizationOnLocalVariableOrMethodParameter"})

    public static <T1, T2> Pair<T1, T2> executeAndProcessOutput(List<String> command, File startingFolder, StreamParser<T1> stdParser, StreamParser<T2> errParser) {
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.directory(startingFolder);

        final Ref<Pair<T1, T2>> result = Ref.create(null);

        startProcessAndWatchOutput(processBuilder, result, stdParser, errParser);

        synchronized (result) {
            while (result.isNull()) {
                try {
                    result.wait(200);
                } catch (InterruptedException e) {
                    break;
                }
            }
        }

        return result.get();
    }


    private static <T1, T2> void startProcessAndWatchOutput(ProcessBuilder processBuilder, final Ref<Pair<T1, T2>> result, final StreamParser<T1> stdParser, final StreamParser<T2> errParser) {
        final Process process;
        try {
            process = processBuilder.start();
        } catch (IOException e) {
            LOG.info("Exception launching process: ", e);
            synchronized (result) {
                result.set(new Pair<T1, T2>(null, null));
                result.notifyAll();
            }
            return;
        }

        LOG.info("process started");
        final Thread thread = new Thread(new Runnable() {
            public void run() {
                try {
                    eatOutStreams(process, result, stdParser, errParser);
                }
                catch (Exception e) {
                    LOG.info("exception: ", e);
                    synchronized (result) {
                        result.set(new Pair<T1, T2>(null, null));
                        result.notifyAll();
                    }
                }
            }
        }, "Google Go Sdk detecting script output streams reader");

        thread.setDaemon(true);

        thread.start();
    }

    @SuppressWarnings({"SynchronizationOnLocalVariableOrMethodParameter"})
    private static <T1, T2> void eatOutStreams(Process process, Ref<Pair<T1, T2>> result, StreamParser<T1> stdParser, StreamParser<T2> errParser) throws Exception {
        final InputStream stdError = process.getErrorStream();
        final InputStream stdOutput = process.getInputStream();

        final Reader errReader = new InputStreamReader(stdError);
        final Reader outReader = new InputStreamReader(stdOutput);

        final StringBuilder err = new StringBuilder();
        final StringBuilder out = new StringBuilder();

        final CharBuffer buffer = CharBuffer.allocate(1024);

        long startTime = System.currentTimeMillis();
        boolean dataRead, processIsStillRunning;
        do {

            LOG.info("draining");
            dataRead = false;
            processIsStillRunning = false;

            while (stdError.available() > 0) {
                LOG.info("Error output stream data");
                final int count = errReader.read(buffer);
                err.append(buffer.array(), 0, count);
                dataRead = true;
            }

            while (stdOutput.available() > 0) {
                LOG.info("stdout output stream data");
                final int count = outReader.read(buffer);
                out.append(buffer.array(), 0, count);
                dataRead = true;
            }

            try {
                process.exitValue();
            } catch (IllegalThreadStateException e) {
                processIsStillRunning = true;
                Thread.sleep(50L);
            }
        } while (dataRead || (processIsStillRunning && (System.currentTimeMillis() - startTime < 2000)));

        synchronized (result) {
            result.set(
                    Pair.create(
                            stdParser != null ? stdParser.parseStream(out.toString()) : null,
                            errParser != null ? errParser.parseStream(err.toString()) : null
                    ));

            err.setLength(0);
            out.setLength(0);

            LOG.info("notifying" + result.get());
            result.notifyAll();
        }

        try {
            LOG.info("getting process exit code");
            process.exitValue();
        } catch (IllegalThreadStateException e) {

            LOG.info("exception .. waiting");
            Thread.sleep(1000L);

            LOG.info("Destroying process");
            process.destroy();
        }
    }
}
TOP

Related Classes of ro.redeul.google.go.util.ProcessUtil

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.