/*
* Perforce/Java Integration Layer
* Copyright (C) 2001-2002 David Freels
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.dafreels.vcs.command;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* Title: Description: Copyright: Copyright (c) 2001 Company: DF Systems
*
* @author David Freels
* @created July 10, 2002
* @version 1.0
*/
public final class ProcessReader extends Thread
{
private BufferedReader m_in = null;
//The input stream to read from
private BufferedReader m_err = null;
//The error stream to read from
/**
* Signals the outside process that the Process has finished and the data has
* been read.
*/
private boolean m_finished = false;
/**
* The current Process to work on
*/
private Process m_proc = null;
/**
* Tells the run method if the Thread is still running
*/
private boolean m_running = false;
/**
* Tells the ProcessReader that the Process is ready to be read
*/
private boolean m_ready = false;
private final MessageFormatter m_format = MessageFormatter.getInstance();
/**
* Singleton instance of the ProcessReader
*/
private static ProcessReader m_reader = new ProcessReader(true);
/**
* reader thread for stderr
*/
private ProcessReader m_errReader = null;
/**
* Constructor for the ProcessReader object
*/
private ProcessReader(boolean isParent)
{
m_running = true;
if ( isParent )
{
m_errReader = new ProcessReader(false);
}
this.start();
}
/**
* Gets the Instance attribute of the ProcessReader class
*
* @param proc Description
* @return The Instance value
*/
public static ProcessReader getInstance(Process proc)
{
if (m_reader == null)
{
m_reader = new ProcessReader(true);
//Set the current Process
m_reader.setProcess(proc);
return m_reader;
}
//Set the current Process
m_reader.setProcess(proc);
//Wake up the reader so it can start working
m_reader.interrupt();
return m_reader;
}
/**
* Sets the Process attribute of the ProcessReader object
*
* @param proc The new Process value
*/
private void setProcess(Process proc)
{
synchronized (this)
{
// make sure that the m_in and m_err get set before m_ready does.
// just because they come first doesn't mean that the JMM will
// execute them that way. Putting them in a synchronized block
// makes sure they get executed before m_ready is set.
m_proc = proc;
//m_err = new BufferedReader(new InputStreamReader(m_proc.getErrorStream()));
if ( m_reader == this )
{
m_in = new BufferedReader(new InputStreamReader(m_proc.getInputStream()));
m_errReader.setProcess(proc);
}
else
{
m_in = new BufferedReader(new InputStreamReader(m_proc.getErrorStream()));
}
}
m_ready = true;
}
/**
* Gets the Finished attribute of the ProcessReader object
*
* @return The Finished value
*/
public boolean isFinished()
{
if ( m_reader == this )
{
while ( !m_errReader.isFinished())
{
}
}
return m_finished;
}
/**
* Method Description
*/
public static void stopReader()
{
if (m_reader != null)
{
//Flag the Thread as not running
m_reader.m_running = false;
m_reader.m_errReader.m_running = false;
//Wake up the Thread so it can be terminated
m_reader.interrupt();
}
}
/**
* Main processing method for the ProcessReader object
*/
public void run()
{
while (m_running)
{
if (m_ready)
{
String line = "";
m_format.clearMessages();
m_format.addMessage("The command produced the following messages:");
try
{
String tmp = "";
while ((line = m_in.readLine()) != null )
{
if ( m_reader == this )
{
m_format.addMessage(line);
}
else
{
m_format.addErrorMessage(line);
}
}
//boolean moreIn = true;
//boolean moreErr = true;
// read both process stdout and stderr. If either
// one gets too full it can freeze the application,
// JBuilder7 seems to be esp. prone to freezing
// Mark Ackerman 7/10/2002
/*
while (moreIn || moreErr)
{
if (moreErr)
{
if (m_err.ready())
{
if ((line = m_err.readLine()) != null)
{
m_format.addErrorMessage(line);
}
else
{
moreErr = false;
}
}
}
if (moreIn)
{
if (m_in.ready())
{
if ((line = m_in.readLine()) != null)
{
m_format.addMessage(line);
}
else
{
moreIn = false;
}
}
}
}
*/
}
catch (IOException ioe)
{
System.out.println("[ProcessReader] (run) Error reading data from process!" +
System.getProperty("line.separator") + ioe.toString());
}
finally
{
m_proc = null;
m_finished = true;
m_ready = false;
}
}
else
{
try
{
//Sleep for 10 minutes so we don't use
//too many CPU cycles
//Thread.sleep(600000);
synchronized (this)
{
wait();
}
}
catch (InterruptedException ie)
{
//Do nothing, we were probably awaken so that a Process could be run
System.out.println("[ProcessReader] (run) Waking up ProcessReader");
}
}
}
}
public void interrupt()
{
super.interrupt();
if ( m_reader == this )
{
m_errReader.interrupt();
}
}
}