You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
4.7 KiB

package com.highcharts.export.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Timer;
import java.util.concurrent.TimeoutException;
import org.apache.commons.io.IOUtils;
import com.highcharts.export.converter.SVGConverterException;
import com.highcharts.export.util.TempDir;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server {
private Process process;
private final int port;
private final String host;
private final int readTimeout;
private final int connectTimeout;
private final int maxTimeout;
private ServerState state = ServerState.IDLE;
protected static final Logger logger = Logger.getLogger("server");
public Server(String exec, String script, String host, int port, int connectTimeout, int readTimeout, int maxTimeout) {
// assign port and host to this instance
this.port = port;
this.host = host;
this.connectTimeout = connectTimeout;
this.readTimeout = readTimeout;
this.maxTimeout = maxTimeout;
try {
ArrayList<String> commands = new ArrayList<String>();
commands.add(exec);
commands.add(script);
commands.add("-host");
commands.add(host);
commands.add("-port");
commands.add("" + port);
logger.log(Level.FINE, commands.toString());
process = new ProcessBuilder(commands).start();
final BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String readLine = bufferedReader.readLine();
if (readLine == null || !readLine.contains("ready")) {
logger.log(Level.WARNING, "Command starting Phantomjs failed");
process.destroy();
throw new RuntimeException("Error, PhantomJS couldnot start");
}
initialize();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
if (process != null) {
logger.log(Level.WARNING, "Shutting down PhantomJS instance, kill process directly, {0}", this.toString());
try {
process.getErrorStream().close();
process.getInputStream().close();
process.getOutputStream().close();
} catch (IOException e) {
logger.log(Level.WARNING, "Error while shutting down process: {0}", e.getMessage());
}
process.destroy();
}
}
});
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void initialize() {
logger.log(Level.FINE, "Phantom server started on port {0}", port);
}
public String request(String params) throws SocketTimeoutException, SVGConverterException, TimeoutException {
String response = "";
Timer _timer = new Timer();
try {
URL url = new URL("http://" + host + ":"
+ port + "/");
// TEST with running a local phantom instance
// url = new URL("http://" + host + ":7777/");
// logger.log(Level.INFO, "requesting url: " + url.toString());
// logger.log(Level.INFO, "parameters: " + params);
state = ServerState.BUSY;
_timer.schedule(new TimeOut(this), maxTimeout);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
connection.setConnectTimeout(connectTimeout);
connection.setReadTimeout(readTimeout);
OutputStream out = connection.getOutputStream();
out.write(params.getBytes("utf-8"));
out.close();
InputStream in = connection.getInputStream();
response = IOUtils.toString(in, "utf-8");
in.close();
_timer.cancel();
state = ServerState.IDLE;
} catch (SocketTimeoutException ste) {
_timer.cancel();
throw new SocketTimeoutException(ste.getMessage());
} catch (Exception e) {
if(state == ServerState.TIMEDOUT) {
throw new TimeoutException(e.getMessage());
}
_timer.cancel();
throw new SVGConverterException(e.getMessage());
}
return response;
}
public void cleanup() {
try {
/* It's not enough to only destroy the process, this helps*/
process.getErrorStream().close();
process.getInputStream().close();
process.getOutputStream().close();
} catch (IOException e) {
logger.log(Level.SEVERE, "Error while shutting down process: {0}", e.getMessage());
}
process.destroy();
process = null;
logger.log(Level.FINE, "Destroyed phantomJS process running on port {0}", port);
}
public int getPort() {
return port;
}
public String getHost() {
return host;
}
public ServerState getState() {
return state;
}
public void setState(ServerState state) {
this.state = state;
}
@Override
public String toString() {
return this.getClass().getName() + "listening to port: " + port;
}
}