cdb5abea841289d6dbcd085549e8592ab28aebc4
[taxeditor.git] / eu.etaxonomy.taxeditor.test / src / test / java / eu / etaxonomy / taxeditor / httpinvoker / CDMServer.java
1 // $Id$
2 /**
3 * Copyright (C) 2014 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10 package eu.etaxonomy.taxeditor.httpinvoker;
11
12 import java.io.BufferedReader;
13 import java.io.IOException;
14 import java.io.InputStreamReader;
15 import java.net.Socket;
16
17 import javax.sql.DataSource;
18
19 import org.apache.log4j.Level;
20 import org.apache.log4j.Logger;
21 import org.springframework.core.io.ClassPathResource;
22 import org.springframework.core.io.Resource;
23 import org.unitils.database.annotations.TestDataSource;
24
25 import eu.etaxonomy.taxeditor.remoting.server.CDMServerException;
26 import eu.etaxonomy.taxeditor.remoting.source.CdmRemoteSourceBase;
27
28 /**
29 *
30 * (Singleton) Server instance which manages a compatible cdmlib-webapp-war.
31 * This is done by launching a jetty instance (using jetty-runner) as an
32 * executed process. The choice of the external process over a more
33 * preferable 'embedded jetty' instance is due to problems arising from the
34 * class loading of classes (e.g. from hibernate core) which are needed
35 * for both the webapp as well as the remoting client.
36 *
37 * @author cmathew
38 * @date 23 Sep 2014
39 *
40 */
41
42 public class CDMServer {
43
44 public static final Logger logger = Logger.getLogger(CDMServer.class);
45
46 @TestDataSource
47 protected DataSource dataSource;
48
49 private final String name = "default";
50 private final String host = "127.0.0.1";
51 private final int port = 9090;
52 private final int stopPort = 9191;
53 private final String stopKey = "jetty-cdm-server";
54 private final String contextPath = "";
55
56 private boolean keepServerRunning = false;
57
58 public static final Resource DEFAULT_CDM_WEBAPP_RESOURCE =
59 new ClassPathResource("/etc/jetty/cdmlib-remote-webapp.war");
60
61 public static final Resource DEFAULT_JETTY_CONFIG_RESOURCE =
62 new ClassPathResource("/etc/jetty/jetty.xml");
63
64 public static final Resource DEFAULT_JETTY_TEMP_RESOURCE =
65 new ClassPathResource("/etc/jetty/temp");
66
67 public static final Resource DEFAULT_JETTY_TEMP_WAR_LIB_RESOURCE =
68 new ClassPathResource("/etc/jetty/temp/webapp/WEB-INF/lib");
69
70 public static final Resource DEFAULT_DATASOURCE_FILE =
71 new ClassPathResource("datasources.xml");
72
73 public static final Resource DEFAULT_JETTY_RUNNER_RESOURCE =
74 new ClassPathResource("/etc/jetty/jetty-runner-9.2.3.v20140905.jar");
75
76 public static final Resource DEFAULT_JETTY_RESOURCE =
77 new ClassPathResource("/etc/jetty/start-9.2.3.v20140905.jar");
78
79
80
81 private static CDMServer cdmServer = null;
82 private static CDMServerException cdmse = null;
83
84 private void CDMServer() {
85 logger.setLevel(Level.INFO);
86 }
87
88 public static CDMServer getInstance() {
89 if(cdmServer == null) {
90 cdmServer = new CDMServer();
91 }
92 return cdmServer;
93 }
94
95 public String getName() {
96 return name;
97 }
98
99 public String getHost() {
100 return host;
101 }
102
103 public int getPort() {
104 return port;
105 }
106
107 public String getContextPath() {
108 return contextPath;
109 }
110
111 public boolean getKeepServerRunning() {
112 return keepServerRunning;
113 }
114
115 public void setKeepServerRunning(boolean keepServerRunning) {
116 this.keepServerRunning = keepServerRunning;
117 }
118
119 public static boolean isRunningInEclipse() {
120 return (System.getProperty("sun.java.command") != null &&
121 System.getProperty("sun.java.command").startsWith("org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"));
122 }
123
124 private String getVMArgs() throws IOException {
125 StringBuilder sb = new StringBuilder();
126 sb.append(" -Dspring.profiles.active=remoting");
127 sb.append(" -Dcdm.beanDefinitionFile=" + DEFAULT_DATASOURCE_FILE.getFile().getAbsolutePath());
128 sb.append(" -Dcdm.datasource=cdmTest");
129 return sb.toString();
130 }
131
132 private String getStartServerArgs() {
133 StringBuilder sb = new StringBuilder();
134 sb.append(" --port ");
135 sb.append(port);
136 return sb.toString();
137 }
138
139 private String getStopServerSettings() {
140 StringBuilder sb = new StringBuilder();
141 sb.append(" --stop-port ");
142 sb.append(stopPort);
143 sb.append(" --stop-key ");
144 sb.append(stopKey);
145 return sb.toString();
146 }
147
148 private String getStopServerArgs() {
149 StringBuilder sb = new StringBuilder();
150 sb.append(" STOP.PORT=");
151 sb.append(stopPort);
152 sb.append(" STOP.KEY=");
153 sb.append(stopKey);
154 return sb.toString();
155 }
156
157 public void start() throws CDMServerException {
158
159 /**
160 * First check if the CDM server responds to a service request, which implies that
161 * the server has started properly. If no response is received then check if the
162 * server is listening on specific host / port, which implies that the server
163 * has started but incorrectly, in which case we try to force stop it (if we can)
164 * and start a new server.
165 */
166 if(isRunning(1)) {
167 logger.info("[CDM-Server] Server already running @ " + host + ":" + port );
168 return;
169 } else if (isAvailable(1)){
170 logger.info("[CDM-Server] Server available, but not started correctly @ " + host + ":" + port );
171 logger.info("[CDM-Server] .... trying to force stop server @ " + host + ":" + port );
172 try {
173 stop(true);
174 } catch (Exception e) {
175 throw new CDMServerException("CDM Server could not be stopped : " + e.getMessage());
176 }
177 }
178
179 Thread t = new Thread() {
180 @Override
181 public void run() {
182 StringBuffer output = new StringBuffer();
183 try{
184 Process p;
185 String command = "java "
186 + getVMArgs()
187 + " -jar "
188 + DEFAULT_JETTY_RUNNER_RESOURCE.getFile().getAbsolutePath()
189 + getStartServerArgs()
190 + getStopServerSettings()
191 + " "
192 + DEFAULT_CDM_WEBAPP_RESOURCE.getFile().getAbsolutePath();
193 logger.info("[CDM-Server] Starting server with Command : " + command);
194 p = Runtime.getRuntime().exec(command);
195
196 BufferedReader reader =
197 new BufferedReader(new InputStreamReader(p.getInputStream()));
198
199 String line = "";
200 while ((line = reader.readLine())!= null) {
201 logger.info("[CDM-Server] Start : " + line);
202 }
203
204 } catch (Exception e) {
205 e.printStackTrace();
206 cdmse = new CDMServerException(e);
207 }
208
209 }
210 };
211
212 t.setDaemon(true);
213 cdmse = null;
214 t.start();
215
216 if(isRunning(60)) {
217 logger.info("[CDM-Server] Started Server @ " + host + ":" + port );
218 } else {
219 logger.info("[CDM-Server] Server not started within given interval");
220 // making sure to kill server if it is not started correctly
221 try {
222 stop(true);
223 } catch (Exception e) {
224 throw new CDMServerException("CDM Server could not be stopped : " + e.getMessage());
225 }
226 throw new CDMServerException("CDM Server not started : ");
227 }
228
229 }
230
231 public boolean isAvailable(int checkingIntervals) throws CDMServerException {
232 int intervalsCount = 0;
233 do {
234 try {
235 Socket s = new Socket(host, port);
236 logger.info("[CDM-Server] Available @ " + host + ":" + port );
237 return true;
238 } catch (IOException ioe) {
239
240 }
241 try {
242 Thread.sleep(1000);
243 } catch (InterruptedException ie) {
244 throw new CDMServerException("Error checking CDM Server status", ie);
245 }
246 intervalsCount++;
247 } while (intervalsCount < checkingIntervals);
248
249 return false;
250 }
251
252 public boolean isStopped(int checkingIntervals) throws CDMServerException {
253 int intervalsCount = 0;
254 do {
255 try {
256 Socket s = new Socket(host, port);
257 } catch (IOException ioe) {
258 return true;
259 }
260 try {
261 Thread.sleep(1000);
262 } catch (InterruptedException ie) {
263 throw new CDMServerException("Error checking CDM Server status", ie);
264 }
265 intervalsCount++;
266 } while (intervalsCount < checkingIntervals);
267
268 return false;
269 }
270
271 public boolean isRunning(int checkingIntervals) throws CDMServerException {
272 CdmRemoteSourceBase crsb = new CdmRemoteSourceBase("local-cdm-server",
273 host,
274 port,
275 contextPath,
276 null);
277 int intervalsCount = 0;
278 do {
279 try {
280 if(cdmse != null) {
281 return false;
282 }
283 boolean check = crsb.checkConnection();
284 if(check) {
285 logger.info("[CDM-Server] Running @ " + host + ":" + port );
286 return true;
287 }
288 } catch (Exception e) {
289
290 }
291 try {
292 Thread.sleep(1000);
293 } catch (InterruptedException ie) {
294 throw new CDMServerException("Error checking CDM Server status", ie);
295 }
296 intervalsCount++;
297 } while (intervalsCount < checkingIntervals);
298 return false;
299 }
300
301 public void stop() throws Exception {
302 stop(false);
303 }
304 public void stop(boolean force) throws Exception {
305
306 if(!force) {
307 if(!getInstance().isAvailable(1)) {
308 logger.info("[CDM-Server] Server already stopped @ " + host + ":" + port );
309 return;
310 }
311
312 if(getInstance().getKeepServerRunning()) {
313 logger.info("[CDM-Server] Server @ " + host + ":" + port + " is set to keep running");
314 return;
315 }
316 }
317 Thread t = new Thread() {
318 @Override
319 public void run() {
320 StringBuffer output = new StringBuffer();
321 try{
322 Process p;
323 String command = "java -jar " + DEFAULT_JETTY_RESOURCE.getFile().getAbsolutePath()
324 + getStopServerArgs() + " --stop ";
325 logger.info("[CDM-Server] Stop Command : " + command);
326 p = Runtime.getRuntime().exec(command);
327 p.waitFor();
328 BufferedReader reader =
329 new BufferedReader(new InputStreamReader(p.getInputStream()));
330 String line = "";
331 while ((line = reader.readLine())!= null) {
332 logger.info("CDM-Server Stop : " + line + "\n");
333 }
334 } catch (Exception e) {
335 e.printStackTrace();
336 }
337
338 }
339 };
340
341 t.setDaemon(true);
342 t.start();
343
344 if(isStopped(5)) {
345 logger.info("[CDM-Server] Stopped Server @ " + host + ":" + port );
346 } else {
347 logger.info("[CDM-Server] Could not stop @ " + host + ":" + port + ". Please kill it manually");
348 }
349 }
350 }