org.p_vcd.process.ProcessBase.java Source code

Java tutorial

Introduction

Here is the source code for org.p_vcd.process.ProcessBase.java

Source

/*
 * Copyright (C) 2012-2015, Juan Manuel Barrios <http://juan.cl/>
 * All rights reserved.
 *
 * This file is part of P-VCD. http://p-vcd.org/
 * P-VCD is made available under the terms of the BSD 2-Clause License.
 */
package org.p_vcd.process;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ProcessBuilder.Redirect;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.p_vcd.model.MyUtil;
import org.p_vcd.model.Parameters;

public abstract class ProcessBase {

    private StatusListener status;
    private Thread processingThread;
    private boolean processRunning;
    private Process currentSystemProcess;

    public void asyncRun(StatusListener status) {
        if (status != null) {
            this.status = status;
        } else {
            this.status = new StatusListener() {
                @Override
                public void appendOutputLine(String line) {
                }

                @Override
                public void setPctProgress(String stepName, double pct) {
                }

                @Override
                public void callbackOnEnd(ProcessBase process, boolean wasSuccessful) {
                }
            };
        }
        this.processingThread = new Thread() {
            @Override
            public void run() {
                try {
                    ProcessBase.this.runProcess(ProcessBase.this.status);
                    ProcessBase.this.status.callbackOnEnd(ProcessBase.this, true);
                } catch (Throwable tr) {
                    tr.printStackTrace();
                    ProcessBase.this.status.appendOutputLine("\n\n" + tr.toString());
                    ProcessBase.this.status.setPctProgress("ERROR: " + tr.toString(), 1);
                    ProcessBase.this.status.callbackOnEnd(ProcessBase.this, false);
                }
            }
        };
        this.processingThread.start();
    }

    public void sendKillProcess() {
        if (this.processingThread != null || !this.processingThread.isAlive())
            return;
        Thread kthread = new Thread() {
            @Override
            public void run() {
                while (ProcessBase.this.processRunning) {
                    System.out.println("\ntrying to kill process...\n");
                    ProcessBase.this.status.appendOutputLine("\ntrying to kill process...\n");
                    System.out.println(ProcessBase.this.currentSystemProcess.getClass());
                    ProcessBase.this.currentSystemProcess.destroy();
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                while (ProcessBase.this.processingThread.isAlive()) {
                    System.out.println("\ninterrupting process...\n");
                    ProcessBase.this.status.appendOutputLine("\ninterrupting process...\n");
                    ProcessBase.this.processingThread.interrupt();
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        kthread.setDaemon(true);
        kthread.start();
    }

    public void waitProcess() {
        try {
            this.processingThread.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public synchronized boolean hasEnded() {
        return !this.processingThread.isAlive();
    }

    protected abstract void runProcess(StatusListener status) throws Exception;

    protected void runVlc(ProcessArguments arguments) throws Exception {
        runCommandInternal(Parameters.get().getVlcExePath(), arguments, Parameters.get().getUserDataPath(), null,
                null);
    }

    protected void runWget(ProcessArguments arguments, File workingDir, StringBuffer sbSaveStderr)
            throws Exception {
        runCommandInternal(Parameters.get().getWgetExePath(), arguments, workingDir, null, sbSaveStderr);
    }

    protected void runYoutubeDl(ProcessArguments arguments, File workingDir) throws Exception {
        runCommandInternal(Parameters.get().getYoutubedlExePath(), arguments, workingDir, null, null);
    }

    protected void runPvcdDb(ProcessArguments arguments) throws Exception {
        runPvcd("pvcd_db", arguments);
    }

    protected void runPvcdSearch(ProcessArguments arguments) throws Exception {
        runPvcd("pvcd_search", arguments);
    }

    protected void runPvcdMerge(ProcessArguments arguments) throws Exception {
        runPvcd("pvcd_mergeLocalToGlobal", arguments);
    }

    protected void runPvcdDetect(ProcessArguments arguments) throws Exception {
        runPvcd("pvcd_detect", arguments);
    }

    private void runPvcd(String command, ProcessArguments arguments) throws Exception {
        if (Parameters.get().getPvcdMaxCores() > 1)
            arguments.add("-num_cores", Parameters.get().getPvcdMaxCores());
        String binfile = command + Parameters.get().getSystemExeExtension();
        if (Parameters.get().getPvcdPath().length() > 0)
            binfile = new File(Parameters.get().getPvcdPath(), binfile).toString();
        runCommandInternal(binfile, arguments, Parameters.get().getUserDataPath(), null, null);
    }

    private void runCommandInternal(String command, ProcessArguments commandArgs, File workingDir,
            StringBuffer sbSaveStdout, StringBuffer sbSaveStderr) throws Exception {
        commandArgs.insertFirst(command);
        FileUtils.forceMkdir(workingDir);
        StringBuffer sbLog = new StringBuffer();
        sbLog.append("\n").append(MyUtil.getFormateDate());
        commandArgs.addToLog(sbLog);
        System.out.println(sbLog.toString());
        this.status.appendOutputLine(sbLog.toString());
        ProcessBuilder pb = new ProcessBuilder(commandArgs.getCommands());
        pb.directory(workingDir);
        pb.redirectInput(Redirect.INHERIT);
        pb.redirectOutput(Redirect.PIPE);
        pb.redirectError(Redirect.PIPE);
        long init = System.currentTimeMillis();
        this.currentSystemProcess = pb.start();
        PrintThreadWithStatus thStdout = new PrintThreadWithStatus(this.currentSystemProcess.getInputStream(),
                command, this.status, sbSaveStdout);
        PrintThreadWithStatus thStderr = new PrintThreadWithStatus(this.currentSystemProcess.getErrorStream(),
                command, this.status, sbSaveStderr);
        this.currentSystemProcess.getOutputStream().close();
        thStdout.start();
        thStderr.start();
        int ret = -1;
        try {
            this.processRunning = true;
            ret = this.currentSystemProcess.waitFor();
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        } finally {
            this.processRunning = false;
        }
        try {
            thStderr.join();
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        try {
            thStdout.join();
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        long milis = System.currentTimeMillis() - init;
        if (ret != 0) {
            throw new Exception("command error code=" + ret + " (" + milis + " ms)");
        }
        sbLog = new StringBuffer();
        sbLog.append(MyUtil.getFormateDate()).append("command ").append(command).append(" ok (").append(milis)
                .append(" ms)");
        System.out.println(sbLog.toString());
        this.status.appendOutputLine(sbLog.toString());
    }
}

class PrintThreadWithStatus extends Thread {

    private InputStream is;
    private String commandName;
    private StatusListener status;
    private StringBuffer sbOutput;

    public PrintThreadWithStatus(InputStream is, String commandName, StatusListener status, StringBuffer sbOutput) {
        this.is = is;
        String s = commandName;
        if (s.endsWith(".exe") || s.endsWith(".EXE"))
            s = s.substring(0, s.length() - 4);
        this.commandName = "[" + s + "] ";
        this.status = status;
        this.sbOutput = sbOutput;
    }

    @Override
    public void run() {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(commandName + line);
                this.status.appendOutputLine(line);
                if (this.sbOutput != null)
                    this.sbOutput.append(line).append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(br);
            IOUtils.closeQuietly(is);
        }
    }

    public String getSavedOutput() {
        return sbOutput.toString();
    }
}