3 * Copyright (C) 2014 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.taxeditor
.httpinvoker
;
12 import java
.io
.BufferedReader
;
13 import java
.io
.IOException
;
14 import java
.io
.InputStreamReader
;
16 import javax
.management
.InstanceNotFoundException
;
17 import javax
.management
.MBeanException
;
18 import javax
.management
.MBeanServerConnection
;
19 import javax
.management
.MalformedObjectNameException
;
20 import javax
.management
.ObjectName
;
21 import javax
.management
.ReflectionException
;
22 import javax
.management
.remote
.JMXConnector
;
23 import javax
.management
.remote
.JMXConnectorFactory
;
24 import javax
.management
.remote
.JMXServiceURL
;
25 import javax
.sql
.DataSource
;
27 import org
.apache
.log4j
.Logger
;
28 import org
.springframework
.core
.io
.ClassPathResource
;
29 import org
.springframework
.core
.io
.Resource
;
30 import org
.unitils
.database
.annotations
.TestDataSource
;
32 import eu
.etaxonomy
.taxeditor
.remoting
.server
.CDMServerException
;
33 import eu
.etaxonomy
.taxeditor
.remoting
.source
.CdmRemoteSourceBase
;
37 * (Singleton) Server instance which manages a compatible cdmlib-webapp-war.
38 * This is done by launching a jetty instance (using jetty-runner) as an
39 * executed process. The choice of the external process over a more
40 * preferable 'embedded jetty' instance is due to problems arising from the
41 * class loading of classes (e.g. from hibernate core) which are needed
42 * for both the webapp as well as the remoting client.
49 public class CDMServer
{
51 public static final Logger logger
= Logger
.getLogger(CDMServer
.class);
54 protected DataSource dataSource
;
56 private final String name
= "default";
57 private final String host
= "127.0.0.1";
58 private int httpPort
= 9090;
59 private int stopPort
= 9191;
60 private String stopKey
= "jetty-cdm-server";
61 private final String contextPath
= "";
63 public static final Resource DEFAULT_CDM_WEBAPP_RESOURCE
=
64 new ClassPathResource("/etc/jetty/cdmlib-remote-webapp.war");
66 public static final Resource DEFAULT_DATASOURCE_FILE
=
67 new ClassPathResource("datasources.xml");
69 public static final Resource DEFAULT_JETTY_RUNNER_RESOURCE
=
70 new ClassPathResource("/etc/jetty/jetty-runner-9.2.3.v20140905.jar");
72 public static final Resource DEFAULT_JETTY_RESOURCE
=
73 new ClassPathResource("/etc/jetty/start-9.2.3.v20140905.jar");
75 private static CDMServer cdmServer
= null;
76 private static CDMServerException cdmse
= null;
78 private boolean serverAlreadyRunning
= false;
80 private void CDMServer() {}
82 public static CDMServer
getInstance() {
83 if(cdmServer
== null) {
84 cdmServer
= new CDMServer();
89 public String
getName() {
93 public String
getHost() {
97 public int getPort() {
101 public String
getContextPath() {
105 public void setHttpPort(int port
) {
106 this.httpPort
= port
;
109 public void setStopPort(int stopPort
) {
110 this.stopPort
= stopPort
;
113 public void setStopKey(String stopKey
) {
114 this.stopKey
= stopKey
;
118 public static boolean isRunningInEclipse() {
119 return (System
.getProperty("sun.java.command") != null &&
120 System
.getProperty("sun.java.command").startsWith("org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"));
123 private String
getVMArgs() throws IOException
{
124 StringBuilder sb
= new StringBuilder();
125 sb
.append(" -Dspring.profiles.active=remoting");
126 sb
.append(" -Dcdm.beanDefinitionFile=" + DEFAULT_DATASOURCE_FILE
.getFile().getAbsolutePath());
127 sb
.append(" -Dcdm.datasource=cdmTest");
128 return sb
.toString();
131 private String
getStartServerArgs() throws IOException
{
132 StringBuilder sb
= new StringBuilder();
133 sb
.append(" --port " + httpPort
);
134 return sb
.toString();
137 private String
getStopServerSettings() {
138 StringBuilder sb
= new StringBuilder();
139 sb
.append(" --stop-port ");
141 sb
.append(" --stop-key ");
143 return sb
.toString();
146 private String
getStopServerArgs() {
147 StringBuilder sb
= new StringBuilder();
148 sb
.append(" STOP.PORT=");
150 sb
.append(" STOP.KEY=");
152 return sb
.toString();
156 public void start() throws CDMServerException
{
159 * First check if the CDM server responds to a service request, which implies that
160 * the server has started properly. If no response is received then check if the
161 * server is listening on specific host / port, which implies that the server
162 * has started but incorrectly, in which case we try to force stop it (if we can)
163 * and start a new server.
166 logger
.info("[CDM-Server] Server already running @ " + host
+ ":" + httpPort
);
167 serverAlreadyRunning
= true;
171 Thread t
= new Thread() {
175 StringBuffer output
= new StringBuffer();
178 String command
= "java "
181 + DEFAULT_JETTY_RUNNER_RESOURCE
.getFile().getAbsolutePath()
182 + getStartServerArgs()
183 + getStopServerSettings()
185 + DEFAULT_CDM_WEBAPP_RESOURCE
.getFile().getAbsolutePath();
186 logger
.info("[CDM-Server] Starting server with Command : " + command
);
187 p
= Runtime
.getRuntime().exec(command
);
189 BufferedReader inpReader
=
190 new BufferedReader(new InputStreamReader(p
.getInputStream()));
192 BufferedReader errReader
=
193 new BufferedReader(new InputStreamReader(p
.getErrorStream()));
196 while ((line
= inpReader
.readLine())!= null) {
197 logger
.info("[CDM-Server Start] : " + line
);
200 while ((line
= errReader
.readLine())!= null) {
201 logger
.info("[CDM-Server Start] : " + line
);
204 } catch (Exception e
) {
206 cdmse
= new CDMServerException(e
);
216 logger
.info("[CDM-Server] Server running @ " + host
+ ":" + httpPort
);
218 logger
.info("[CDM-Server] Server not started within given interval");
219 // making sure to kill server if it is not started correctly
222 } catch (Exception e
) {
223 throw new CDMServerException("CDM Server could not be stopped : " + e
.getMessage());
225 throw new CDMServerException("CDM Server not started : ");
231 public boolean isStarted(int checkingIntervals
) throws CDMServerException
{
232 CdmRemoteSourceBase crsb
= new CdmRemoteSourceBase("local-cdm-server",
237 int intervalsCount
= 0;
243 boolean check
= crsb
.checkConnection();
245 logger
.info("[CDM-Server] Running @ " + host
+ ":" + httpPort
);
248 } catch (Exception e
) {
253 } catch (InterruptedException ie
) {
254 throw new CDMServerException("Error checking CDM Server status", ie
);
257 } while (intervalsCount
< checkingIntervals
);
261 public void stop() throws Exception
{
265 public void stop(boolean force
) throws Exception
{
268 if(!getInstance().isStarted(1)) {
269 logger
.info("[CDM-Server] Server already stopped @ " + host
+ ":" + httpPort
);
274 if(serverAlreadyRunning
) {
277 Thread t
= new Thread() {
280 StringBuffer output
= new StringBuffer();
283 String command
= "java -jar " + DEFAULT_JETTY_RESOURCE
.getFile().getAbsolutePath()
284 + getStopServerArgs() + " --stop ";
285 logger
.info("[CDM-Server] Stop Command : " + command
);
286 p
= Runtime
.getRuntime().exec(command
);
288 BufferedReader inpReader
=
289 new BufferedReader(new InputStreamReader(p
.getInputStream()));
291 BufferedReader errReader
=
292 new BufferedReader(new InputStreamReader(p
.getErrorStream()));
295 while ((line
= inpReader
.readLine())!= null) {
296 logger
.info("[CDM-Server Stop] : " + line
);
299 while ((line
= errReader
.readLine())!= null) {
300 logger
.info("[CDM-Server Stop] : " + line
);
302 logger
.info("CDM-Server Stopped : ");
303 } catch (Exception e
) {
304 logger
.info("[CDM-Server] Could not stop @ " + host
+ ":" + httpPort
+ ". Please kill it manually");
316 public static void stopServerViaJMX(int jmxPort
) throws CDMServerException
{
317 String JMX_URL
= "service:jmx:rmi:///jndi/rmi://localhost:" + jmxPort
+ "/jmxrmi";
318 logger
.warn("Shutting down Jetty instance ... ");
321 JMXConnector connector
= JMXConnectorFactory
.connect(new JMXServiceURL(JMX_URL
), null);
322 connector
.connect(null);
323 MBeanServerConnection connection
= connector
.getMBeanServerConnection();
324 ObjectName objectName
= new ObjectName("org.eclipse.jetty.server:type=server,id=0");
325 connection
.invoke(objectName
, "stop", null, null);
326 logger
.warn("Shutdown command sent");
327 } catch (InstanceNotFoundException e
) {
328 throw new CDMServerException(e
);
329 } catch (MBeanException e
) {
330 throw new CDMServerException(e
);
331 } catch (ReflectionException e
) {
332 throw new CDMServerException(e
);
333 } catch (IOException e
) {
334 throw new CDMServerException(e
);
335 } catch (MalformedObjectNameException e
) {
336 throw new CDMServerException(e
);