Add test for editor / server cdmlib version check
[taxeditor.git] / eu.etaxonomy.taxeditor.cdmlib / src / main / java / eu / etaxonomy / taxeditor / remoting / source / CdmServerInfo.java
index ec715ab2f07e4766a382145ce1ad3d2fadc03824..f30a93dcdfb17d7949b400aae3de95c86093d459 100644 (file)
@@ -12,8 +12,11 @@ package eu.etaxonomy.taxeditor.remoting.source;
 import java.io.IOException;
 import java.net.Socket;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.ClientProtocolException;
@@ -21,13 +24,19 @@ import org.apache.http.client.HttpClient;
 import org.apache.http.client.ResponseHandler;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.params.HttpConnectionParams;
+import org.apache.http.params.HttpParams;
 import org.apache.http.util.EntityUtils;
 import org.apache.log4j.Logger;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
+import eu.etaxonomy.cdm.api.application.CdmApplicationState;
 import eu.etaxonomy.cdm.config.CdmSourceException;
+import eu.etaxonomy.cdm.database.CdmPersistentDataSource;
+import eu.etaxonomy.cdm.database.ICdmDataSource;
+import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
 import eu.etaxonomy.taxeditor.remoting.server.CDMServerException;
 
 /**
@@ -38,18 +47,25 @@ import eu.etaxonomy.taxeditor.remoting.server.CDMServerException;
 public class CdmServerInfo {
     public static final Logger logger = Logger.getLogger(CdmServerInfo.class);
 
+    private final static String CDMSERVER_PREFIX = "cdmserver";
     private final static String NAME_PRODUCTION = "edit-production";
     private final static String SERVER_PRODUCTION = "dev.e-taxonomy.eu";
 
     private final static String NAME_INTEGRATION = "edit-integration";
     private final static String SERVER_INTEGRATION = "int.e-taxonomy.eu";
 
+    private final static String NAME_DEMO_1 = "edit-WS I";
+    private final static String SERVER_DEMO_1 = "160.45.63.230";
+
+    private final static String NAME_DEMO_2 = "edit-WS II";
+    private final static String SERVER_DEMO_2 = "160.45.63.231";
+
     private final static String NAME_TEST = "edit-test";
     private final static String SERVER_TEST = "test.e-taxonomy.eu";
 
-    private final static String SERVER_LOCALHOST = "localhost";
+    public final static String SERVER_LOCALHOST = "localhost";
     private final static String NAME_LOCALHOST = "localhost";
-    private final static String NAME_LOCALHOST_MGD = "localhost mgd.";
+    public final static String NAME_LOCALHOST_MGD = "localhost mgd.";
 
     private final static String NAME_LOCALHOST_DEV = "localhost-dev";
     private final static String NAME_INSTANCE_LOCALHOST_DEV = "local-dev";
@@ -62,12 +78,18 @@ public class CdmServerInfo {
     private final int port;
     private final List<CdmInstanceInfo> instances;
 
+    private static List<CdmServerInfo> cdmServerInfoList;
+
+    private String cdmlibServicesVersion = "";
+    private String cdmlibServicesLastModified = "";
+
 
     public CdmServerInfo(String name, String server, int port) {
         this.name = name;
         this.server = server;
         this.port = port;
         instances = new ArrayList<CdmInstanceInfo>();
+
     }
 
 
@@ -78,10 +100,86 @@ public class CdmServerInfo {
 
     }
 
+    public boolean isLocalhost() {
+        return name.startsWith(SERVER_LOCALHOST);
+    }
+
+    public boolean isLocalhostMgd() {
+        return NAME_LOCALHOST_MGD.equals(name);
+    }
+
+    public String getCdmlibServicesVersion() {
+        return cdmlibServicesVersion;
+    }
+
+    public String getCdmlibLastModified() {
+        return cdmlibServicesLastModified;
+    }
+
     public void refreshInstances() throws CDMServerException {
-        String url = "http://" + server + ":" + String.valueOf(port) + "/cdmserver/instances.jsp";
+        instances.clear();
+        if(isLocalhostMgd()) {
+            addInstancesFromDataSourcesConfig();
+        } else {
+            addInstancesViaHttp();
+        }
+        Collections.sort(instances, new Comparator<CdmInstanceInfo>() {
+            @Override
+            public int compare(CdmInstanceInfo cii1, CdmInstanceInfo cii2)
+            {
+                return cii1.getName().toString().compareTo(cii2.getName().toString());
+            }
+        });
+    }
+
+    public void updateInfo() throws CDMServerException {
+        String url = "http://" + server + ":" + String.valueOf(port) + "/" + CDMSERVER_PREFIX + "/info.jsp";
+        String responseBody = getResponse(url);
+        if(responseBody != null) {
+            try {
+                JSONObject info = new JSONObject(responseBody);
+                cdmlibServicesVersion =  info.getString("cdmlibServicesVersion");
+                cdmlibServicesLastModified = info.getString("cdmlibServicesLastModified");
+            } catch (JSONException e) {
+                throw new CDMServerException(e);
+            }
+        }
+    }
+
+    public void addInstancesViaHttp() throws CDMServerException {
+        updateInfo();
+        String url = "http://" + server + ":" + String.valueOf(port) + "/" + CDMSERVER_PREFIX + "/instances.jsp";
+        String responseBody = getResponse(url);
+        if(responseBody != null) {
+            try {
+                JSONArray array = new JSONArray(responseBody);
+                for(int i=0;i<array.length();i++) {
+                    JSONObject instance = (JSONObject)array.get(i);
+                    if(instance != null) {
+                        JSONObject conf = (JSONObject)instance.get("configuration");
+                        if(conf != null) {
+                            String instanceName = conf.getString("instanceName");
+                            // we need to remove the first (char) forward slash from
+                            // the base path
+                            String basePath = conf.getString("basePath").substring(1);
+                            addInstance(instanceName, basePath);
+                            logger.info("Added instance with name : " + instanceName + ", basePath : " + basePath);
+                        }
+                    }
+                }
+            } catch (JSONException e) {
+                throw new CDMServerException(e);
+            }
+        }
+    }
 
+    private String getResponse(String url) throws CDMServerException {
         HttpClient client = new DefaultHttpClient();
+        HttpParams params = client.getParams();
+
+        HttpConnectionParams.setConnectionTimeout(params, 5000);
+        HttpConnectionParams.setSoTimeout(params, 5000);
+
         HttpGet httpGet = new HttpGet(url);
 
         logger.info("Executing request " + httpGet.getRequestLine());
@@ -110,32 +208,22 @@ public class CdmServerInfo {
         } catch (IOException e) {
             throw new CDMServerException(e);
         }
+        return responseBody;
+    }
 
+    public void addInstancesFromDataSourcesConfig() {
 
-        if(responseBody != null) {
-            try {
-                JSONArray array = new JSONArray(responseBody);
-                for(int i=0;i<array.length();i++) {
-                    JSONObject instance = (JSONObject)array.get(i);
-                    if(instance != null) {
-                        JSONObject conf = (JSONObject)instance.get("configuration");
-                        if(conf != null) {
-                            String instanceName = conf.getString("instanceName");
-                            // we need to remove the first (char) forward slash from
-                            // the base path
-                            String basePath = conf.getString("basePath").substring(1);
-                            addInstance(instanceName, basePath);
-                            logger.info("Added instance with name : " + instanceName + ", basePath : " + basePath);
-                        }
-                    }
-                }
-            } catch (JSONException e) {
-                throw new CDMServerException(e);
-            }
+        for(ICdmDataSource dataSource : CdmPersistentDataSource.getAllDataSources()){
+            logger.warn("Adding local instance " + dataSource.getName());
+            addInstance(dataSource.getName(), dataSource.getName());
         }
 
     }
 
+    public String toString(String instanceName, int port) {
+        return server + ":" + String.valueOf(port) + "/" + instanceName;
+    }
+
     public CdmInstanceInfo getInstanceFromName(String instanceName) {
         if(instanceName == null) {
             return null;
@@ -149,7 +237,7 @@ public class CdmServerInfo {
         return null;
     }
 
-    public ICdmRemoteSource getCdmRemoteSource(CdmInstanceInfo instance) {
+    public CdmRemoteSource getCdmRemoteSource(CdmInstanceInfo instance, int port) {
         if(instance != null) {
             return CdmRemoteSource.NewInstance(name,
                     server,
@@ -160,20 +248,23 @@ public class CdmServerInfo {
         return null;
     }
 
-    public boolean pingServer(){
+    public boolean pingServer() {
         try {
             Socket s = new Socket(server, port);
             logger.info("[CDM-Server] Available @ " + server + ":" + port );
+            updateInfo();
             return true;
         } catch (IOException ioe) {
 
+        } catch (CDMServerException e) {
+
         }
         return false;
     }
 
-    public boolean pingInstance(CdmInstanceInfo instance) throws CDMServerException  {
+    public boolean pingInstance(CdmInstanceInfo instance, int port) throws CDMServerException  {
 
-        ICdmRemoteSource crs = getCdmRemoteSource(instance);
+        ICdmRemoteSource crs = getCdmRemoteSource(instance, port);
         try {
             if(crs != null && crs.checkConnection()) {
                 logger.info("[CDM-Server] Running @ " + server + ":" + port + " for instance " + instance);
@@ -186,13 +277,96 @@ public class CdmServerInfo {
         return false;
     }
 
+    public int compareDbSchemaVersion(CdmInstanceInfo instance, int port) throws CDMServerException {
+
+        ICdmRemoteSource crs = getCdmRemoteSource(instance, port);
+        String dbSchemaVersion;
+        try {
+            dbSchemaVersion = crs.getDbSchemaVersion();
+        } catch (CdmSourceException e) {
+            throw new CDMServerException(e);
+        }
+
+
+        if(dbSchemaVersion != null) {
+            return CdmMetaData.compareVersion(dbSchemaVersion, CdmMetaData.getDbSchemaVersion(), 3, null);
+        } else {
+            throw new CDMServerException("Cannot determine editor db. schema version");
+        }
+    }
+
+    public int compareCdmlibServicesVersion() throws CdmSourceException {
+
+        String serverVersion = cdmlibServicesVersion;
+        String serverCdmlibLastModified = cdmlibServicesLastModified;
+
+        return compareCdmlibServicesVersion(serverVersion, serverCdmlibLastModified);
+    }
+
+
+    /**
+     * @param serverVersion
+     * @param editorVersion
+     * @throws CdmSourceException
+     */
+    public static int compareCdmlibServicesVersion(String serverVersion, String serverCdmlibLastModified) throws CdmSourceException {
+
+        String editorVersion = CdmApplicationState.getCdmlibVersion();
+        String editorCdmlibLastModified = CdmApplicationState.getCdmlibLastModified();
+
+        int result = 0;
+        if(StringUtils.isBlank(serverVersion) || StringUtils.isBlank(editorVersion)) {
+            throw new CdmSourceException("cdmlib-services server or editor version is empty");
+        }
+
+        String[] serverVersionSplit = serverVersion.split("\\.");
+        String[] editorVersionSplit = editorVersion.split("\\.");
+
+        if(serverVersionSplit.length < 3 || editorVersionSplit.length < 3 || serverVersionSplit.length > 4 || editorVersionSplit.length > 4) {
+            throw new CdmSourceException("cdmlib-services server or editor version is invalid");
+        }
+
+        Integer serverVersionPart;
+        Integer editorVersionPart;
+
+        for(int i=0 ; i<3 ; i++) {
+            serverVersionPart = Integer.valueOf(serverVersionSplit[i]);
+            editorVersionPart = Integer.valueOf(editorVersionSplit[i]);
+
+            int partCompare = serverVersionPart.compareTo(editorVersionPart);
+            if (partCompare != 0){
+                return partCompare;
+            }
+        }
+        // at this point major, minor and patch versions are matching
+
+        if(StringUtils.isBlank(serverCdmlibLastModified) || StringUtils.isBlank(editorCdmlibLastModified)) {
+            throw new CdmSourceException("cdmlib-services server or editor version is empty");
+        }
+
+        String cdmServerIgnoreVersion = System.getProperty("cdm.server.version.lm.ignore");
+        if(StringUtils.isBlank(cdmServerIgnoreVersion) || !cdmServerIgnoreVersion.equals("true")) {
+            Long serverLastModified = Long.valueOf(serverCdmlibLastModified);
+            Long editorLastModified = Long.valueOf(editorCdmlibLastModified);
+            return serverLastModified.compareTo(editorLastModified);
+        }
+
+        return 0;
+    }
+
+
+
     public static List<CdmServerInfo> getCdmServers() {
-        List<CdmServerInfo> cdmServerInfoList = new ArrayList<CdmServerInfo>();
-        cdmServerInfoList.add(new CdmServerInfo(NAME_PRODUCTION, SERVER_PRODUCTION, 80));
-        cdmServerInfoList.add(new CdmServerInfo(NAME_INTEGRATION, SERVER_INTEGRATION, 80));
-        cdmServerInfoList.add(new CdmServerInfo(NAME_TEST, SERVER_TEST, 80));
-        cdmServerInfoList.add(new CdmServerInfo(NAME_LOCALHOST, SERVER_LOCALHOST, 8080));
-        cdmServerInfoList.add(new CdmServerInfo(NAME_LOCALHOST_MGD, SERVER_LOCALHOST,8080));
+        if(cdmServerInfoList == null) {
+            cdmServerInfoList = new ArrayList<CdmServerInfo>();
+            //cdmServerInfoList.add(new CdmServerInfo(NAME_PRODUCTION, SERVER_PRODUCTION, 80));
+            //cdmServerInfoList.add(new CdmServerInfo(NAME_INTEGRATION, SERVER_INTEGRATION, 80));
+            cdmServerInfoList.add(new CdmServerInfo(NAME_DEMO_1, SERVER_DEMO_1, 80));
+            cdmServerInfoList.add(new CdmServerInfo(NAME_DEMO_2, SERVER_DEMO_2, 80));
+            cdmServerInfoList.add(new CdmServerInfo(NAME_TEST, SERVER_TEST, 80));
+            cdmServerInfoList.add(new CdmServerInfo(NAME_LOCALHOST, SERVER_LOCALHOST, 8080));
+            cdmServerInfoList.add(new CdmServerInfo(NAME_LOCALHOST_MGD, SERVER_LOCALHOST,8080));
+        }
         return cdmServerInfoList;
     }
 
@@ -217,17 +391,18 @@ public class CdmServerInfo {
         return instances;
     }
 
-    public static ICdmRemoteSource getDevServerRemoteSource() {
-        String value=System.getProperty("cdm.server.dev.activate");
+    public static CdmRemoteSource getDevServerRemoteSource() {
+        String value = System.getProperty("cdm.server.dev.port");
         boolean available = false;
         CdmInstanceInfo devInstance = null;
-        if(value != null && value.equals("true")) {
-            CdmServerInfo devCii = new CdmServerInfo(NAME_LOCALHOST_DEV, SERVER_LOCALHOST_DEV, PORT_LOCALHOST_DEV);
+        if(value != null && !value.isEmpty()) {
+            int devPort = Integer.valueOf(value);
+            CdmServerInfo devCii = new CdmServerInfo(NAME_LOCALHOST_DEV, SERVER_LOCALHOST_DEV, devPort);
             try {
                 devInstance = devCii.addInstance(NAME_INSTANCE_LOCALHOST_DEV, BASEPATH_LOCALHOST_DEV);
-                available = devCii.pingInstance(devInstance);
+                available = devCii.pingInstance(devInstance, devPort);
                 if(available) {
-                    return devCii.getCdmRemoteSource(devInstance);
+                    return devCii.getCdmRemoteSource(devInstance, devPort);
                 }
             } catch (Exception e) {
 
@@ -238,6 +413,12 @@ public class CdmServerInfo {
 
     public class CdmInstanceInfo {
         private final String name;
+
+        /**
+         * The full path of the instance including the the prefix (if any).
+         * E.g. for an EDIT instance this would be something like "cdmserver/remoting"
+         * For a managed local server this would simply be "remoting"
+         */
         private final String basePath;