/* * Copyright (C) 2009-2017 Alistair Neil * * 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 2 * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package lib; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.SwingWorker; /** * * @author Alistair Neil */ public class ClientProcess { public static final int CLIENT_STOPPED = 0; public static final int CLIENT_RUNNING = 1; public static final int CLIENT_TIMEDOUT = 2; private long initialdelay = 0; private volatile long startupTimeout; private SwingWorker, String> swWorker; private volatile Process procApplication; private PrintWriter pwWriter; private volatile Thread threadSleep; private int intStatus = CLIENT_STOPPED; /** * Constructor */ public ClientProcess() { setStartupTimeout(15); } /** * Set the initial delay that is executed prior to starting the process * * @param ms */ public final void setStartupDelay(long ms) { initialdelay = ms; } /** * Set startup timeout * * @param seconds */ public final void setStartupTimeout(long seconds) { startupTimeout = seconds * 1000; } /** * Starts the client process * * @param processpath */ public final void start(final String processpath) { swWorker = new SwingWorker, String>() { String line; int endstatus; @Override protected ArrayList doInBackground() { BufferedReader brProcInput = null; BufferedReader brProcError = null; try { endstatus = CLIENT_STOPPED; if (isCancelled()) { return null; } threadSleep = Thread.currentThread(); if (initialdelay > 0) { try { Thread.sleep(initialdelay); } catch (InterruptedException ex) { } } threadSleep = null; initialdelay = 0; if (isCancelled()) { return null; } procApplication = Runtime.getRuntime().exec(processpath); if (procApplication == null) { return null; } brProcInput = new BufferedReader(new InputStreamReader(procApplication.getInputStream()), 512); brProcError = new BufferedReader(new InputStreamReader(procApplication.getErrorStream()), 512); pwWriter = new PrintWriter(procApplication.getOutputStream()); long timeout = System.currentTimeMillis() + startupTimeout; while (!isCancelled()) { if (brProcInput.ready()) { timeout = System.currentTimeMillis() + startupTimeout; // Read process notifications line = brProcInput.readLine(); publish(line); } if (brProcError.ready()) { timeout = System.currentTimeMillis() + startupTimeout; // Read process notifications line = brProcError.readLine(); publish(line); } if (System.currentTimeMillis() > timeout && startupTimeout > 0) { endstatus = CLIENT_TIMEDOUT; break; } threadSleep = Thread.currentThread(); try { Thread.sleep(20); } catch (InterruptedException ex) { } threadSleep = null; } } catch (Exception ex) { Logger.getGlobal().logp(Level.INFO, ClientProcess.class.getName(), "SwingWorker Loop Exception", ex.getMessage()); } finally { // Cleanup resources try { if (brProcInput != null) { brProcInput.close(); } if (brProcError != null) { brProcError.close(); } pwWriter.close(); // Destroy process if (procApplication != null) { procApplication.getOutputStream().close(); procApplication.getInputStream().close(); procApplication.getErrorStream().close(); procApplication.destroy(); } } catch (Exception ex) { Logger.getGlobal().logp(Level.INFO, ClientProcess.class.getName(), "SwingWorker Cleanup", ex.getMessage()); } } return null; } @Override protected void process(List chunks) { for (String s : chunks) { if (s != null) { clientProcessEventFired(s); } } } @Override protected void done() { intStatus = endstatus; clientProcessEventFired(""); } }; intStatus = CLIENT_RUNNING; clientProcessEventFired(""); // Start client process swWorker.execute(); } public final int getClientStatus() { return intStatus; } /** * Return the client system process * * @return a process */ public final Process getProcess() { return procApplication; } /** * Stops the client process * */ public final void stopProcess() { if (threadSleep != null) { threadSleep.interrupt(); } if (swWorker != null) { swWorker.cancel(true); } try { procApplication.waitFor(); } catch (Exception ex) { Logger.getGlobal().logp(Level.INFO, ClientProcess.class.getName(), "stopProcess", ex.getMessage()); } } /** * Send a message to the process * * @param message */ public final void sendMessage(String message) { pwWriter.write(message); } /** * Event from the process, should be overriden by sub class * * @param data */ public void clientProcessEventFired(String data) { } }