I have a spring boot application. These are the classes:
RunBatchFile.java
public class RunBatchFile {
private Boolean isSuccessful;
private String content;
public void RunningBatchCommand() {
String filePath = "C:/Users/attsuap1/Desktop/test.bat";
try {
Process p = Runtime.getRuntime().exec(filePath);
int exitVal = p.waitFor();
if (exitVal == 0)
{
isSuccessful = true;
}
else {
isSuccessful = false;
}
System.out.println(isSuccessful);
} catch (Exception e) {
e.printStackTrace();
}
}
public RunBatchFile(Boolean isSuccessful) {
this.isSuccessful = isSuccessful;
this.content = content;
}
public RunBatchFile(String format) {
// TODO Auto-generated constructor stub
}
public Boolean getisSuccessful() {
return isSuccessful;
}
public String getContent() {
return content;
}
}
BatchFileController
#RestController
public class BatchFileController {
private static final String template = "Sum, %s!";
private static boolean isSuccessful;
#RequestMapping("/runbatchfile")
#ResponseBody
public RunBatchFile runbatchFile(#RequestParam(value = "isSuccessful") Boolean isSuccessful) {
return new RunBatchFile(String.format(template, isSuccessful));
}
}
The runBatchFile.java class executes a batch file and will show output as either true or false depending on whether the batch file has executed its commands correctly or not. I want to display that output on a web browser therefore i have created the BatchFileController.java class.
I get the error:
Required Boolean parameter 'isSuccessful' is not present
How do i edit my codes to make this work? Which means, either {true} or {false} is shown on the web browser when i run localhost:8080/runbatchfile?
I'm not quite sure what you are doing. The issue you are having with your controller is that you have defined your method to require a boolean parameter. Given your scenario, that would not make sense, as you would not tell the endpoint the result of the script running; the endpoint tells you that. Your method return type should be boolean instead.
Generally this would be the way to go about this if it is a short running script. I tested with a simple ping command and things worked out. Pointing to an invalid IP failed.
If the script takes a lot of time, you're going to want to go async where you submit a job, and you can check back with a different method to see what the status is.
I would have a class to run your batch file:
public class RunBatchFile {
public boolean runBatch() {
String filePath = "C:/Users/attsuap1/Desktop/test.bat";
try {
Process p = Runtime.getRuntime().exec(filePath);
int exitVal = p.waitFor();
return exitVal == 0;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
And then in your controller:
#RequestMapping("/runbatchfile")
public boolean runbatchFile() {
RunBatchFile rbf = new RunBatchFile();
return rbf.runBatch();
}
If you want to wrap your results so your response isn't just a true/false string. Note that the return type of the method has changed to a simple POJO:
Class
public class RunBatchFile {
public ResultWrapper runBatch() {
String filePath = "C:/Users/attsuap1/Desktop/test.bat";
try {
Process p = Runtime.getRuntime().exec(filePath);
int exitVal = p.waitFor();
return new ResultWrapper(exitVal == 0);
} catch (Exception e) {
e.printStackTrace();
return new ResultWrapper(false);
}
}
}
Wrapper Class
public class ResultWrapper {
private boolean result;
public ResultWrapper(boolean result) {
this.result = result;
}
public boolean getResult() {
return result;
}
}
Controller Method
#RequestMapping("/runbatchfile")
public ResultWrapper runbatchFile() {
RunBatchFile rbf = new RunBatchFile();
return rbf.runBatch();
}
Related
I have a class called Parameters, which implements Serializable. But when I use writeObject(p), I got the error message. I checked the status of p. It says it is already Serialized.
package Server.Interface;
import java.util.*;
import java.io.Serializable;
public class Parameters implements Serializable{
private String command;
private String location;
private ArrayList<Integer> numbers;
public Parameters(String command, String location,ArrayList<Integer> numbers) {
this.command = command;
this.location = location;
this.numbers = numbers;
}
public String getCommend() {
return command;
}
public void setCommend(String c) {
this.command = c;
}
public String getLocation() {
return location;
}
public void setNumbers(ArrayList<Integer> numbers) {
this.numbers = numbers;
}
}
The code of client:
public void sendMessage(Parameters p) {
try {
if(p instanceof Serializable){
System.out.println("can be serialized");
}
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(p);
InputStream is=socket.getInputStream();
int attempts = 0;
while(is.available() == 0 && attempts < 1000)
{
System.out.println(attempts);
attempts++;
try {
Thread.sleep(10);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("============================");
BufferedReader br=new BufferedReader(new InputStreamReader(is));
System.out.println("============================");
String info=null;
while((info=br.readLine())!=null&&info.length()>0){
System.out.println(info);
break;
}
}
catch (IOException e) {
System.out.println("IOError");
e.printStackTrace();
}
}
This is the message:
can be serialized
IOError
java.io.NotSerializableException: Client.TCPClient
It clearly says that the object is serialized. But writeObject(p) fails. I also tried set the arraylist of p to be null, and it passed. But ArrayList is serializable in default right? It should not affect the serialization.
Is there any other way of testing for connection to PeopleSoft from java.
this is not working for me
ERROR:
bea.jolt.JoltException: NwHdlr: IO
exceptions\njava.net.ConnectException: Connection timed out: connect
at bea.jolt.NwHdlr.open_socket(NwHdlr.java:2240)
import psft.pt8.joa.API;
import psft.pt8.joa.ISession;
public class Test {
public static void main(String[] args) {
System.out.println(test());
}
public static boolean test()
{
boolean status;
try {
ISession session = API.createSession();
boolean isSuccess = session.connectS(1, "//129.154.79.140:9033", "PS", "PS", new byte[0], "PS");
if(isSuccess)
{
status = true;
}
else
{
status = false;
}
} catch (Exception e) {
e.printStackTrace();
//To create localized exception ExceptionManager.createNlsAdapterSDKException(ExceptionManager.createNlsAdapterSDKException(MessageBundle.getInstance(),Messages.Test_CONN_SUCC_200, arguments);
status = false;
}
return status;
}
}
I am running a springboot server.
This server has some webservices.
One of those services has to run an external jar when it receives a request. Actually the server is the interface between a calculation engine (the jar), and the user.
There is the code :
public class Launcher extends Thread{
#Override
public void run() {
// TODO Auto-generated method stub
runJar(this.getJar(), this.getArgs());
}
private void runJar(String jar, String[] args){
try {
String[] s = new String[4+args.length];
s[0] = "nohup";
s[1] = "java";
s[2] = "-jar";
s[3] = jar;
for(int i = 0; i < args.length; i++){
s[i+4] = args[i];
}
Process p = Runtime.getRuntime().exec(s);
//Process exec = Runtime.getRuntime().exec(new String[] {"mkdir", "monTest"});
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("failed");
e.printStackTrace();
}
}
}
public class Memory {
private ArrayList<Integer> startedIds;
public ArrayList<Integer> getStartedIds() {
return startedIds;
}
public void setStartedIds(ArrayList<Integer> startedIds) {
this.startedIds = startedIds;
}
public Memory() {
this.startedIds = new ArrayList<>();
}
public Memory(ArrayList<Integer> arr) {
this.startedIds = arr;
}
public int start() {
int id = this.findAvailableId();
this.getStartedIds().add(id);
System.out.println("i'm going to start with a big command!+uhpop");
String[] args = {"arg1","arg2", "arg3", "&"};
Launcher launcher = new Launcher("myJar.jar", args);
launcher.start();
return id;
}
private int findAvailableId() {
int id = 0;
while(this.getStartedIds().contains(id)){
id++;
}
return id;
}
}
If my jar do something really simple such as create a file, it works nice. But if it's more complex, the thread just stops working, the cpu fall to 0%. It depends on what i ask. For some task it can run 30-35seconds before the issue happens for others such as doing
while(true);
It stopped a few seconds latter.
I thought it was something like a timeout, but actually it is not a constant time. Maybe something like memory issue...?
I have tried to run the same code outside the springboot server (on a simple java project main that launch Memory.start() and it works well. So I supposed it was a spring boot misunderstanding from my side. If someone know how to make this jar run independently from the springboot server just tell me please.
Thank you.
I finally found the solution. I had to place a
p.waitFor();
so the thread launching the jar will not stop. Then, the input and the output of the jar are not connected to the input/output of the lauching thread, then, i had to create an other thread to monitor the output of the jar (it actually print it in the main thread). I found those informations here : http://labs.excilys.com/2012/06/26/runtime-exec-pour-les-nuls-et-processbuilder/
I still don't really understand why it was working outside the springboot server, actually it should not have run...
If somebody is interested, here is my code.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
class AfficheurFlux implements Runnable {
private final InputStream inputStream;
AfficheurFlux(InputStream inputStream) {
this.inputStream = inputStream;
}
private BufferedReader getBufferedReader(InputStream is) {
return new BufferedReader(new InputStreamReader(is));
}
#Override
public void run() {
BufferedReader br = getBufferedReader(inputStream);
String ligne = "";
try {
while ((ligne = br.readLine()) != null) {
System.out.println(ligne);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Memory {
private ArrayList<Integer> startedIds;
public ArrayList<Integer> getStartedIds() {
return startedIds;
}
public void setStartedIds(ArrayList<Integer> startedIds) {
this.startedIds = startedIds;
}
public Memory() {
this.startedIds = new ArrayList<>();
}
public Memory(ArrayList<Integer> arr) {
this.startedIds = arr;
}
public int startJar() {
int id = this.findAvailableId();
this.getStartedIds().add(id);
System.out.println("i'm going to start with a big command!");
String[] args = {"arg1","arg2", "arg3"};
Launcher launcher = new Launcher("myJar.jar", args);
launcher.start();
return id;
}
private int findAvailableId() {
int id = 0;
while(this.getStartedIds().contains(id)){
id++;
}
return id;
}
public class Launcher extends Thread{
private String jar;
private String[] args;
public AntLauncher(String jar, String[] args) {
super();
this.jar = jar;
this.args = args;
}
#Override
public void run() {
runJar(this.getJar(), this.getArgs());
}
private void runJar(String jar, String[] args){
try {
String[] s = new String[3+args.length];
s[0] = "java";
s[1] = "-jar";
s[2] = jar;
for(int i = 0; i < args.length; i++){
s[i+3] = args[i];
}
Process p = Runtime.getRuntime().exec(s);
AfficheurFlux fluxSortie = new AfficheurFlux(p.getInputStream());
AfficheurFlux fluxErreur = new AfficheurFlux(p.getErrorStream());
new Thread(fluxSortie).start();
new Thread(fluxErreur).start();
p.waitFor();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Fin du programme");
}
}
}
A very good article (When Runtime.exec() won't) says: The only possible time you would use exitValue() instead of waitFor() would be when you don't want your program to block waiting on an external process that may never complete. Instead of using the waitFor() method, I would prefer passing a boolean parameter called waitFor into the exitValue() method to determine whether or not the current thread should wait. A boolean would be more beneficial because exitValue() is a more appropriate name for this method, and it isn't necessary for two methods to perform the same function under different conditions. Such simple condition discrimination is the domain of an input parameter.
I have exactly same situation where my system call would start a process which will keep running until user decides to kill it. If I use '(process.waitFor() == 0)' it will block program there because process will not be completed. Author in article above suggest that exitValue() can be used with 'waitFor' parameter. Did anybody try it out ? Any example would be helpful.
Code:
// Start ProcessBuilder, 'str' contains a command
ProcessBuilder pbuilder = new ProcessBuilder(str);
pbuilder.directory(new File("/root/workspace/Project1"));
pbuilder.redirectErrorStream(true);
Process prcs = pbuilder.start();
AForm.execStatustext.append("\n=> Process is:" + prcs);
// Read output
StringBuilder out = new StringBuilder();
BufferedReader bfrd = new BufferedReader(new InputStreamReader(process.getInputStream()));
String current_line = null, previous_line = null;
while ((current_line = bfrd.readLine()) != null) {
if (!line.equals(previous_line)) {
previous_line = current_line;
out.append(current_line).append('\n');
//System.out.println(line);
}
}
//process.getInputStream().close();
// Send 'Enter' keystroke through BufferedWriter to get control back
BufferedWriter bfrout = new BufferedWriter(new OutputStreamWriter(prcs.getOutputStream()));
bfrout.write("\\r");
bfrout.newLine();
bfrout.flush();
bfrout.write("\\r");
bfrout.newLine();
bfrout.flush();
//process.getOutputStream().close();*/
if (prcs.waitFor() == 0)
System.out.println("Commands executed successfully");
System.exit(0);
This is a "rough" example of some library code I use to launch external processes.
Basically, this uses three threads. The first is used to execute the actually command and then wait till it exists.
The other two deal with the processes output and input streams. This makes these independent of each other prevents the ability for one to block the other.
The whole thing is then tied together with a listener that is notified when something happens.
The error handling could be better (as the fail condition is a little unclear as to what/who actually failed), but the basic concept is there...
This means you can launch the process and not care...(until you want to)
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class TestBackgroundProcess {
public static void main(String[] args) {
new TestBackgroundProcess();
}
public TestBackgroundProcess() {
BackgroundProcess bp = new BackgroundProcess("java", "-jar", "dist/BackgroundProcess.jar");
bp.setListener(new ProcessListener() {
#Override
public void charRead(BackgroundProcess process, char value) {
}
#Override
public void lineRead(BackgroundProcess process, String text) {
System.out.println(text);
}
#Override
public void processFailed(BackgroundProcess process, Exception exp) {
System.out.println("Failed...");
exp.printStackTrace();
}
#Override
public void processCompleted(BackgroundProcess process) {
System.out.println("Completed - " + process.getExitValue());
}
});
System.out.println("Execute command...");
bp.start();
bp.send("dir");
bp.send("exit");
System.out.println("I'm not waiting here...");
}
public interface ProcessListener {
public void charRead(BackgroundProcess process, char value);
public void lineRead(BackgroundProcess process, String text);
public void processFailed(BackgroundProcess process, Exception exp);
public void processCompleted(BackgroundProcess process);
}
public class BackgroundProcess extends Thread {
private List<String> commands;
private File startIn;
private int exitValue;
private ProcessListener listener;
private OutputQueue outputQueue;
public BackgroundProcess(String... cmds) {
commands = new ArrayList<>(Arrays.asList(cmds));
outputQueue = new OutputQueue(this);
}
public void setStartIn(File startIn) {
this.startIn = startIn;
}
public File getStartIn() {
return startIn;
}
public int getExitValue() {
return exitValue;
}
public void setListener(ProcessListener listener) {
this.listener = listener;
}
public ProcessListener getListener() {
return listener;
}
#Override
public void run() {
ProcessBuilder pb = new ProcessBuilder(commands);
File startIn = getStartIn();
if (startIn != null) {
pb.directory(startIn);
}
pb.redirectError();
Process p;
try {
p = pb.start();
InputStreamConsumer isc = new InputStreamConsumer(p.getInputStream(), this, getListener());
outputQueue.init(p.getOutputStream(), getListener());
outputQueue.start();
p.waitFor();
isc.join();
outputQueue.terminate();
outputQueue.join();
ProcessListener listener = getListener();
if (listener != null) {
listener.processCompleted(this);
}
} catch (InterruptedException ex) {
ProcessListener listener = getListener();
if (listener != null) {
listener.processFailed(this, ex);
}
} catch (IOException ex) {
ProcessListener listener = getListener();
if (listener != null) {
listener.processFailed(this, ex);
}
}
}
public void send(String cmd) {
outputQueue.send(cmd);
}
}
public class OutputQueue extends Thread {
private List<String> cmds;
private OutputStream os;
private ProcessListener listener;
private BackgroundProcess backgroundProcess;
private ReentrantLock waitLock;
private Condition waitCon;
private boolean keepRunning = true;
public OutputQueue(BackgroundProcess bp) {
backgroundProcess = bp;
cmds = new ArrayList<>(25);
waitLock = new ReentrantLock();
waitCon = waitLock.newCondition();
}
public ProcessListener getListener() {
return listener;
}
public OutputStream getOutputStream() {
return os;
}
public BackgroundProcess getBackgroundProcess() {
return backgroundProcess;
}
public void init(OutputStream outputStream, ProcessListener listener) {
os = outputStream;
this.listener = listener;
}
public void send(String cmd) {
waitLock.lock();
try {
cmds.add(cmd);
waitCon.signalAll();
} finally {
waitLock.unlock();
}
}
public void terminate() {
waitLock.lock();
try {
cmds.clear();
keepRunning = false;
waitCon.signalAll();
} finally {
waitLock.unlock();
}
}
#Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
}
BackgroundProcess backgroundProcess = getBackgroundProcess();
ProcessListener listener = getListener();
OutputStream outputStream = getOutputStream();
try {
while (keepRunning) {
while (cmds.isEmpty() && keepRunning) {
waitLock.lock();
try {
waitCon.await();
} catch (Exception exp) {
} finally {
waitLock.unlock();
}
}
if (!cmds.isEmpty()) {
waitLock.lock();
try {
while (!cmds.isEmpty()) {
String cmd = cmds.remove(0);
System.out.println("Send " + cmd);
outputStream.write(cmd.getBytes());
outputStream.write('\n');
outputStream.write('\r');
outputStream.flush();
}
} finally {
waitLock.unlock();
}
}
}
} catch (IOException ex) {
if (listener != null) {
listener.processFailed(backgroundProcess, ex);
}
}
}
}
public class InputStreamConsumer extends Thread {
private InputStream is;
private ProcessListener listener;
private BackgroundProcess backgroundProcess;
public InputStreamConsumer(InputStream is, BackgroundProcess backgroundProcess, ProcessListener listener) {
this.is = is;
this.listener = listener;
this.backgroundProcess = backgroundProcess;
start();
}
public ProcessListener getListener() {
return listener;
}
public BackgroundProcess getBackgroundProcess() {
return backgroundProcess;
}
#Override
public void run() {
BackgroundProcess backgroundProcess = getBackgroundProcess();
ProcessListener listener = getListener();
try {
StringBuilder sb = new StringBuilder(64);
int in = -1;
while ((in = is.read()) != -1) {
char value = (char) in;
if (listener != null) {
listener.charRead(backgroundProcess, value);
if (value == '\n' || value == '\r') {
if (sb.length() > 0) {
listener.lineRead(null, sb.toString());
sb.delete(0, sb.length());
}
} else {
sb.append(value);
}
}
}
} catch (IOException ex) {
listener.processFailed(backgroundProcess, ex);
}
}
}
}
Before using waitFor in main thread, create another thread (child) and construct logic for your termination cases in this new thread. For example, wait for 10 secs.
If the condition is fulfilled, then interrupt the main thread from the child thread ant handle the following logic on your main thread.
The following code creates a child thread to invoke the process and the main thread does its work until the child finishes successfully.
import java.io.IOException;
public class TestExecution {
public boolean myProcessState = false;
class MyProcess implements Runnable {
public void run() {
//------
Process process;
try {
process = Runtime.getRuntime().exec("your command");
process.waitFor();
int processExitValue = process.exitValue();
if(processExitValue == 0) {
myProcessState = true;
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void doMyWork() {
MyProcess myProcess = new MyProcess();
Thread myProcessExecuter = new Thread(myProcess);
myProcessExecuter.start();
while(!myProcessState) {
// do your job until the process exits with success
}
}
public static void main(String[] args) {
TestExecution testExecution = new TestExecution();
testExecution.doMyWork();
}
}
If I use '(process.waitFor() == 0)' it will block program there because process will not be completed.
No it won't. It will block the thread. That's why you have threads.
Author in article above suggest that exitValue() can be used with 'waitFor' parameter
No he doesn't. He is talking about how he would have designed it, if anybody had asked him. But they didn't, and he didn't.
Did anybody try it out ?
You can't. It doesn't exist.
I've a batch file that needs to be invoked from a java program. The batch file in-turn invokes an EXE. The EXE program will return data which I want to handle. If the EXE prints data to console am able to capture it as follows. But when the EXE is returning data after its completion, am not able to capture it.
ProcessBuilder pb = new ProcessBuilder("foo.bat");
Process p = pb.start();
int exitValue = p.waitFor();
BufferedReader reader;
// System.out.println("Exit Value" + exitValue);
if (exitValue == 0) {
reader = new BufferedReader(new InputStreamReader(p
.getInputStream()));
} else {
reader = new BufferedReader(new InputStreamReader(p
.getErrorStream()));
}
StringBuffer sb = new StringBuffer();
String temp = reader.readLine();
while (temp != null) {
sb.append(temp);
temp = reader.readLine();
}
reader.close();
System.out.println(sb.toString());
How do i need to capture the data returned by the EXE executed from a batch file?
The EXE is basically a C program. When I invoke the C program, the main method returns me the data, which I want to handle it.
Do you have control over the script? I'd try storing the return value (that's what you want?) from the executable to an environment variable. You may have to export it. Here's a tutorial on how to handle environment variables with Java.
Thanks to jitters comment - no, it doesn't work. We can't change values of the environment variable in a 'global' way (now I know..)
But, the idea works with a little adaptation: I'd still try to store the return value in a global accessible resource: Simply send the return value to a file (exec myapp > result.txt) and read the value from that file in your java application.
I think i had the same problem some time ago. One problem with the previous strategy is that you're waiting for the process to finish (waitFor) to capture the data returned from it. You may have problems if the process fails or hang ups. A better aproach would be something like this:
You should create two threads to consume the input stream and the error stream of the process, independently of the waitFor call. Something like these should work:
1.- Create a class that wraps the execution of the process:
public class ExecutionWrapper {
private int exitStatus;
private String[] command;
private String[] environment;
private String directory;
private boolean running;
private Process process;
private ExecutionWrapperOutput error;
private ExecutionWrapperOutput output;
public ExecutionWrapper(String command, String[] environment, String directory) {
this.command = new String[] { command };
this.environment = environment;
this.directory = directory;
this.exitStatus = -1;
}
public ExecutionWrapper(List<String> command, List<String> environment, String directory) {
if (command != null)
this.command = command.toArray(new String[command.size()]);
if (environment != null)
this.environment = environment.toArray(new String[environment.size()]);
this.directory = directory;
this.exitStatus = -1;
}
public void start() {
try {
this.process = Runtime.getRuntime().exec(this.command, this.environment, new File(this.directory));
this.running = true;
// Error and information messages
this.error = new ExecutionWrapperOutput(this.process.getErrorStream());
this.output = new ExecutionWrapperOutput(this.process.getInputStream());
// Start the messaging threads
this.error.start();
this.output.start();
// Final status
Runnable runner = new Runnable() {
public void run() {
try {
ExecutionWrapper.this.exitStatus = ExecutionWrapper.this.process.waitFor();
ExecutionWrapper.this.running = false;
ExecutionWrapper.this.process.destroy();
} catch (Exception ex) {
LoggingUtiles.exception(ex);
ExecutionWrapper.this.exitStatus = -1;
}
}
};
new Thread(runner).start();
} catch (Throwable t) {
LoggingUtiles.exception(t);
}
}
public void stop() {
this.running = false;
this.process.destroy();
}
public boolean isRunning() {
return running;
}
public int getExitStatus() {
return exitStatus;
}
public String[] getError(boolean clear) {
return this.error.getLines(clear);
}
public String[] getOutput(boolean clear) {
return this.output.getLines(clear);
}
public String[] getCommand() {
return command;
}
public String getDirectory() {
return directory;
}
public void waitFor() {
try {
process.waitFor();
} catch (Throwable t) {
LoggingUtiles.exception(t);
}
}
}
2.- Then, create the ExecutionWrapperOutput class, that processes the output of the process streams:
public class ExecutionWrapperOutput extends Thread {
private InputStream is;
private List<String> output;
private Object mutex = new Object();
ExecutionWrapperOutput(InputStream is) {
this.is = is;
this.output = new ArrayList<String>();
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
synchronized (mutex) {
output.add(line);
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public String[] getLines(boolean clear) {
String[] lines = null;
synchronized (mutex) {
lines = output.toArray(new String[] {});
if (clear)
output.clear();
}
return lines;
}
}
Maybe all this works for you. Let me now if it works...