Project

General

Profile

Download (11.2 KB) Statistics
| Branch: | Tag: | Revision:
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

    
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;
26

    
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;
31

    
32
import eu.etaxonomy.taxeditor.remoting.server.CDMServerException;
33
import eu.etaxonomy.taxeditor.remoting.source.CdmRemoteSourceBase;
34

    
35
/**
36
 *
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.
43
 *
44
 * @author cmathew
45
 * @date 23 Sep 2014
46
 *
47
 */
48

    
49
public class CDMServer {
50

    
51
    public static final Logger logger = Logger.getLogger(CDMServer.class);
52

    
53
    @TestDataSource
54
    protected DataSource dataSource;
55

    
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 = "";
62

    
63
    public static final Resource DEFAULT_CDM_WEBAPP_RESOURCE =
64
            new ClassPathResource("/etc/jetty/cdmlib-remote-webapp.war");
65

    
66
    public static final Resource DEFAULT_DATASOURCE_FILE =
67
            new ClassPathResource("datasources.xml");
68

    
69
    public static final Resource DEFAULT_JETTY_RUNNER_RESOURCE =
70
            new ClassPathResource("/etc/jetty/jetty-runner-9.2.3.v20140905.jar");
71

    
72
    public static final Resource DEFAULT_JETTY_RESOURCE =
73
            new ClassPathResource("/etc/jetty/start-9.2.3.v20140905.jar");
74

    
75
    private static CDMServer cdmServer = null;
76
    private static CDMServerException cdmse = null;
77

    
78
    private void CDMServer() {}
79

    
80
    public static CDMServer getInstance() {
81
        if(cdmServer == null) {
82
            cdmServer = new CDMServer();
83
        }
84
        return cdmServer;
85
    }
86

    
87
    public String getName() {
88
        return name;
89
    }
90

    
91
    public String getHost() {
92
        return host;
93
    }
94

    
95
    public int getPort() {
96
        return httpPort;
97
    }
98

    
99
    public String getContextPath() {
100
        return contextPath;
101
    }
102

    
103
    public void setHttpPort(int port) {
104
        this.httpPort = port;
105
    }
106

    
107
    public void setStopPort(int stopPort) {
108
        this.stopPort = stopPort;
109
    }
110

    
111
    public void setStopKey(String stopKey) {
112
        this.stopKey = stopKey;
113
    }
114

    
115

    
116
    public static boolean isRunningInEclipse() {
117
        return (System.getProperty("sun.java.command") != null &&
118
                System.getProperty("sun.java.command").startsWith("org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"));
119
    }
120

    
121
    private String getVMArgs() throws IOException {
122
        StringBuilder sb = new StringBuilder();
123
        sb.append(" -Dspring.profiles.active=remoting");
124
        sb.append(" -Dcdm.beanDefinitionFile=" + DEFAULT_DATASOURCE_FILE.getFile().getAbsolutePath());
125
        sb.append(" -Dcdm.datasource=cdmTest");
126
        return sb.toString();
127
    }
128

    
129
    private String getStartServerArgs() throws IOException {
130
        StringBuilder sb = new StringBuilder();
131
        sb.append(" --port " + httpPort);
132
        return sb.toString();
133
    }
134

    
135
    private String getStopServerSettings() {
136
        StringBuilder sb = new StringBuilder();
137
        sb.append(" --stop-port ");
138
        sb.append(stopPort);
139
        sb.append(" --stop-key ");
140
        sb.append(stopKey);
141
        return sb.toString();
142
    }
143

    
144
    private String getStopServerArgs() {
145
        StringBuilder sb = new StringBuilder();
146
        sb.append(" STOP.PORT=");
147
        sb.append(stopPort);
148
        sb.append(" STOP.KEY=");
149
        sb.append(stopKey);
150
        return sb.toString();
151
    }
152

    
153

    
154
    public void start() throws CDMServerException {
155

    
156
        /**
157
         * First check if the CDM server responds to a service request, which implies that
158
         * the server has started properly. If no response is received then check if the
159
         * server is listening on specific host / port, which implies that the server
160
         * has started but incorrectly, in which case we try to force stop it (if we can)
161
         * and start a new server.
162
         */
163
        if(isStarted(1)) {
164
            logger.info("[CDM-Server] Server already running @ " + host + ":" + httpPort );
165
            return;
166
        }
167

    
168
        Thread t = new Thread() {
169
            @Override
170
            public void run() {
171

    
172
                StringBuffer output = new StringBuffer();
173
                try{
174
                    Process p;
175
                    String command = "java "
176
                            + getVMArgs()
177
                            + " -jar "
178
                            + DEFAULT_JETTY_RUNNER_RESOURCE.getFile().getAbsolutePath()
179
                            + getStartServerArgs()
180
                            + getStopServerSettings()
181
                            + " "
182
                            + DEFAULT_CDM_WEBAPP_RESOURCE.getFile().getAbsolutePath();
183
                    logger.info("[CDM-Server] Starting server with Command : " + command);
184
                    p = Runtime.getRuntime().exec(command);
185

    
186
                    BufferedReader inpReader =
187
                            new BufferedReader(new InputStreamReader(p.getInputStream()));
188

    
189
                    BufferedReader errReader =
190
                            new BufferedReader(new InputStreamReader(p.getErrorStream()));
191

    
192
                    String line = "";
193
                    while ((line = inpReader.readLine())!= null) {
194
                        logger.info("[CDM-Server Start] : " + line);
195
                    }
196

    
197
                    while ((line = errReader.readLine())!= null) {
198
                        logger.info("[CDM-Server Start] : " + line);
199
                    }
200

    
201
                } catch (Exception e) {
202
                    e.printStackTrace();
203
                    cdmse = new CDMServerException(e);
204
                }
205
            }
206
        };
207

    
208
        t.setDaemon(true);
209
        cdmse = null;
210
        t.start();
211

    
212
        if(isStarted(50)) {
213
            logger.info("[CDM-Server] Server running @ " + host + ":" + httpPort );
214
        } else {
215
            logger.info("[CDM-Server] Server not started within given interval");
216
            // making sure to kill server if it is not started correctly
217
            try {
218
                stop(true);
219
            } catch (Exception e) {
220
                throw new CDMServerException("CDM Server could not be stopped : " + e.getMessage());
221
            }
222
            throw new CDMServerException("CDM Server not started : ");
223
        }
224

    
225
    }
226

    
227

    
228
    public boolean isStarted(int checkingIntervals) throws CDMServerException  {
229
        CdmRemoteSourceBase crsb = new CdmRemoteSourceBase("local-cdm-server",
230
                host,
231
                httpPort,
232
                contextPath,
233
                null);
234
        int intervalsCount = 0;
235
        do {
236
            try {
237
                if(cdmse != null) {
238
                    return false;
239
                }
240
                boolean check = crsb.checkConnection();
241
                if(check) {
242
                    logger.info("[CDM-Server] Running @ " + host + ":" + httpPort );
243
                    return true;
244
                }
245
            } catch (Exception e) {
246

    
247
            }
248
            try {
249
                Thread.sleep(1000);
250
            } catch (InterruptedException ie) {
251
                throw new CDMServerException("Error checking CDM Server status", ie);
252
            }
253
            intervalsCount++;
254
        } while (intervalsCount < checkingIntervals);
255
        return false;
256
    }
257

    
258
    public void stop() throws Exception {
259
        stop(false);
260
    }
261

    
262
    public void stop(boolean force) throws Exception {
263

    
264
        if(!force) {
265
            if(!getInstance().isStarted(1)) {
266
                logger.info("[CDM-Server] Server already stopped @ " + host + ":" + httpPort );
267
                return;
268
            }
269
        }
270

    
271
        Thread t = new Thread() {
272
            @Override
273
            public void run() {
274
                StringBuffer output = new StringBuffer();
275
                try{
276
                    Process p;
277
                    String command = "java -jar " + DEFAULT_JETTY_RESOURCE.getFile().getAbsolutePath()
278
                            + getStopServerArgs() + " --stop ";
279
                    logger.info("[CDM-Server] Stop Command : " + command);
280
                    p = Runtime.getRuntime().exec(command);
281

    
282
                    BufferedReader inpReader =
283
                            new BufferedReader(new InputStreamReader(p.getInputStream()));
284

    
285
                    BufferedReader errReader =
286
                            new BufferedReader(new InputStreamReader(p.getErrorStream()));
287

    
288
                    String line = "";
289
                    while ((line = inpReader.readLine())!= null) {
290
                        logger.info("[CDM-Server Stop] : " + line);
291
                    }
292

    
293
                    while ((line = errReader.readLine())!= null) {
294
                        logger.info("[CDM-Server Stop] : " + line);
295
                    }
296
                    logger.info("CDM-Server Stopped : ");
297
                } catch (Exception e) {
298
                    logger.info("[CDM-Server] Could not stop @ " + host + ":" + httpPort + ". Please kill it manually");
299

    
300
                }
301

    
302
            }
303
        };
304

    
305
        t.setDaemon(true);
306
        t.start();
307

    
308
    }
309

    
310
    public static void stopServerViaJMX(int jmxPort) throws CDMServerException  {
311
        String JMX_URL = "service:jmx:rmi:///jndi/rmi://localhost:" + jmxPort + "/jmxrmi";
312
        logger.warn("Shutting down Jetty instance ... ");
313

    
314
        try {
315
            JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(JMX_URL), null);
316
            connector.connect(null);
317
            MBeanServerConnection connection = connector.getMBeanServerConnection();
318
            ObjectName objectName = new ObjectName("org.eclipse.jetty.server:type=server,id=0");
319
            connection.invoke(objectName, "stop", null, null);
320
            logger.warn("Shutdown command sent");
321
        } catch (InstanceNotFoundException e) {
322
            throw new CDMServerException(e);
323
        } catch (MBeanException e) {
324
            throw new CDMServerException(e);
325
        } catch (ReflectionException e) {
326
            throw new CDMServerException(e);
327
        } catch (IOException e) {
328
            throw new CDMServerException(e);
329
        } catch (MalformedObjectNameException e) {
330
            throw new CDMServerException(e);
331
        }
332

    
333

    
334

    
335
    }
336
}
(2-2/7)