From: gumartinm
Date: Wed, 18 Jan 2012 01:19:01 +0000 (+0100)
Subject: Launch commands without using fork from the JVM.
X-Git-Url: https://git.gumartinm.name/?a=commitdiff_plain;h=a3ff75e35e80cc43b258f47aeda15022b5936945;p=JavaForFun
Launch commands without using fork from the JVM.
Sometimes you may receive a nice OutofMemory exception because of the overcommitting memory allocation,
although you could have still enough memory.
Issues related to fork and virtual memory.
See: http://developers.sun.com/solaris/articles/subprocess/subprocess.html
---
diff --git a/JavaFork/Daemon/README.txt b/JavaFork/Daemon/README.txt
new file mode 100644
index 0000000..604f093
--- /dev/null
+++ b/JavaFork/Daemon/README.txt
@@ -0,0 +1,3 @@
+Launch:
+
+javafork IPADDRESS TCP_PORT MAX_LISTEN
diff --git a/JavaFork/Daemon/javafork b/JavaFork/Daemon/javafork
new file mode 100755
index 0000000..6ad9212
Binary files /dev/null and b/JavaFork/Daemon/javafork differ
diff --git a/JavaFork/Daemon/javafork.c b/JavaFork/Daemon/javafork.c
new file mode 100644
index 0000000..6d78c0c
--- /dev/null
+++ b/JavaFork/Daemon/javafork.c
@@ -0,0 +1,347 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "javafork.h"
+
+
+int main (int argc, char *argv[]) {
+ pid_t pid;
+
+ if ((pid = fork()) == -1) {
+ perror("fork: ");
+ return -1;
+ }
+ else {
+ if (pid == 0) {
+ /*child process*/
+ main_child(argc, argv);
+ }
+ }
+
+ return 0;
+}
+
+
+int main_child (int argc, char *argv[]) {
+ struct protoent *protocol;
+ struct sockaddr_in addr_server;
+ struct sockaddr_in addr_client;
+ int sockfd;
+ int sockclient;
+ pthread_t idThread;
+ int clilen;
+
+
+ daemonize(argv[0], LOG_SYSLOG, LOG_PID);
+ setsid();
+
+ signal(SIGPIPE,SIG_IGN);
+
+ /*Retrieve protocol number from /etc/protocols file */
+ protocol=getprotobyname("tcp");
+ if (protocol == NULL) {
+ syslog(LOG_ERR, "cannot map \"tcp\" to protocol number");
+ exit (1);
+ }
+
+ bzero((char*) &addr_server, sizeof(addr_server));
+ addr_server.sin_family = AF_INET;
+ if (inet_pton(AF_INET, argv[1], &addr_server.sin_addr.s_addr) <= 0)
+ syslog (LOG_ERR, "error inet_pton");
+
+ addr_server.sin_port = htons(atol(argv[2]));
+
+ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ syslog (LOG_ERR, "socket creation failed");
+ exit(1);
+ }
+
+ if (bind(sockfd, (struct sockaddr *) &addr_server, sizeof(addr_server)) < 0) {
+ syslog (LOG_ERR, "socket bind failed");
+ exit(1);
+ }
+
+ if (listen (sockfd, atoi(argv[3])) < 0 ) {
+ syslog (LOG_ERR, "socket listen failed");
+ exit(1);
+ }
+
+ while(1) {
+ clilen = sizeof(addr_client);
+ if ((sockclient = accept (sockfd, (struct sockaddr *) &addr_client, &clilen)) < 0) {
+ syslog (LOG_ERR, "socket accept failed");
+ exit(1);
+ }
+ if (pthread_create (&idThread, NULL, serverThread, (void *)sockclient) != 0 ) {
+ syslog (LOG_ERR, "thread creation failed");
+ }
+ }
+}
+
+
+int daemonize(const char *pname, int facility, int option) {
+ int fd;
+
+ if ( (fd = open( "/dev/tty", O_RDWR, 0) ) == -1) {
+ /*We already have no tty control*/
+ close(fd);
+ return 0;
+ }
+
+ /*Sending messages to log*/
+ openlog(pname, option, facility);
+
+ ioctl(fd, TIOCNOTTY, (caddr_t)0);
+ close(fd);
+
+ if((fd = open( "/dev/null", O_RDWR, 0) ) == -1) {
+ close(fd);
+ return 0;
+ }
+ dup2(fd,0);
+ dup2(fd,1);
+ dup2(fd,2);
+ close(fd);
+
+ return 0;
+}
+
+void *serverThread (void * arg) {
+ int sockclient;
+ int n;
+ char buf[512];
+
+ sockclient = (int) arg;
+ pthread_detach(pthread_self());
+
+ n = recv(sockclient, buf, sizeof(buf), 0);
+ if(n > 0){
+ buf[n] = '\0';
+ fork_system(sockclient, buf);
+ }
+
+ close(sockclient);
+
+ pthread_exit(0);
+}
+
+
+int fork_system(int socket, char *command) {
+ int pid;
+ int pfdOUT[2];
+ int pfdERR[2];
+ char buf[2000];
+ char string[100];
+ struct pollfd polls[2];
+ int returnstatus;
+ int n;
+
+ sem_t * semaphore;
+ /*Required variables in order to share memory between processes*/
+ key_t keyvalue;
+ int idreturnst;
+ int *returnst;
+
+ if (pipe(pfdOUT) == -1) {
+ syslog (LOG_ERR, "pipe for stdout failed");
+ close(pfdOUT[0]);
+ close(pfdOUT[1]);
+ return -1;
+ }
+ if (pipe(pfdERR) == -1) {
+ syslog (LOG_ERR, "pipe for stderr failed");
+ close(pfdOUT[0]);
+ close(pfdOUT[1]);
+ close(pfdERR[0]);
+ close(pfdERR[1]);
+ return -1;
+ }
+
+ if ((semaphore = sem_open("javaforksem", O_CREAT, 0644, 1)) == SEM_FAILED) {
+ syslog (LOG_ERR, "semaphore open failed");
+ close(pfdOUT[0]);
+ close(pfdOUT[1]);
+ close(pfdERR[0]);
+ close(pfdERR[1]);
+ if (sem_close(semaphore) <0 ) {
+ syslog (LOG_ERR, "semaphore open failed and close failed");
+ }
+ if (sem_unlink("javaforksem") < 0) {
+ syslog (LOG_ERR, "semaphore open failed and unlink failed");
+ }
+ return -1;
+ }
+
+ if (sem_init(semaphore, 1, 1) < 0) {
+ syslog (LOG_ERR, "semaphore initialization failed");
+ close(pfdOUT[0]);
+ close(pfdOUT[1]);
+ close(pfdERR[0]);
+ close(pfdERR[1]);
+ if (sem_close(semaphore) <0 ) {
+ syslog (LOG_ERR, "semaphore open failed and close failed");
+ }
+ if (sem_unlink("javaforksem") < 0) {
+ syslog (LOG_ERR, "semaphore open failed and unlink failed");
+ }
+ return -1;
+ }
+
+ if (sem_wait(semaphore) < 0) {
+ syslog (LOG_ERR, "semaphore wait failed");
+ }
+
+ /*Allocate shared memory*/
+ keyvalue=ftok("/bin/ls", SHAREMEMKEY); /*the /bin/ls must exist otherwise this does not work... */
+ if (keyvalue == -1) {
+ syslog (LOG_ERR, "ftok failed");
+ /*TODO: Close again pipes and semaphore.*/
+ return -1;
+ }
+ /*Attach shared memory*/
+ idreturnst=shmget(keyvalue,sizeof(int), 0660 | IPC_CREAT);
+ if (idreturnst == -1) {
+ syslog (LOG_ERR, "shmget failed");
+ /*TODO: Close again pipes and semaphore.*/
+ return -1;
+ }
+ returnst = (int *)shmat(idreturnst, (void *)0, 0);
+ if ((*returnst)== -1) {
+ syslog (LOG_ERR, "shmat failed");
+ /*TODO: Close again pipes and semaphore.*/
+ return -1;
+ }
+
+ /*By default*/
+ (*returnst) = 0;
+
+ if ((pid=fork()) == -1) {
+ perror("fork: ");
+ close(pfdOUT[0]);
+ close(pfdOUT[1]);
+ close(pfdERR[0]);
+ close(pfdERR[1]);
+ if (sem_close(semaphore) <0 ) {
+ syslog (LOG_ERR, "semaphore open failed and close failed");
+ }
+ if (sem_unlink("javaforksem") < 0) {
+ syslog (LOG_ERR, "semaphore open failed and unlink failed");
+ }
+ return -1;
+ }
+ else {
+ /*Child process*/
+ if (pid == 0) {
+ if (dup2(pfdOUT[1],1) < 0) {
+ syslog (LOG_ERR, "child: dup2 pfdOUT failed");
+ exit(-1);
+ }
+ if (dup2(pfdERR[1],2) < 0) {
+ syslog (LOG_ERR, "child: dup2 pfdERR failed");
+ exit(-1);
+ }
+ if (sem_wait(semaphore) < 0) {
+ syslog (LOG_ERR, "child: semaphore wait failed");
+ }
+ returnstatus=system(command);
+ if (WIFEXITED(returnstatus) == 1) {
+ (*returnst) = WEXITSTATUS(returnstatus);
+ }
+ else {
+ (*returnst) = -1;
+ }
+ exit(0);
+ }
+ else {
+ /*Parent process*/
+ polls[0].fd=pfdOUT[0];
+ polls[1].fd=pfdERR[0];
+ polls[0].events=POLLIN;
+ polls[1].events=POLLIN;
+ sprintf(string,"");
+ send(socket,string,strlen(string),0);
+ sprintf(string,"");
+ send(socket,string,strlen(string),0);
+ /*The child will be woken up*/
+ if (sem_post(semaphore) < 0 ) {
+ syslog (LOG_ERR, "error waiking up child process");
+ /*TODO: exit closing the descriptors*/
+ }
+ while(1){
+ if(poll(polls,2,100)){
+ if(polls[0].revents&&POLLIN) {
+ bzero(buf,2000);
+ n=read(pfdOUT[0],buf,1990);
+ sprintf(string,"");
+ send(socket,string,strlen(string),0);
+ }
+ if(polls[1].revents&&POLLIN) {
+ bzero(buf,2000);
+ n=read(pfdERR[0],buf,1990);
+ sprintf(string,"");
+ send(socket,string,strlen(string),0);
+ }
+ if(!polls[0].revents&&POLLIN && !polls[1].revents&&POLLIN) {
+ syslog (LOG_ERR, "Error polling pipes");
+ break;
+ }
+ }
+ else {
+ /*When timeout*/
+ if(waitpid(pid,NULL,WNOHANG)) {
+ /*Child is dead, we can finish the connection*/
+ break;
+ }
+ /*The child process is not dead, keep polling more data from stdout or stderr streams*/
+ }
+ }
+
+ /*We reach this code when the child process is dead or because of an error polling pipes*/
+ /*In the second case the result stored in *returnst could be wrong, anyway there was*/
+ /*an error so, the result is unpredictable.*/
+ /*TODO: if error while polling pipes do not reach this code an exit with -1*/
+ sprintf(string,"", (*returnst));
+ send(socket,string,strlen(string),0);
+ sprintf(string,"");
+ send(socket,string,strlen(string),0);
+
+ close(pfdOUT[0]);
+ close(pfdOUT[1]);
+ close(pfdERR[0]);
+ close(pfdERR[1]);
+ if (sem_close(semaphore) <0 ) {
+ syslog (LOG_ERR, "semaphore close failed");
+ }
+ if (sem_unlink("javaforksem") < 0) {
+ syslog (LOG_ERR, "semaphore unlink failed");
+ }
+
+ shmdt ((int *)returnst);
+ shmctl (idreturnst, IPC_RMID, (struct shmid_ds *)NULL);
+ }
+ }
+
+ return 0;
+}
diff --git a/JavaFork/Daemon/javafork.h b/JavaFork/Daemon/javafork.h
new file mode 100644
index 0000000..d6321a0
--- /dev/null
+++ b/JavaFork/Daemon/javafork.h
@@ -0,0 +1,7 @@
+/*System V IPC key*/
+#define SHAREMEMKEY 1
+
+void *serverThread (void *arg);
+int daemonize(const char *pname, int facility, int option);
+int main_child (int argc, char *argv[]);
+int fork_system(int socket, char *command);
diff --git a/JavaFork/JavaExample/javafork-example/pom.xml b/JavaFork/JavaExample/javafork-example/pom.xml
new file mode 100644
index 0000000..f24711c
--- /dev/null
+++ b/JavaFork/JavaExample/javafork-example/pom.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ 4.0.0
+
+ javafork
+ de.fork.java
+ 2.0-SNAPSHOT
+
+
+ javafork-example
+ javafork-example
+ http://gumartinm.name
+
+
+
+
+
diff --git a/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/ForkDaemon.java b/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/ForkDaemon.java
new file mode 100644
index 0000000..074318f
--- /dev/null
+++ b/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/ForkDaemon.java
@@ -0,0 +1,166 @@
+package de.fork.java;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.xml.sax.SAXException;
+
+/**
+ *
+ * With this class we can run processes using the intended daemon which is
+ * waiting for TCP connections in a specified port.
+ *
+ *
+ * Receiving the results in a XML format from the daemon where we can find three
+ * kinds of different fields: error, out and ret. Every field is related to the
+ * stderr, stdout and return code respectively.
+ *
+ *
+ *
+ * Example, stream received from daemon:
+ * {@code
+ *
+ * }
+ *
+ *
+ *
+ * This class has to process the above stream and it offers two methods wich can be used
+ * to retrieve the stderr and stdout in a right way without having to know about the XML stream
+ * received from the daemon. The user does not have to know about how the daemon sends the data,
+ * he or she will work directly with the strings related to each stream. Those methods
+ * are {@link ForkDaemon#getStdout()} and {@link ForkDaemon#getStderr()} The return code from the command
+ * executed by the daemon can be retrieved as a return parameter from the method
+ * {@link ForkDaemon#exec(String, String, int)}
+ *
+ *
+ * Instances of this class are mutable. To use them concurrently, clients must surround each
+ * method invocation (or invocation sequence) with external synchronization of the clients choosing.
+ *
+ */
+public class ForkDaemon {
+ private final ForkParser handler;
+
+
+ /**
+ * Simple constructor.
+ * Nothing special here.
+ *
+ */
+ public ForkDaemon () {
+ handler = new ForkParser();
+ }
+
+
+ /**
+ * This method sends commands to the daemon.
+ *
+ * It uses a TCP connection in order to send commands to the daemon and receive
+ * the results related to that command.
+ *
+ * The mehtod retrieves the stdout, stderr and the return code of that command.
+ *
+ *
The host name can either be a machine name, such as
+ * "java.sun.com", or a textual representation of its
+ * IP address. If a literal IP address is supplied, only the
+ * validity of the address format is checked.
+ *
+ *
For host specified in literal IPv6 address,
+ * either the form defined in RFC 2732 or the literal IPv6 address
+ * format defined in RFC 2373 is accepted. IPv6 scoped addresses are also
+ * supported. See here for a description of IPv6
+ * scoped addresses.
+ *
+ * @param command the command to be executed by the daemon.
+ * @param host the specified host.
+ * @param port the TCP port where the daemon accepts connections.
+ *
+ * @return the executed command's return code.
+ *
+ * @throws UnknownHostException if no IP address for the
+ * host could be found, or if a scope_id was specified
+ * @throws SecurityException if a security manager exists
+ * and its checkConnect method doesn't allow the operation
+ * @throws IOException if an I/O error occurs when creating the socket.
+ * @throws SAXException
+ * @throws FactoryConfigurationError if the implementation is not available or cannot be instantiated.
+ * @throws SAXException If any SAX errors occur during processing.
+ * @throws ParserConfigurationException
+ */
+ public int exec(final String command, String host, int port)
+ throws UnknownHostException, IOException, SAXException, ParserConfigurationException {
+ final SAXParserFactory spf = SAXParserFactory.newInstance();
+ final SAXParser saxParser = spf.newSAXParser();
+ PrintWriter out = null;
+
+ final Socket socket = new Socket(InetAddress.getByName(host), port);
+ try {
+ out = new PrintWriter(socket.getOutputStream(), true);
+ out.println(command);
+ saxParser.parse(socket.getInputStream(), handler);
+ }
+ finally {
+ if (out != null) {
+ out.close();
+ }
+ socket.close();
+ }
+
+ //Just for testing the parser by using a file instead of a TCP connection.
+ //InputSource input = new InputSource(new FileReader("/tmp/xmlfromdaemon.xml"));
+ //saxParser.parse(input, handler);
+
+ return new Integer(handler.getReturnValue()).intValue();
+ }
+
+
+ /**
+ * Retrieve the standard output.
+ *
+ * @see {@link ForkDaemon#getStderr()}
+ * @return stdout
+ */
+ public String getStdout() {
+ return handler.getStdout();
+ }
+
+
+ /**
+ *
+ * Retrieve the standard error.
+ *
+ *
+ *
+ * Example, stream received from daemon:
+ * {@code
+ *
+ * }
+ *
+ *
+ *
+ *
+ * From that example with this method we are going to obtain this return parameter:
+ * {@code
+ * ls: no se puede acceder a bbb: No existe el fichero o el directorio
+ * ls: no se puede acceder a aaa: No existe el fichero o el directorio
+ * ls: no se puede acceder a dddd: No existe el fichero o el directorio
+ * }
+ *
+ *
+ * @return stderr
+ */
+ public String getStderr() {
+ return handler.getStderr();
+ }
+}
\ No newline at end of file
diff --git a/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/ForkParser.java b/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/ForkParser.java
new file mode 100644
index 0000000..c20ba15
--- /dev/null
+++ b/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/ForkParser.java
@@ -0,0 +1,141 @@
+package de.fork.java;
+
+import org.apache.log4j.Logger;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.ext.DefaultHandler2;
+
+/**
+ *
+ * Class intended to parse the XML stream received from the daemon which is
+ * waiting to run commands. These commands are sent by the method
+ * {@link es.dia.pos.n2a.util.os.unix.ForkDaemon#exec(String, String, int)}
+ *
+ *
+ * After processing one command the daemon sends a XML stream with the stderr,
+ * stdout and return status of that command. With this class we extract those values
+ * and we can retrieve them using the methods {@link #getStderr() }, {@link #getStdout()}
+ * and {@link #getReturnValue()}
+ *
+ *
+ *
+ * Example, stream received from daemon:
+ * {@code
+ *
+ * }
+ *
+ * From the above example with this method we are going to obtain this return parameter:
+ * {@code
+ * ls: no se puede acceder a bbb: No existe el fichero o el directorio
+ * ls: no se puede acceder a aaa: No existe el fichero o el directorio
+ * ls: no se puede acceder a dddd: No existe el fichero o el directorio
+ * }
+ *
+ *
+ * @return stderr
+ */
+ public String getStderr() {
+ return stderr;
+
+ }
+
+
+ /**
+ * Retrieve the standard output.
+ *
+ * @see {@link ForkParser#getStderr()}
+ * @return stdout
+ */
+ public String getStdout() {
+ return stdout;
+ }
+
+
+ /**
+ * Retrieve the return code from the executed command.
+ *
+ * @return return status, usually 0 means the command went OK.
+ */
+ public String getReturnValue() {
+ return returnCode;
+ }
+
+
+ @Override
+ public void startElement (String uri, String localName, String qName, Attributes attributes) {
+ accumulator.setLength(0);
+ }
+
+
+ @Override
+ public void characters(char[] buffer, int start, int length) {
+ accumulator.append(buffer, start, length);
+ }
+
+ @Override
+ public void warning(SAXParseException exception) {
+ logger.error("WARNING line:" + exception.getLineNumber(), exception);
+ }
+
+ @Override
+ public void error(SAXParseException exception) {
+ logger.error("ERROR line:" + exception.getLineNumber(), exception);
+ }
+
+ @Override
+ public void fatalError(SAXParseException exception) throws SAXException {
+ logger.error("FATAL ERROR line:" + exception.getLineNumber(), exception);
+ throw (exception);
+ }
+}
\ No newline at end of file
diff --git a/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/LauncherProcesses.java b/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/LauncherProcesses.java
new file mode 100644
index 0000000..0f93fe2
--- /dev/null
+++ b/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/LauncherProcesses.java
@@ -0,0 +1,275 @@
+package de.fork.java;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.net.UnknownHostException;
+import javax.xml.parsers.ParserConfigurationException;
+import org.apache.log4j.Logger;
+import org.xml.sax.SAXException;
+
+
+public class LauncherProcesses {
+
+ private static final Logger logger = Logger.getLogger(LauncherProcesses.class);
+
+ // Exit process status
+ private static final int STATUS_ERR = -1;
+
+ private static final int DEFAULT_PORT = 5193;
+ private static final String DEFAULT_HOST = "127.0.0.1";
+
+ /**
+ * Run a process.
+ *
+ * @param command system command to be executed.
+ *
+ * @return return code.
+ */
+ public static int exec(final String command) throws IOException, InterruptedException {
+
+ return exec(command, null, null);
+ }
+
+ /**
+ * Run a process.
+ *
+ * @param command system command to execute.
+ * @param standarOutPut if not null, the standard output is redirected to this parameter.
+ *
+ * @return return code.
+ */
+ public static int exec(final String command, final PrintStream standarOutPut) throws IOException, InterruptedException {
+
+ return exec(command, standarOutPut, null);
+ }
+
+
+ /**
+ * Run a process.
+ *
+ * @param command system command to be executed.
+ * @param standarOutPut if not null, the standard output is redirected to this parameter.
+ * @param errorOutPut if not null, the error output is redirected to this parameter.
+ *
+ * @return return code from the executed system command.
+ */
+ public static int exec(final String command, final PrintStream standarOutPut, final PrintStream errorOutPut) throws IOException, InterruptedException {
+
+ return exec(command, standarOutPut, errorOutPut, DEFAULT_HOST, DEFAULT_PORT);
+ }
+
+ /**
+ * Run a process.
+ *
+ * @param command system command to be executed.
+ * @param aLogger send the information to log.
+ */
+ public static int exec(final String command, final Logger aLogger) throws IOException, InterruptedException {
+
+ //calling private method to handle logger input/ouput in a common method
+ return execHandlingLogger(command, aLogger, DEFAULT_HOST, DEFAULT_PORT);
+ }
+
+
+ /**
+ * @param commandAndArguments String array containing system command and its
+ * arguments to be executed.
+ * For example:
+ *
+ * @param aLogger
+ *
+ * @return return code from the executed system command.
+ *
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ public static int exec(final String[] commandAndArguments, final Logger aLogger) throws IOException, InterruptedException {
+ String wholeCommand="";
+
+ for(String argument : commandAndArguments) {
+ wholeCommand = wholeCommand + " " + argument;
+ }
+
+ //calling private method to handle logger input/ouput in a common method
+ return execHandlingLogger(wholeCommand, aLogger, DEFAULT_HOST, DEFAULT_PORT);
+ }
+
+
+ /**
+ *
+ * @param command system command to be executed.
+ * @param standarOutPut the stdout stream from that command as a PrintStream
+ * @param errorOutPut the stderr stream from that command as a PrintStream
+ * @param host the specified host.
+ * @param port the TCP port where the daemon accepts connections.
+ *
+ *
The host name can either be a machine name, such as
+ * "java.sun.com", or a textual representation of its
+ * IP address. If a literal IP address is supplied, only the
+ * validity of the address format is checked.
+ *
+ *
For host specified in literal IPv6 address,
+ * either the form defined in RFC 2732 or the literal IPv6 address
+ * format defined in RFC 2373 is accepted. IPv6 scoped addresses are also
+ * supported. See here for a description of IPv6
+ * scoped addresses.
+ *
+ *
+ * @return the executed command's return code.
+ *
+ * @throws UnknownHostException
+ * @throws IOException
+ */
+ public static int exec(final String command, final PrintStream standarOutPut,
+ final PrintStream errorOutPut, final String host, int port) throws IOException {
+ int exitStatus = LauncherProcesses.STATUS_ERR;
+
+ ForkDaemon process = new ForkDaemon();
+ try {
+ exitStatus = process.exec(command, host, port);
+ } catch (SAXException e) {
+ // This is not a crazy thing, we are trying to insert this new method without
+ // breaking the old methods which did not throw SAXException or ParserConfigurationException
+ //[§EJ Item 61] Do not blame me.
+ throw new IOException(e);
+ } catch (ParserConfigurationException e) {
+ // This is not a crazy thing, we are trying to insert this new method without
+ // breaking the old methods which did not throw SAXException or ParserConfigurationException
+ //[§EJ Item 61] Do not blame me.
+ throw new IOException(e);
+ }
+
+ if (standarOutPut != null) {
+ if (process.getStdout() != null) {
+ standarOutPut.println(process.getStdout());
+ }
+ }
+
+ if (errorOutPut != null) {
+ if (process.getStderr() != null) {
+ errorOutPut.println(process.getStderr());
+ }
+ }
+
+ return exitStatus;
+ }
+
+
+ /**
+ *
+ * @param command system command to be executed.
+ * @param aLogger
+ * @param host the specified host.
+ * @param port the TCP port where the daemon accepts connections.
+ *
+ * @return the executed command's return code.
+ *
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ private static int execHandlingLogger(final String command, final Logger aLogger,
+ final String host, int port) throws IOException, InterruptedException {
+ int exitStatus = LauncherProcesses.STATUS_ERR;
+
+ ForkDaemon process = new ForkDaemon();
+ try {
+ exitStatus = process.exec(command, host, port);
+ } catch (SAXException e) {
+ // This is not a crazy thing, we are trying to insert this new method without
+ // breaking the old methods which did not throw SAXException or ParserConfigurationException
+ // Do not blame me.
+ throw new IOException(e);
+ } catch (ParserConfigurationException e) {
+ // This is not a crazy thing, we are trying to insert this new method without
+ // breaking the old methods which did not throw SAXException or ParserConfigurationException
+ // Do not blame me.
+ throw new IOException(e);
+ }
+
+ if (process.getStdout() != null) {
+ aLogger.info(process.getStdout());
+ }
+ if (process.getStderr() != null) {
+ aLogger.error(process.getStderr());
+ }
+
+ return exitStatus;
+ }
+
+
+ /**
+ * @param command command and its arguments to be executed.
+ * For example:
+ *
+ * @param aLogger send information to log
+ *
+ * @return the executed command's return code.
+ *
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ public static InputStream execStream (final String [] command, final Logger aLogger)
+ throws IOException, InterruptedException {
+ int exitStatus = LauncherProcesses.STATUS_ERR;
+
+ InputStream stdInput = null;
+
+ String wholeCommand="";
+ for(String argument : command) {
+ wholeCommand = wholeCommand + " " + argument;
+ }
+
+ ForkDaemon process = new ForkDaemon();
+ try {
+ exitStatus = process.exec(wholeCommand, DEFAULT_HOST, DEFAULT_PORT);
+ } catch (SAXException e) {
+ // This is not a crazy thing, we are trying to insert this new method without
+ // breaking the old methods which did not throw SAXException or ParserConfigurationException
+ throw new IOException(e);
+ } catch (ParserConfigurationException e) {
+ // This is not a crazy thing, we are trying to insert this new method without
+ // breaking the old methods which did not throw SAXException or ParserConfigurationException
+ throw new IOException(e);
+ }
+
+ if(exitStatus == 0) {
+ stdInput = new ByteArrayInputStream(process.getStdout().getBytes("UTF-8"));
+ }
+ else {
+ aLogger.error(process.getStderr());
+ }
+
+
+ return stdInput;
+ }
+
+ /**
+ *