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

8 years ago
  1. package com.highcharts.export.server;
  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.InputStreamReader;
  6. import java.io.OutputStream;
  7. import java.net.SocketTimeoutException;
  8. import java.net.URL;
  9. import java.net.URLConnection;
  10. import java.util.ArrayList;
  11. import java.util.Timer;
  12. import java.util.concurrent.TimeoutException;
  13. import org.apache.commons.io.IOUtils;
  14. import com.highcharts.export.converter.SVGConverterException;
  15. import com.highcharts.export.util.TempDir;
  16. import java.util.logging.Level;
  17. import java.util.logging.Logger;
  18. public class Server {
  19. private Process process;
  20. private final int port;
  21. private final String host;
  22. private final int readTimeout;
  23. private final int connectTimeout;
  24. private final int maxTimeout;
  25. private ServerState state = ServerState.IDLE;
  26. protected static final Logger logger = Logger.getLogger("server");
  27. public Server(String exec, String script, String host, int port, int connectTimeout, int readTimeout, int maxTimeout) {
  28. // assign port and host to this instance
  29. this.port = port;
  30. this.host = host;
  31. this.connectTimeout = connectTimeout;
  32. this.readTimeout = readTimeout;
  33. this.maxTimeout = maxTimeout;
  34. try {
  35. ArrayList<String> commands = new ArrayList<String>();
  36. commands.add(exec);
  37. commands.add(script);
  38. commands.add("-host");
  39. commands.add(host);
  40. commands.add("-port");
  41. commands.add("" + port);
  42. logger.log(Level.FINE, commands.toString());
  43. process = new ProcessBuilder(commands).start();
  44. final BufferedReader bufferedReader = new BufferedReader(
  45. new InputStreamReader(process.getInputStream()));
  46. String readLine = bufferedReader.readLine();
  47. if (readLine == null || !readLine.contains("ready")) {
  48. logger.log(Level.WARNING, "Command starting Phantomjs failed");
  49. process.destroy();
  50. throw new RuntimeException("Error, PhantomJS couldnot start");
  51. }
  52. initialize();
  53. Runtime.getRuntime().addShutdownHook(new Thread() {
  54. @Override
  55. public void run() {
  56. if (process != null) {
  57. logger.log(Level.WARNING, "Shutting down PhantomJS instance, kill process directly, {0}", this.toString());
  58. try {
  59. process.getErrorStream().close();
  60. process.getInputStream().close();
  61. process.getOutputStream().close();
  62. } catch (IOException e) {
  63. logger.log(Level.WARNING, "Error while shutting down process: {0}", e.getMessage());
  64. }
  65. process.destroy();
  66. }
  67. }
  68. });
  69. } catch (IOException e) {
  70. throw new RuntimeException(e);
  71. }
  72. }
  73. public void initialize() {
  74. logger.log(Level.FINE, "Phantom server started on port {0}", port);
  75. }
  76. public String request(String params) throws SocketTimeoutException, SVGConverterException, TimeoutException {
  77. String response = "";
  78. Timer _timer = new Timer();
  79. try {
  80. URL url = new URL("http://" + host + ":"
  81. + port + "/");
  82. // TEST with running a local phantom instance
  83. // url = new URL("http://" + host + ":7777/");
  84. // logger.log(Level.INFO, "requesting url: " + url.toString());
  85. // logger.log(Level.INFO, "parameters: " + params);
  86. state = ServerState.BUSY;
  87. _timer.schedule(new TimeOut(this), maxTimeout);
  88. URLConnection connection = url.openConnection();
  89. connection.setDoOutput(true);
  90. connection.setConnectTimeout(connectTimeout);
  91. connection.setReadTimeout(readTimeout);
  92. OutputStream out = connection.getOutputStream();
  93. out.write(params.getBytes("utf-8"));
  94. out.close();
  95. InputStream in = connection.getInputStream();
  96. response = IOUtils.toString(in, "utf-8");
  97. in.close();
  98. _timer.cancel();
  99. state = ServerState.IDLE;
  100. } catch (SocketTimeoutException ste) {
  101. _timer.cancel();
  102. throw new SocketTimeoutException(ste.getMessage());
  103. } catch (Exception e) {
  104. if(state == ServerState.TIMEDOUT) {
  105. throw new TimeoutException(e.getMessage());
  106. }
  107. _timer.cancel();
  108. throw new SVGConverterException(e.getMessage());
  109. }
  110. return response;
  111. }
  112. public void cleanup() {
  113. try {
  114. /* It's not enough to only destroy the process, this helps*/
  115. process.getErrorStream().close();
  116. process.getInputStream().close();
  117. process.getOutputStream().close();
  118. } catch (IOException e) {
  119. logger.log(Level.SEVERE, "Error while shutting down process: {0}", e.getMessage());
  120. }
  121. process.destroy();
  122. process = null;
  123. logger.log(Level.FINE, "Destroyed phantomJS process running on port {0}", port);
  124. }
  125. public int getPort() {
  126. return port;
  127. }
  128. public String getHost() {
  129. return host;
  130. }
  131. public ServerState getState() {
  132. return state;
  133. }
  134. public void setState(ServerState state) {
  135. this.state = state;
  136. }
  137. @Override
  138. public String toString() {
  139. return this.getClass().getName() + "listening to port: " + port;
  140. }
  141. }