1
1
package com .browserstack .local ;
2
2
3
3
import java .io .BufferedReader ;
4
+ import java .io .InputStreamReader ;
4
5
import java .io .FileReader ;
5
6
import java .io .FileWriter ;
6
7
import java .util .ArrayList ;
7
8
import java .util .HashMap ;
8
9
import java .util .Arrays ;
9
10
import java .util .List ;
10
11
import java .util .Map ;
12
+ import org .json .*;
11
13
12
14
/**
13
15
* Creates and manages a secure tunnel connection to BrowserStack.
14
16
*/
15
17
public class Local {
16
18
17
19
List <String > command ;
20
+ Map <String , String > startOptions ;
21
+ String binaryPath ;
22
+ String logFilePath ;
23
+ int pid = 0 ;
18
24
19
25
private Process proc = null ;
20
26
@@ -44,22 +50,16 @@ public Local() {
44
50
* @throws Exception
45
51
*/
46
52
public void start (Map <String , String > options ) throws Exception {
47
- command = new ArrayList <String >();
48
-
53
+ startOptions = options ;
49
54
if (options .get ("binarypath" ) != null ) {
50
- command . add ( options .get ("binarypath" ) );
55
+ binaryPath = options .get ("binarypath" );
51
56
} else {
52
57
LocalBinary lb = new LocalBinary ();
53
- command . add ( lb .getBinaryPath () );
58
+ binaryPath = lb .getBinaryPath ();
54
59
}
55
60
56
- String logFilePath = options .get ("logfile" ) == null ?
57
- (System .getProperty ("user.dir" ) + "/local.log" ) : options .get ("logfile" );
58
- command .add ("-logFile" );
59
- command .add (logFilePath );
60
-
61
- command .add (options .get ("key" ));
62
- makeCommand (options );
61
+ logFilePath = options .get ("logfile" ) == null ? (System .getProperty ("user.dir" ) + "/local.log" ) : options .get ("logfile" );
62
+ makeCommand (options , "start" );
63
63
64
64
if (options .get ("onlyCommand" ) != null ) return ;
65
65
@@ -71,26 +71,24 @@ public void start(Map<String, String> options) throws Exception {
71
71
fw .close ();
72
72
73
73
proc = processBuilder .start ();
74
- FileReader f = new FileReader (logFilePath );
75
- BufferedReader reader = new BufferedReader (f );
76
- String string ;
77
-
78
- while (true ) {
79
- string = reader .readLine ();
80
- if (string == null ) continue ;
81
-
82
- if (string .equalsIgnoreCase ("Press Ctrl-C to exit" )) {
83
- f .close ();
84
- break ;
85
- }
86
-
87
- if (string .contains ("*** Error" )) {
88
- f .close ();
89
- stop ();
90
- throw new LocalException (string );
91
- }
74
+ BufferedReader stdoutbr = new BufferedReader (new InputStreamReader (proc .getInputStream ()));
75
+ BufferedReader stderrbr = new BufferedReader (new InputStreamReader (proc .getErrorStream ()));
76
+ String stdout ="" , stderr ="" , line ;
77
+ while ((line = stdoutbr .readLine ()) != null ) {
78
+ stdout += line ;
79
+ }
80
+ while ((line = stderrbr .readLine ()) != null ) {
81
+ stderr += line ;
92
82
}
83
+ int r = proc .waitFor ();
93
84
85
+ JSONObject obj = new JSONObject (stdout != "" ? stdout : stderr );
86
+ if (!obj .getString ("state" ).equals ("connected" )){
87
+ throw new LocalException (obj .getString ("message" ));
88
+ }
89
+ else {
90
+ pid = obj .getInt ("pid" );
91
+ }
94
92
}
95
93
}
96
94
@@ -99,12 +97,13 @@ public void start(Map<String, String> options) throws Exception {
99
97
*
100
98
* @throws InterruptedException
101
99
*/
102
- public void stop () throws InterruptedException {
103
- if (proc != null ) {
104
- proc .destroy ();
105
- while (isRunning ()) {
106
- Thread .sleep (1000 );
107
- }
100
+ public void stop () throws Exception {
101
+ if (pid != 0 ) {
102
+ makeCommand (startOptions , "stop" );
103
+ ProcessBuilder processBuilder = new ProcessBuilder (command );
104
+ proc = processBuilder .start ();
105
+ proc .waitFor ();
106
+ pid = 0 ;
108
107
}
109
108
}
110
109
@@ -113,23 +112,25 @@ public void stop() throws InterruptedException {
113
112
*
114
113
* @return true if Local instance is running, else false
115
114
*/
116
- public boolean isRunning () {
117
- if (proc == null ) return false ;
118
-
119
- try {
120
- proc .exitValue ();
121
- return false ;
122
- } catch (IllegalThreadStateException e ) {
123
- return true ;
124
- }
115
+ public boolean isRunning () throws Exception {
116
+ if (pid == 0 ) return false ;
117
+ return isProcessRunning (pid );
125
118
}
126
119
127
120
/**
128
121
* Creates a list of command-line arguments for the Local instance
129
122
*
130
123
* @param options Options supplied for the Local instance
131
124
*/
132
- private void makeCommand (Map <String , String > options ) {
125
+ private void makeCommand (Map <String , String > options , String opCode ) {
126
+ command = new ArrayList <String >();
127
+ command .add (binaryPath );
128
+ command .add ("-d" );
129
+ command .add (opCode );
130
+ command .add ("-logFile" );
131
+ command .add (logFilePath );
132
+ command .add (options .get ("key" ));
133
+
133
134
for (Map .Entry <String , String > opt : options .entrySet ()) {
134
135
List <String > ignoreKeys = Arrays .asList ("key" , "logfile" , "binarypath" );
135
136
String parameter = opt .getKey ().trim ();
@@ -146,4 +147,34 @@ private void makeCommand(Map<String, String> options) {
146
147
}
147
148
}
148
149
}
150
+
151
+ /**
152
+ * Checks if process with pid is running
153
+ *
154
+ * @param options Options supplied for the Local instance
155
+ * @link http://stackoverflow.com/a/26423642/941691
156
+ */
157
+ private boolean isProcessRunning (int pid ) throws Exception {
158
+ ArrayList <String > cmd = new ArrayList <String >();
159
+ if (System .getProperty ("os.name" ).toLowerCase ().contains ("windows" )) {
160
+ //tasklist exit code is always 0. Parse output
161
+ //findstr exit code 0 if found pid, 1 if it doesn't
162
+ cmd .add ("cmd" );
163
+ cmd .add ("/c" );
164
+ cmd .add ("\" tasklist /FI \" PID eq " + pid + "\" | findstr " + pid + "\" " );
165
+ }
166
+ else {
167
+ //ps exit code 0 if process exists, 1 if it doesn't
168
+ cmd .add ("ps" );
169
+ cmd .add ("-p" );
170
+ cmd .add (String .valueOf (pid ));
171
+ }
172
+
173
+ ProcessBuilder processBuilder = new ProcessBuilder (cmd );
174
+ proc = processBuilder .start ();
175
+ int exitValue = proc .waitFor ();
176
+
177
+ // 0 is the default exit code which means the process exists
178
+ return exitValue == 0 ;
179
+ }
149
180
}
0 commit comments