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
;
14 import java
.io
.FileInputStream
;
15 import java
.io
.FileNotFoundException
;
16 import java
.io
.IOException
;
17 import java
.io
.InputStream
;
18 import java
.io
.InputStreamReader
;
19 import java
.net
.URISyntaxException
;
21 import java
.util
.Properties
;
23 import javax
.management
.InstanceNotFoundException
;
24 import javax
.management
.MBeanException
;
25 import javax
.management
.MBeanServerConnection
;
26 import javax
.management
.MalformedObjectNameException
;
27 import javax
.management
.ObjectName
;
28 import javax
.management
.ReflectionException
;
29 import javax
.management
.remote
.JMXConnector
;
30 import javax
.management
.remote
.JMXConnectorFactory
;
31 import javax
.management
.remote
.JMXServiceURL
;
32 import javax
.sql
.DataSource
;
34 import org
.apache
.log4j
.Logger
;
35 import org
.eclipse
.core
.runtime
.FileLocator
;
36 import org
.springframework
.core
.io
.ClassPathResource
;
37 import org
.springframework
.core
.io
.Resource
;
38 import org
.unitils
.database
.annotations
.TestDataSource
;
40 import eu
.etaxonomy
.cdm
.database
.CdmPersistentDataSource
;
41 import eu
.etaxonomy
.cdm
.database
.ICdmDataSource
;
42 import eu
.etaxonomy
.taxeditor
.remoting
.server
.CDMServerException
;
43 import eu
.etaxonomy
.taxeditor
.remoting
.source
.CdmRemoteSourceBase
;
47 * (Singleton) Server instance which manages a compatible cdmlib-webapp-war.
48 * This is done by launching a jetty instance (using jetty-runner) as an
49 * executed process. The choice of the external process over a more
50 * preferable 'embedded jetty' instance is due to problems arising from the
51 * class loading of classes (e.g. from hibernate core) which are needed
52 * for both the webapp as well as the remoting client.
59 public class CDMServer
{
61 public static final Logger logger
= Logger
.getLogger(CDMServer
.class);
64 protected DataSource dataSource
;
66 private final String name
= "default";
67 private final String host
= "127.0.0.1";
68 private int httpPort
= 9090;
69 private int stopPort
= 9191;
70 private String stopKey
= "jetty-cdm-server";
71 private final String contextPath
= "";
73 public static final Resource DEFAULT_CDM_WEBAPP_RESOURCE
=
74 new ClassPathResource("/etc/jetty/cdmlib-remote-webapp.war");
76 public static final Resource DEFAULT_DATASOURCE_FILE
=
77 new ClassPathResource("datasources.xml");
79 public static final Resource DEFAULT_JETTY_RUNNER_RESOURCE
=
80 new ClassPathResource("/etc/jetty/jetty-runner-9.2.3.v20140905.jar");
82 public static final Resource DEFAULT_JETTY_RESOURCE
=
83 new ClassPathResource("/etc/jetty/start-9.2.3.v20140905.jar");
85 private static CDMServer cdmServer
= null;
86 private static CDMServerException cdmse
= null;
88 private boolean serverAlreadyRunning
= false;
90 private File dataSourcesFile
;
91 private final String dataSourceName
;
93 public CDMServer(String dataSourceName
, URL serverPropertiesURL
) throws CDMServerException
{
94 this.dataSourceName
= dataSourceName
;
95 Properties prop
= new Properties();
98 File serverPropertiesFile
= new File(FileLocator
.resolve(serverPropertiesURL
).toURI());
99 InputStream inputStream
= new FileInputStream(serverPropertiesFile
);
101 prop
.load(inputStream
);
104 } catch (FileNotFoundException e
) {
105 throw new CDMServerException(e
);
106 } catch (URISyntaxException e
) {
107 throw new CDMServerException(e
);
108 } catch (IOException e
) {
109 throw new CDMServerException(e
);
114 if(prop
.getProperty("httpPort") != null) {
115 setHttpPort(Integer
.valueOf(prop
.getProperty("httpPort")));
118 if(prop
.getProperty("stopPort") != null) {
119 setStopPort(Integer
.valueOf(prop
.getProperty("stopPort")));
122 if(prop
.getProperty("stopKey") != null) {
123 setStopKey(prop
.getProperty("stopKey"));
130 public String
getName() {
134 public String
getHost() {
138 public int getPort() {
142 public String
getContextPath() {
146 public void setHttpPort(int port
) {
147 this.httpPort
= port
;
150 public void setStopPort(int stopPort
) {
151 this.stopPort
= stopPort
;
154 public void setStopKey(String stopKey
) {
155 this.stopKey
= stopKey
;
159 public static boolean isRunningInEclipse() {
160 return (System
.getProperty("sun.java.command") != null &&
161 System
.getProperty("sun.java.command").startsWith("org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"));
164 private String
getVMArgs() throws IOException
{
165 StringBuilder sb
= new StringBuilder();
166 sb
.append(" -Dspring.profiles.active=remoting");
167 sb
.append(" -Dcdm.beanDefinitionFile=" + DEFAULT_DATASOURCE_FILE
.getFile().getAbsolutePath());
168 sb
.append(" -Dcdm.datasource=cdmTest");
169 return sb
.toString();
172 private String
getStartServerArgs() throws IOException
{
173 StringBuilder sb
= new StringBuilder();
174 sb
.append(" --port " + httpPort
);
175 return sb
.toString();
178 private String
getStopServerSettings() {
179 StringBuilder sb
= new StringBuilder();
180 sb
.append(" --stop-port ");
182 sb
.append(" --stop-key ");
184 return sb
.toString();
187 private String
getStopServerArgs() {
188 StringBuilder sb
= new StringBuilder();
189 sb
.append(" STOP.PORT=");
191 sb
.append(" STOP.KEY=");
193 return sb
.toString();
197 public void start() throws CDMServerException
{
200 * First check if the CDM server responds to a service request, which implies that
201 * the server has started properly. If no response is received then check if the
202 * server is listening on specific host / port, which implies that the server
203 * has started but incorrectly, in which case we try to force stop it (if we can)
204 * and start a new server.
207 logger
.info("[CDM-Server] Server already running @ " + host
+ ":" + httpPort
);
208 serverAlreadyRunning
= true;
212 Thread t
= new Thread() {
216 StringBuffer output
= new StringBuffer();
219 String command
= "java "
222 + DEFAULT_JETTY_RUNNER_RESOURCE
.getFile().getAbsolutePath()
223 + getStartServerArgs()
224 + getStopServerSettings()
226 + DEFAULT_CDM_WEBAPP_RESOURCE
.getFile().getAbsolutePath();
227 logger
.info("[CDM-Server] Starting server with Command : " + command
);
228 p
= Runtime
.getRuntime().exec(command
);
230 BufferedReader inpReader
=
231 new BufferedReader(new InputStreamReader(p
.getInputStream()));
233 BufferedReader errReader
=
234 new BufferedReader(new InputStreamReader(p
.getErrorStream()));
237 while ((line
= inpReader
.readLine())!= null) {
238 logger
.info("[CDM-Server Start] : " + line
);
241 while ((line
= errReader
.readLine())!= null) {
242 logger
.info("[CDM-Server Start] : " + line
);
245 } catch (Exception e
) {
247 cdmse
= new CDMServerException(e
);
257 logger
.info("[CDM-Server] Server running @ " + host
+ ":" + httpPort
);
259 logger
.info("[CDM-Server] Server not started within given interval");
260 // making sure to kill server if it is not started correctly
263 } catch (Exception e
) {
264 throw new CDMServerException("CDM Server could not be stopped : " + e
.getMessage());
266 throw new CDMServerException("CDM Server not started : ");
272 public boolean isStarted(int checkingIntervals
) throws CDMServerException
{
273 CdmRemoteSourceBase crsb
= new CdmRemoteSourceBase("local-cdm-server",
278 int intervalsCount
= 0;
284 boolean check
= crsb
.checkConnection();
286 logger
.info("[CDM-Server] Running @ " + host
+ ":" + httpPort
);
289 } catch (Exception e
) {
294 } catch (InterruptedException ie
) {
295 throw new CDMServerException("Error checking CDM Server status", ie
);
298 } while (intervalsCount
< checkingIntervals
);
302 public void stop() throws Exception
{
306 public void stop(boolean force
) throws Exception
{
309 if(!cdmServer
.isStarted(1)) {
310 logger
.info("[CDM-Server] Server already stopped @ " + host
+ ":" + httpPort
);
315 if(serverAlreadyRunning
) {
318 Thread t
= new Thread() {
321 StringBuffer output
= new StringBuffer();
324 String command
= "java -jar " + DEFAULT_JETTY_RESOURCE
.getFile().getAbsolutePath()
325 + getStopServerArgs() + " --stop ";
326 logger
.info("[CDM-Server] Stop Command : " + command
);
327 p
= Runtime
.getRuntime().exec(command
);
329 BufferedReader inpReader
=
330 new BufferedReader(new InputStreamReader(p
.getInputStream()));
332 BufferedReader errReader
=
333 new BufferedReader(new InputStreamReader(p
.getErrorStream()));
336 while ((line
= inpReader
.readLine())!= null) {
337 logger
.info("[CDM-Server Stop] : " + line
);
340 while ((line
= errReader
.readLine())!= null) {
341 logger
.info("[CDM-Server Stop] : " + line
);
343 logger
.info("CDM-Server Stopped : ");
344 } catch (Exception e
) {
345 logger
.info("[CDM-Server] Could not stop @ " + host
+ ":" + httpPort
+ ". Please kill it manually");
357 public static void stopServerViaJMX(int jmxPort
) throws CDMServerException
{
358 String JMX_URL
= "service:jmx:rmi:///jndi/rmi://localhost:" + jmxPort
+ "/jmxrmi";
359 logger
.warn("Shutting down Jetty instance ... ");
362 JMXConnector connector
= JMXConnectorFactory
.connect(new JMXServiceURL(JMX_URL
), null);
363 connector
.connect(null);
364 MBeanServerConnection connection
= connector
.getMBeanServerConnection();
365 ObjectName objectName
= new ObjectName("org.eclipse.jetty.server:type=server,id=0");
366 connection
.invoke(objectName
, "stop", null, null);
367 logger
.warn("Shutdown command sent");
368 } catch (InstanceNotFoundException e
) {
369 throw new CDMServerException(e
);
370 } catch (MBeanException e
) {
371 throw new CDMServerException(e
);
372 } catch (ReflectionException e
) {
373 throw new CDMServerException(e
);
374 } catch (IOException e
) {
375 throw new CDMServerException(e
);
376 } catch (MalformedObjectNameException e
) {
377 throw new CDMServerException(e
);
381 public void convertEditorToServerConfig() {
382 String xmlString
= "<?xml version=\"1.0\" encoding=\"UTF-8\"?> " + System
.lineSeparator() +
383 "<beans xmlns=\"http://www.springframework.org/schema/beans\"" + System
.lineSeparator() +
384 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + System
.lineSeparator() +
385 "xmlns:tx=\"http://www.springframework.org/schema/tx\"" + System
.lineSeparator() +
386 "xmlns:context=\"http://www.springframework.org/schema/context\"" + System
.lineSeparator() +
387 "xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" + System
.lineSeparator() +
388 "http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd" + System
.lineSeparator() +
389 "http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd" + System
.lineSeparator() +
390 ">" + System
.lineSeparator() +
391 "<bean id=\"dataSourceProperties\" class=\"eu.etaxonomy.cdm.remote.config.DataSourceProperties\">" + System
.lineSeparator() +
392 " <property name=\"propsMap\">" + System
.lineSeparator() +
393 " <map/>" + System
.lineSeparator() +
394 " </property>" + System
.lineSeparator() +
397 for(ICdmDataSource dataSource
: CdmPersistentDataSource
.getAllDataSources()) {