diff --git a/pom.xml b/pom.xml
index eac06c7..2569f17 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
com.browserstack
browserstack-local-java
jar
- 0.1.0
+ 0.2.0
browserstack-local-java
Java bindings for BrowserStack Local
@@ -51,6 +51,11 @@
commons-io
1.3.2
+
+ org.json
+ json
+ 20160212
+
diff --git a/src/main/java/com/browserstack/local/Local.java b/src/main/java/com/browserstack/local/Local.java
index 81e5a99..e59d6c3 100644
--- a/src/main/java/com/browserstack/local/Local.java
+++ b/src/main/java/com/browserstack/local/Local.java
@@ -1,6 +1,7 @@
package com.browserstack.local;
import java.io.BufferedReader;
+import java.io.InputStreamReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
@@ -8,6 +9,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import org.json.*;
/**
* Creates and manages a secure tunnel connection to BrowserStack.
@@ -15,6 +17,10 @@
public class Local {
List command;
+ Map startOptions;
+ String binaryPath;
+ String logFilePath;
+ int pid = 0;
private Process proc = null;
@@ -44,22 +50,16 @@ public Local() {
* @throws Exception
*/
public void start(Map options) throws Exception {
- command = new ArrayList();
-
+ startOptions = options;
if (options.get("binarypath") != null) {
- command.add(options.get("binarypath"));
+ binaryPath = options.get("binarypath");
} else {
LocalBinary lb = new LocalBinary();
- command.add(lb.getBinaryPath());
+ binaryPath = lb.getBinaryPath();
}
- String logFilePath = options.get("logfile") == null ?
- (System.getProperty("user.dir") + "/local.log") : options.get("logfile");
- command.add("-logFile");
- command.add(logFilePath);
-
- command.add(options.get("key"));
- makeCommand(options);
+ logFilePath = options.get("logfile") == null ? (System.getProperty("user.dir") + "/local.log") : options.get("logfile");
+ makeCommand(options, "start");
if (options.get("onlyCommand") != null) return;
@@ -71,26 +71,24 @@ public void start(Map options) throws Exception {
fw.close();
proc = processBuilder.start();
- FileReader f = new FileReader(logFilePath);
- BufferedReader reader = new BufferedReader(f);
- String string;
-
- while (true) {
- string = reader.readLine();
- if (string == null) continue;
-
- if (string.equalsIgnoreCase("Press Ctrl-C to exit")) {
- f.close();
- break;
- }
-
- if (string.contains("*** Error")) {
- f.close();
- stop();
- throw new LocalException(string);
- }
+ BufferedReader stdoutbr = new BufferedReader(new InputStreamReader(proc.getInputStream()));
+ BufferedReader stderrbr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
+ String stdout="", stderr="", line;
+ while ((line = stdoutbr.readLine()) != null) {
+ stdout += line;
+ }
+ while ((line = stderrbr.readLine()) != null) {
+ stderr += line;
}
+ int r = proc.waitFor();
+ JSONObject obj = new JSONObject(stdout != "" ? stdout : stderr);
+ if(!obj.getString("state").equals("connected")){
+ throw new LocalException(obj.getString("message"));
+ }
+ else {
+ pid = obj.getInt("pid");
+ }
}
}
@@ -99,12 +97,13 @@ public void start(Map options) throws Exception {
*
* @throws InterruptedException
*/
- public void stop() throws InterruptedException {
- if (proc != null) {
- proc.destroy();
- while (isRunning()) {
- Thread.sleep(1000);
- }
+ public void stop() throws Exception {
+ if (pid != 0) {
+ makeCommand(startOptions, "stop");
+ ProcessBuilder processBuilder = new ProcessBuilder(command);
+ proc = processBuilder.start();
+ proc.waitFor();
+ pid = 0;
}
}
@@ -113,15 +112,9 @@ public void stop() throws InterruptedException {
*
* @return true if Local instance is running, else false
*/
- public boolean isRunning() {
- if (proc == null) return false;
-
- try {
- proc.exitValue();
- return false;
- } catch (IllegalThreadStateException e) {
- return true;
- }
+ public boolean isRunning() throws Exception {
+ if (pid == 0) return false;
+ return isProcessRunning(pid);
}
/**
@@ -129,7 +122,15 @@ public boolean isRunning() {
*
* @param options Options supplied for the Local instance
*/
- private void makeCommand(Map options) {
+ private void makeCommand(Map options, String opCode) {
+ command = new ArrayList();
+ command.add(binaryPath);
+ command.add("-d");
+ command.add(opCode);
+ command.add("-logFile");
+ command.add(logFilePath);
+ command.add(options.get("key"));
+
for (Map.Entry opt : options.entrySet()) {
List ignoreKeys = Arrays.asList("key", "logfile", "binarypath");
String parameter = opt.getKey().trim();
@@ -146,4 +147,34 @@ private void makeCommand(Map options) {
}
}
}
+
+ /**
+ * Checks if process with pid is running
+ *
+ * @param options Options supplied for the Local instance
+ * @link http://stackoverflow.com/a/26423642/941691
+ */
+ private boolean isProcessRunning(int pid) throws Exception {
+ ArrayList cmd = new ArrayList();
+ if (System.getProperty("os.name").toLowerCase().contains("windows")) {
+ //tasklist exit code is always 0. Parse output
+ //findstr exit code 0 if found pid, 1 if it doesn't
+ cmd.add("cmd");
+ cmd.add("/c");
+ cmd.add("\"tasklist /FI \"PID eq " + pid + "\" | findstr " + pid + "\"");
+ }
+ else {
+ //ps exit code 0 if process exists, 1 if it doesn't
+ cmd.add("ps");
+ cmd.add("-p");
+ cmd.add(String.valueOf(pid));
+ }
+
+ ProcessBuilder processBuilder = new ProcessBuilder(cmd);
+ proc = processBuilder.start();
+ int exitValue = proc.waitFor();
+
+ // 0 is the default exit code which means the process exists
+ return exitValue == 0;
+ }
}