f30a93dcdfb17d7949b400aae3de95c86093d459
[taxeditor.git] / eu.etaxonomy.taxeditor.cdmlib / src / main / java / eu / etaxonomy / taxeditor / remoting / source / CdmServerInfo.java
1 // $Id$
2 /**
3 * Copyright (C) 2015 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.remoting.source;
11
12 import java.io.IOException;
13 import java.net.Socket;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.Comparator;
17 import java.util.List;
18
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.http.HttpEntity;
21 import org.apache.http.HttpResponse;
22 import org.apache.http.client.ClientProtocolException;
23 import org.apache.http.client.HttpClient;
24 import org.apache.http.client.ResponseHandler;
25 import org.apache.http.client.methods.HttpGet;
26 import org.apache.http.impl.client.DefaultHttpClient;
27 import org.apache.http.params.HttpConnectionParams;
28 import org.apache.http.params.HttpParams;
29 import org.apache.http.util.EntityUtils;
30 import org.apache.log4j.Logger;
31 import org.json.JSONArray;
32 import org.json.JSONException;
33 import org.json.JSONObject;
34
35 import eu.etaxonomy.cdm.api.application.CdmApplicationState;
36 import eu.etaxonomy.cdm.config.CdmSourceException;
37 import eu.etaxonomy.cdm.database.CdmPersistentDataSource;
38 import eu.etaxonomy.cdm.database.ICdmDataSource;
39 import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
40 import eu.etaxonomy.taxeditor.remoting.server.CDMServerException;
41
42 /**
43 * @author cmathew
44 * @date 20 Jan 2015
45 *
46 */
47 public class CdmServerInfo {
48 public static final Logger logger = Logger.getLogger(CdmServerInfo.class);
49
50 private final static String CDMSERVER_PREFIX = "cdmserver";
51 private final static String NAME_PRODUCTION = "edit-production";
52 private final static String SERVER_PRODUCTION = "dev.e-taxonomy.eu";
53
54 private final static String NAME_INTEGRATION = "edit-integration";
55 private final static String SERVER_INTEGRATION = "int.e-taxonomy.eu";
56
57 private final static String NAME_DEMO_1 = "edit-WS I";
58 private final static String SERVER_DEMO_1 = "160.45.63.230";
59
60 private final static String NAME_DEMO_2 = "edit-WS II";
61 private final static String SERVER_DEMO_2 = "160.45.63.231";
62
63 private final static String NAME_TEST = "edit-test";
64 private final static String SERVER_TEST = "test.e-taxonomy.eu";
65
66 public final static String SERVER_LOCALHOST = "localhost";
67 private final static String NAME_LOCALHOST = "localhost";
68 public final static String NAME_LOCALHOST_MGD = "localhost mgd.";
69
70 private final static String NAME_LOCALHOST_DEV = "localhost-dev";
71 private final static String NAME_INSTANCE_LOCALHOST_DEV = "local-dev";
72 private final static String SERVER_LOCALHOST_DEV = "localhost";
73 private final static int PORT_LOCALHOST_DEV = 8080;
74 private final static String BASEPATH_LOCALHOST_DEV = "";
75
76 private final String name;
77 private final String server;
78 private final int port;
79 private final List<CdmInstanceInfo> instances;
80
81 private static List<CdmServerInfo> cdmServerInfoList;
82
83 private String cdmlibServicesVersion = "";
84 private String cdmlibServicesLastModified = "";
85
86
87 public CdmServerInfo(String name, String server, int port) {
88 this.name = name;
89 this.server = server;
90 this.port = port;
91 instances = new ArrayList<CdmInstanceInfo>();
92
93 }
94
95
96 public CdmInstanceInfo addInstance(String name, String basePath) {
97 CdmInstanceInfo cii = new CdmInstanceInfo(name, basePath);
98 instances.add(cii);
99 return cii;
100
101 }
102
103 public boolean isLocalhost() {
104 return name.startsWith(SERVER_LOCALHOST);
105 }
106
107 public boolean isLocalhostMgd() {
108 return NAME_LOCALHOST_MGD.equals(name);
109 }
110
111 public String getCdmlibServicesVersion() {
112 return cdmlibServicesVersion;
113 }
114
115 public String getCdmlibLastModified() {
116 return cdmlibServicesLastModified;
117 }
118
119 public void refreshInstances() throws CDMServerException {
120 instances.clear();
121 if(isLocalhostMgd()) {
122 addInstancesFromDataSourcesConfig();
123 } else {
124 addInstancesViaHttp();
125 }
126 Collections.sort(instances, new Comparator<CdmInstanceInfo>() {
127 @Override
128 public int compare(CdmInstanceInfo cii1, CdmInstanceInfo cii2)
129 {
130 return cii1.getName().toString().compareTo(cii2.getName().toString());
131 }
132 });
133 }
134
135 public void updateInfo() throws CDMServerException {
136 String url = "http://" + server + ":" + String.valueOf(port) + "/" + CDMSERVER_PREFIX + "/info.jsp";
137 String responseBody = getResponse(url);
138 if(responseBody != null) {
139 try {
140 JSONObject info = new JSONObject(responseBody);
141 cdmlibServicesVersion = info.getString("cdmlibServicesVersion");
142 cdmlibServicesLastModified = info.getString("cdmlibServicesLastModified");
143 } catch (JSONException e) {
144 throw new CDMServerException(e);
145 }
146 }
147 }
148
149 public void addInstancesViaHttp() throws CDMServerException {
150 updateInfo();
151 String url = "http://" + server + ":" + String.valueOf(port) + "/" + CDMSERVER_PREFIX + "/instances.jsp";
152 String responseBody = getResponse(url);
153 if(responseBody != null) {
154 try {
155 JSONArray array = new JSONArray(responseBody);
156 for(int i=0;i<array.length();i++) {
157 JSONObject instance = (JSONObject)array.get(i);
158 if(instance != null) {
159 JSONObject conf = (JSONObject)instance.get("configuration");
160 if(conf != null) {
161 String instanceName = conf.getString("instanceName");
162 // we need to remove the first (char) forward slash from
163 // the base path
164 String basePath = conf.getString("basePath").substring(1);
165 addInstance(instanceName, basePath);
166 logger.info("Added instance with name : " + instanceName + ", basePath : " + basePath);
167 }
168 }
169 }
170 } catch (JSONException e) {
171 throw new CDMServerException(e);
172 }
173 }
174 }
175
176 private String getResponse(String url) throws CDMServerException {
177 HttpClient client = new DefaultHttpClient();
178 HttpParams params = client.getParams();
179
180 HttpConnectionParams.setConnectionTimeout(params, 5000);
181 HttpConnectionParams.setSoTimeout(params, 5000);
182
183 HttpGet httpGet = new HttpGet(url);
184
185 logger.info("Executing request " + httpGet.getRequestLine());
186
187 // Create a custom response handler
188 ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
189
190 @Override
191 public String handleResponse(
192 final HttpResponse response) throws ClientProtocolException, IOException {
193 int status = response.getStatusLine().getStatusCode();
194 if (status >= 200 && status < 300) {
195 HttpEntity entity = response.getEntity();
196 return entity != null ? EntityUtils.toString(entity) : null;
197 } else {
198 throw new ClientProtocolException("Unexpected response status: " + status);
199 }
200 }
201
202 };
203 String responseBody = null;
204 try {
205 responseBody = client.execute(httpGet, responseHandler);
206 } catch (ClientProtocolException e) {
207 throw new CDMServerException(e);
208 } catch (IOException e) {
209 throw new CDMServerException(e);
210 }
211 return responseBody;
212 }
213
214 public void addInstancesFromDataSourcesConfig() {
215
216 for(ICdmDataSource dataSource : CdmPersistentDataSource.getAllDataSources()){
217 logger.warn("Adding local instance " + dataSource.getName());
218 addInstance(dataSource.getName(), dataSource.getName());
219 }
220
221 }
222
223 public String toString(String instanceName, int port) {
224 return server + ":" + String.valueOf(port) + "/" + instanceName;
225 }
226
227 public CdmInstanceInfo getInstanceFromName(String instanceName) {
228 if(instanceName == null) {
229 return null;
230 }
231
232 for(CdmInstanceInfo instance : instances) {
233 if(instance.getName() != null && instance.getName().equals(instanceName)) {
234 return instance;
235 }
236 }
237 return null;
238 }
239
240 public CdmRemoteSource getCdmRemoteSource(CdmInstanceInfo instance, int port) {
241 if(instance != null) {
242 return CdmRemoteSource.NewInstance(name,
243 server,
244 port,
245 instance.getBasePath(),
246 null);
247 }
248 return null;
249 }
250
251 public boolean pingServer() {
252 try {
253 Socket s = new Socket(server, port);
254 logger.info("[CDM-Server] Available @ " + server + ":" + port );
255 updateInfo();
256 return true;
257 } catch (IOException ioe) {
258
259 } catch (CDMServerException e) {
260
261 }
262 return false;
263 }
264
265 public boolean pingInstance(CdmInstanceInfo instance, int port) throws CDMServerException {
266
267 ICdmRemoteSource crs = getCdmRemoteSource(instance, port);
268 try {
269 if(crs != null && crs.checkConnection()) {
270 logger.info("[CDM-Server] Running @ " + server + ":" + port + " for instance " + instance);
271 return true;
272 }
273 } catch (CdmSourceException e) {
274 throw new CDMServerException(e);
275 }
276
277 return false;
278 }
279
280 public int compareDbSchemaVersion(CdmInstanceInfo instance, int port) throws CDMServerException {
281
282 ICdmRemoteSource crs = getCdmRemoteSource(instance, port);
283 String dbSchemaVersion;
284 try {
285 dbSchemaVersion = crs.getDbSchemaVersion();
286 } catch (CdmSourceException e) {
287 throw new CDMServerException(e);
288 }
289
290
291 if(dbSchemaVersion != null) {
292 return CdmMetaData.compareVersion(dbSchemaVersion, CdmMetaData.getDbSchemaVersion(), 3, null);
293 } else {
294 throw new CDMServerException("Cannot determine editor db. schema version");
295 }
296 }
297
298 public int compareCdmlibServicesVersion() throws CdmSourceException {
299
300 String serverVersion = cdmlibServicesVersion;
301 String serverCdmlibLastModified = cdmlibServicesLastModified;
302
303 return compareCdmlibServicesVersion(serverVersion, serverCdmlibLastModified);
304 }
305
306
307 /**
308 * @param serverVersion
309 * @param editorVersion
310 * @throws CdmSourceException
311 */
312 public static int compareCdmlibServicesVersion(String serverVersion, String serverCdmlibLastModified) throws CdmSourceException {
313
314 String editorVersion = CdmApplicationState.getCdmlibVersion();
315 String editorCdmlibLastModified = CdmApplicationState.getCdmlibLastModified();
316
317 int result = 0;
318 if(StringUtils.isBlank(serverVersion) || StringUtils.isBlank(editorVersion)) {
319 throw new CdmSourceException("cdmlib-services server or editor version is empty");
320 }
321
322 String[] serverVersionSplit = serverVersion.split("\\.");
323 String[] editorVersionSplit = editorVersion.split("\\.");
324
325 if(serverVersionSplit.length < 3 || editorVersionSplit.length < 3 || serverVersionSplit.length > 4 || editorVersionSplit.length > 4) {
326 throw new CdmSourceException("cdmlib-services server or editor version is invalid");
327 }
328
329 Integer serverVersionPart;
330 Integer editorVersionPart;
331
332 for(int i=0 ; i<3 ; i++) {
333 serverVersionPart = Integer.valueOf(serverVersionSplit[i]);
334 editorVersionPart = Integer.valueOf(editorVersionSplit[i]);
335
336 int partCompare = serverVersionPart.compareTo(editorVersionPart);
337 if (partCompare != 0){
338 return partCompare;
339 }
340 }
341 // at this point major, minor and patch versions are matching
342
343 if(StringUtils.isBlank(serverCdmlibLastModified) || StringUtils.isBlank(editorCdmlibLastModified)) {
344 throw new CdmSourceException("cdmlib-services server or editor version is empty");
345 }
346
347 String cdmServerIgnoreVersion = System.getProperty("cdm.server.version.lm.ignore");
348 if(StringUtils.isBlank(cdmServerIgnoreVersion) || !cdmServerIgnoreVersion.equals("true")) {
349 Long serverLastModified = Long.valueOf(serverCdmlibLastModified);
350 Long editorLastModified = Long.valueOf(editorCdmlibLastModified);
351 return serverLastModified.compareTo(editorLastModified);
352 }
353
354 return 0;
355 }
356
357
358
359 public static List<CdmServerInfo> getCdmServers() {
360 if(cdmServerInfoList == null) {
361 cdmServerInfoList = new ArrayList<CdmServerInfo>();
362 //cdmServerInfoList.add(new CdmServerInfo(NAME_PRODUCTION, SERVER_PRODUCTION, 80));
363 //cdmServerInfoList.add(new CdmServerInfo(NAME_INTEGRATION, SERVER_INTEGRATION, 80));
364 cdmServerInfoList.add(new CdmServerInfo(NAME_DEMO_1, SERVER_DEMO_1, 80));
365 cdmServerInfoList.add(new CdmServerInfo(NAME_DEMO_2, SERVER_DEMO_2, 80));
366 cdmServerInfoList.add(new CdmServerInfo(NAME_TEST, SERVER_TEST, 80));
367 cdmServerInfoList.add(new CdmServerInfo(NAME_LOCALHOST, SERVER_LOCALHOST, 8080));
368 cdmServerInfoList.add(new CdmServerInfo(NAME_LOCALHOST_MGD, SERVER_LOCALHOST,8080));
369 }
370 return cdmServerInfoList;
371 }
372
373 public String getName() {
374 return name;
375 }
376
377 public String getServer() {
378 return server;
379 }
380
381
382 public int getPort() {
383 return port;
384 }
385
386
387 public List<CdmInstanceInfo> getInstances() throws CDMServerException {
388 if(instances.isEmpty()) {
389 refreshInstances();
390 }
391 return instances;
392 }
393
394 public static CdmRemoteSource getDevServerRemoteSource() {
395 String value = System.getProperty("cdm.server.dev.port");
396 boolean available = false;
397 CdmInstanceInfo devInstance = null;
398 if(value != null && !value.isEmpty()) {
399 int devPort = Integer.valueOf(value);
400 CdmServerInfo devCii = new CdmServerInfo(NAME_LOCALHOST_DEV, SERVER_LOCALHOST_DEV, devPort);
401 try {
402 devInstance = devCii.addInstance(NAME_INSTANCE_LOCALHOST_DEV, BASEPATH_LOCALHOST_DEV);
403 available = devCii.pingInstance(devInstance, devPort);
404 if(available) {
405 return devCii.getCdmRemoteSource(devInstance, devPort);
406 }
407 } catch (Exception e) {
408
409 }
410 }
411 return null;
412 }
413
414 public class CdmInstanceInfo {
415 private final String name;
416
417 /**
418 * The full path of the instance including the the prefix (if any).
419 * E.g. for an EDIT instance this would be something like "cdmserver/remoting"
420 * For a managed local server this would simply be "remoting"
421 */
422 private final String basePath;
423
424
425 public CdmInstanceInfo(String name, String basePath) {
426 this.name = name;
427 this.basePath = basePath;
428 }
429
430
431 public String getName() {
432 return name;
433 }
434
435 public String getBasePath() {
436 return basePath;
437 }
438 }
439 }