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