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.

239 lines
5.6 KiB

8 years ago
  1. package com.highcharts.export.pool;
  2. import java.nio.file.*;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import javax.annotation.PostConstruct;
  6. import org.apache.log4j.Logger;
  7. import com.highcharts.export.server.Server;
  8. import com.highcharts.export.server.ServerState;
  9. import com.highcharts.export.util.TempDir;
  10. import java.io.File;
  11. import java.io.FileOutputStream;
  12. import java.io.IOException;
  13. import java.io.InputStream;
  14. import java.io.OutputStream;
  15. import java.net.URL;
  16. import java.net.URLClassLoader;
  17. import java.util.TreeMap;
  18. import org.apache.commons.io.IOUtils;
  19. import org.springframework.core.io.ClassPathResource;
  20. public class ServerObjectFactory implements ObjectFactory<Server> {
  21. public String exec;
  22. public String script;
  23. private String host;
  24. private int basePort;
  25. private int readTimeout;
  26. private int poolSize;
  27. private int connectTimeout;
  28. private int maxTimeout;
  29. private static TreeMap<Integer, PortStatus> portUsage = new TreeMap<>();
  30. protected static Logger logger = Logger.getLogger("pool");
  31. private enum PortStatus {
  32. BUSY,
  33. FREE;
  34. }
  35. @Override
  36. public Server create() {
  37. logger.debug("in makeObject, " + exec + ", " + script + ", " + host);
  38. Integer port = this.getAvailablePort();
  39. String separator = FileSystems.getDefault().getSeparator();
  40. if (script.isEmpty()) {
  41. // use the bundled highcharts-convert.js script
  42. script = TempDir.getPhantomJsDir().toAbsolutePath().toString() + separator + "highcharts-convert.js";
  43. }
  44. Server server = new Server(exec, script, host, port, connectTimeout, readTimeout, maxTimeout);
  45. portUsage.put(port, PortStatus.BUSY);
  46. return server;
  47. }
  48. @Override
  49. public boolean validate(Server server) {
  50. boolean isValid = false;
  51. try {
  52. if(server.getState() != ServerState.IDLE) {
  53. logger.debug("server didn\'t pass validation");
  54. return false;
  55. }
  56. String result = server.request("{\"status\":\"isok\"}");
  57. if(result.indexOf("OK") > -1) {
  58. isValid = true;
  59. logger.debug("server passed validation");
  60. } else {
  61. logger.debug("server didn\'t pass validation");
  62. }
  63. } catch (Exception e) {
  64. logger.error("Error while validating object in Pool: " + e.getMessage());
  65. }
  66. return isValid;
  67. }
  68. @Override
  69. public void destroy(Server server) {
  70. ServerObjectFactory.releasePort(server.getPort());
  71. server.cleanup();
  72. }
  73. @Override
  74. public void activate(Server server) {
  75. server.setState(ServerState.ACTIVE);
  76. }
  77. @Override
  78. public void passivate(Server server) {
  79. server.setState(ServerState.IDLE);
  80. }
  81. public static void releasePort(Integer port) {
  82. logger.debug("Releasing port " + port);
  83. portUsage.put(port, PortStatus.FREE);
  84. }
  85. public Integer getAvailablePort() {
  86. /* first we check within the defined port range from baseport
  87. * up to baseport + poolsize
  88. */
  89. int port = basePort;
  90. for (; port < basePort + poolSize; port++) {
  91. if (portUsage.containsKey(port)) {
  92. if (portUsage.get(port) == PortStatus.FREE) {
  93. return port;
  94. }
  95. } else {
  96. // doesn't exist any longer, but is within the valid port range
  97. return port;
  98. }
  99. }
  100. // at this point there is no free port, we have to look outside of the valid port range
  101. logger.debug("Nothing free in Portusage " + portUsage.toString());
  102. return portUsage.lastKey() + 1;
  103. }
  104. /*Getters and Setters*/
  105. public String getExec() {
  106. return exec;
  107. }
  108. public void setExec(String exec) {
  109. this.exec = exec;
  110. }
  111. public String getScript() {
  112. return script;
  113. }
  114. public void setScript(String script) {
  115. this.script = script;
  116. }
  117. public String getHost() {
  118. return host;
  119. }
  120. public void setHost(String host) {
  121. this.host = host;
  122. }
  123. public int getBasePort() {
  124. return basePort;
  125. }
  126. public void setBasePort(int basePort) {
  127. this.basePort = basePort;
  128. }
  129. public int getReadTimeout() {
  130. return readTimeout;
  131. }
  132. public void setReadTimeout(int readTimeout) {
  133. this.readTimeout = readTimeout;
  134. }
  135. public int getConnectTimeout() {
  136. return connectTimeout;
  137. }
  138. public void setConnectTimeout(int connectTimeout) {
  139. this.connectTimeout = connectTimeout;
  140. }
  141. public int getMaxTimeout() {
  142. return maxTimeout;
  143. }
  144. public void setMaxTimeout(int maxTimeout) {
  145. this.maxTimeout = maxTimeout;
  146. }
  147. public int getPoolSize() {
  148. return poolSize;
  149. }
  150. public void setPoolSize(int poolSize) {
  151. this.poolSize = poolSize;
  152. }
  153. @PostConstruct
  154. public void afterBeanInit() {
  155. URL u = getClass().getProtectionDomain().getCodeSource().getLocation();
  156. URLClassLoader jarLoader = new URLClassLoader(new URL[]{u}, Thread.currentThread().getContextClassLoader());
  157. String filenames[] = new String[] {"highcharts-convert.js",
  158. "jquery.1.9.1.min.js",
  159. "highcharts.js",
  160. "highstock.js",
  161. "highcharts-more.js",
  162. "data.js",
  163. "drilldown.js",
  164. "funnel.js",
  165. "heatmap.js",
  166. "highcharts-3d.js",
  167. "no-data-to-display.js",
  168. "solid-gauge.js",
  169. "map.js",
  170. "broken-axis.js",
  171. "treemap.js"};
  172. for (String filename : filenames) {
  173. ClassPathResource resource = new ClassPathResource("phantomjs/" + filename, jarLoader);
  174. if (resource.exists()) {
  175. Path path = Paths.get(TempDir.getPhantomJsDir().toString(), filename);
  176. File file;
  177. try {
  178. file = Files.createFile(path).toFile();
  179. file.deleteOnExit();
  180. try (InputStream in = resource.getInputStream();
  181. OutputStream out=new FileOutputStream(file))
  182. {
  183. IOUtils.copy(in, out);
  184. }
  185. } catch (IOException ioex) {
  186. logger.error("Error while setting up phantomjs environment: " + ioex.getMessage());
  187. }
  188. } else {
  189. logger.debug("Copy javascript file to temp folder, resource doesn't exist: " + filename);
  190. }
  191. }
  192. }
  193. }