/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.jstestdriver.browser;
import com.google.jstestdriver.FileUploader;
import com.google.jstestdriver.ProcessFactory;
import com.google.jstestdriver.SlaveBrowser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
/**
* Runs a browser from the command line.
* @author corbinrsmith@gmail.com (Cory Smith)
*/
public class CommandLineBrowserRunner implements BrowserRunner {
private static final Logger logger =
LoggerFactory.getLogger(CommandLineBrowserRunner.class);
private final String browserPath;
private final String browserArgs;
private final ProcessFactory processFactory;
private Process process;
private final String os;
public CommandLineBrowserRunner(String browserPath,
String browserArgs,
ProcessFactory processFactory) {
this(browserPath, browserArgs, processFactory, System.getProperty("os.name"));
}
public CommandLineBrowserRunner(String browserPath,
String browserArgs,
ProcessFactory processFactory,
String os) {
this.browserPath = browserPath;
this.processFactory = processFactory;
this.browserArgs = browserArgs;
this.os = os;
}
@Override
public void startBrowser(String serverAddress) {
try {
String processArgs = "";
if (this.browserArgs.contains("%s")) {
processArgs = this.browserArgs.replace("%s", serverAddress);
} else {
if (this.browserArgs.length() > 0) {
processArgs = this.browserArgs + " ";
}
processArgs += serverAddress;
}
String[] args = processArgs.split(" ");
String[] finalArgs;
if (os.toLowerCase().contains("mac os")) {
finalArgs = new String[args.length + 3];
finalArgs[0] = "open";
finalArgs[1] = "-a";
finalArgs[2] = browserPath;
System.arraycopy(args, 0, finalArgs, 3, args.length);
} else {
finalArgs = new String[args.length + 1];
finalArgs[0] = browserPath;
System.arraycopy(args, 0, finalArgs, 1, args.length);
}
process = processFactory.start(finalArgs);
} catch (IOException e) {
logger.error("Could not start: {} because {}", browserPath, e.toString());
throw new RuntimeException(e);
}
}
@Override
public void stopBrowser() {
try {
process.destroy();
if (process.exitValue() != 0) {
logger.warn("Unexpected shutdown " + process + " " + process.exitValue());
}
} catch (IllegalThreadStateException e) {
logger.warn("Process refused to exit [" + browserPath +" ]: "+ process);
}
}
@Override
public int getTimeout() {
return 30;
}
@Override
public int getNumStartupTries() {
return 1;
}
@Override
public long getHeartbeatTimeout() {
return SlaveBrowser.TIMEOUT;
}
@Override
public int getUploadSize() {
return FileUploader.CHUNK_SIZE;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((browserPath == null) ? 0 : browserPath.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof CommandLineBrowserRunner)) {
return false;
}
CommandLineBrowserRunner other = (CommandLineBrowserRunner) obj;
return (((browserPath == null && other.browserPath == null) ||
browserPath.equals(other.browserPath)) &&
((browserArgs == null && other.browserArgs == null) ||
browserArgs.equals(other.browserArgs)));
}
@Override
public String toString() {
return "CommandLineBrowserRunner [\nbrowserPath=" + browserPath +
"\nargs=" + browserArgs +
",\nprocess=" + process + ",\n process log={\n" + getLog() + "\n}]";
}
private String getLog() {
StringBuilder log = new StringBuilder("error:\n");
if (process == null) {
return "no process log";
}
InputStream errorStream = process.getErrorStream();
InputStream outputStream = process.getInputStream();
byte[] buffer = new byte[512];
try {
while(errorStream.available() > 0) {
errorStream.read(buffer);
log.append(buffer);
}
} catch (IOException e) {
log.append("io exception reading error");
}
log.append("\ninput:\n");
try {
while(outputStream.available() > 0) {
outputStream.read(buffer);
log.append(buffer);
}
} catch (IOException e) {
log.append("io exception reading input");
}
return log.toString();
}
}