package multimonster.converter.plugin.jmx;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
import org.apache.log4j.Logger;
import org.jboss.system.ServiceMBeanSupport;
/**
* Used to call the native process tcprobe which is used to extract metadata.
* It is used by the <code>MetaDataExtractor</code>.
*
* @author Holger Velke
*
* @jmx.mbean name="multimonster:service=TCProbeCaller"
* extends="org.jboss.system.ServiceMBean"
* @jboss.service servicefile="jboss"
*/
public class TCProbeCaller extends ServiceMBeanSupport implements TCProbeCallerMBean{
static private Logger log = Logger.getLogger(TCProbeCaller.class);
// TODO externalize in setting
private String TCPROBE_PATH = "tcprobe";
private String TCPROBE_ARGS = "-B";
//TODO use other container for storing the processes
private Vector processes = null;
/**
* the jmx object name of the MBean
*/
static final public String JMX_NAME = "multimonster:service=TCProbeCaller";
/**
* @return Returns the tCPROBE_ARGS.
*
* @jmx.managed-attribute
*/
public String getTCPROBE_ARGS() {
return TCPROBE_ARGS;
}
/**
* @param tcprobe_args The tCPROBE_ARGS to set.
*
* @jmx.managed-attribute
*/
public void setTCPROBE_ARGS(String tcprobe_args) {
TCPROBE_ARGS = tcprobe_args;
}
/**
* @return Returns the tCPROBE_PATH.
*
* @jmx.managed-attribute
*/
public String getTCPROBE_PATH() {
return TCPROBE_PATH;
}
/**
* @param tcprobe_path The tCPROBE_PATH to set.
*
* @jmx.managed-attribute
*/
public void setTCPROBE_PATH(String tcprobe_path) {
TCPROBE_PATH = tcprobe_path;
}
/**
* this can only be used within the same VM.
*
* @jmx.managed-operation
*/
public TCProbeCaller returnThis() {
log.debug("returnThis()");
return this;
}
//------------------------------------------------------------------------
/**
*
* @return the <code>id</code> of the process started. The <code>id</code> is needed for the following methods.
*/
public int startTCProbeProcess(){
Process tcprobe = null;
int id = 0;
if (processes == null){
processes = new Vector();
}
try {
tcprobe = Runtime.getRuntime().exec(TCPROBE_PATH+" "+TCPROBE_ARGS);
} catch (IOException e){
log.error("problem starting tcprobe process - "+ e.getMessage());
return -1;
}
processes.add(tcprobe);
id = processes.indexOf(tcprobe);
return id;
}
/**
* sends data to the specified transcode process.
*
*
* @param id
* the id of the process the data should be sent to.
* @param data
* the data to send to the process
* @return
* <code>true</code> if more data is needed by transcode. <p>
* <code>false</code> if transcode has finished extraction and needs no more data.
* @throws IOException if there is an unsolvable proble while writing data to tcprobe
*/
public boolean sendDataToTCProbe(int id, byte[] data) throws IOException{
Process tcprobe = null;
tcprobe = getTCProbe(id);
try {
tcprobe.getOutputStream().write(data);
} catch (IOException e) {
try {
tcprobe.waitFor();
} catch (InterruptedException e1) {
log.error("error while waiting for tcprobe to finish", e);
return false;
}
if (tcprobe.exitValue() == 0){
return false;
} else {
log.error("tcprobe finished with exit value "+tcprobe.exitValue());
return false;
}
}
return true;
}
public void finishTCProbeProcess(int id){
Process tcprobe = null;
tcprobe = getTCProbe(id);
try {
tcprobe.getOutputStream().flush();
tcprobe.getOutputStream().close();
} catch (IOException e) {
log.error("problem closing tcprobe's stdin", e);
}
try {
tcprobe.waitFor();
} catch (InterruptedException e) {
log.error("problem waitng for tcprobe: "+e.getMessage());
tcprobe.destroy();
}
if (tcprobe.exitValue() != 0){
log.warn("tcprobe exited with errorcode "+tcprobe.exitValue());
}
}
/**
* get data written to the stdout by the tcprobe process
*
* @param id the id of the process
* @return the data written to stdout
* @throws IOException if an unsolvable problem occours while reading the data
*/
public byte[] getTCProbeStdout(int id) throws IOException{
byte[] result = null;
Process tcprobe = null;
InputStream tcprobeStdout = null;
tcprobe = getTCProbe(id);
tcprobeStdout = tcprobe.getInputStream();
result = new byte[tcprobeStdout.available()];
tcprobeStdout.read(result);
return result;
}
/**
* get data written to the stderr by the tcprobe process
*
* @param id the id of the process
* @return the data written to stdout
* @throws IOException if an unsolvable problem occours while reading the data
*/
public byte[] getTCProbeStderr(int id) throws IOException{
byte[] result = null;
Process tcprobe = null;
InputStream tcprobeStderr = null;
tcprobe = getTCProbe(id);
tcprobeStderr = tcprobe.getErrorStream();
result = new byte[tcprobeStderr.available()];
tcprobeStderr.read(result);
return result;
}
/**
* removes the process form the internal list.
* destroys the process.
*
* @param id the id of the tcprobe process
*/
public void removeTCProbe(int id){
Process transcode = null;
transcode = (Process) processes.remove(id);
transcode.destroy();
}
/**
* gets the process from the internal list
*
* @param id the id of the process
* @return the tcprobe process
*/
private Process getTCProbe(int id){
Process tcprobe = null;
try {
tcprobe = (Process) processes.get(id);
} catch (ArrayIndexOutOfBoundsException e){
throw new IllegalArgumentException("unknown id = "+id);
}
if (tcprobe == null){
throw new IllegalArgumentException("unknown id = "+id);
}
return tcprobe;
}
}