Index: main/trunk/greenstone3/src/java/org/greenstone/util/ProtocolPortProperties.java
===================================================================
--- main/trunk/greenstone3/src/java/org/greenstone/util/ProtocolPortProperties.java	(revision 32358)
+++ main/trunk/greenstone3/src/java/org/greenstone/util/ProtocolPortProperties.java	(revision 32358)
@@ -0,0 +1,213 @@
+/*
+ *    ProtocolPortProperties.java
+ *    Copyright (C) 2008 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.util;
+
+import java.util.Properties;
+
+/*
+ * Utility class to set the protocol and port values from the Properties provided,
+ * which can be a Properties object loaded from either build.properties or global.properties
+ * Currently used by ServletRealmCheck and FedoraServiceProxy.
+ * (Could also be used by Server3.java and GlobalProperties in future, if applicable.)
+ * Can adjust fallback behaviour in this one location to make them all work consistently.
+ */
+public class ProtocolPortProperties {
+
+    public final boolean legacyMode; // true if before https protocol supported
+
+    public static final int ALL_CORRECT = 0;
+    public static final int SECONDARY_PORT_NON_NUMERIC = 1;
+    public static final int INVALID_PRIMARY_PORT = 2;
+    public static final int OLD_TOMCATPORT_BUT_NO_VALUE = 3;
+    public static final int NO_PROTOCOL_OR_PORT = 4;
+    public static final int INVALID_PROTOCOL = 5;
+    public static final int HTTPS_INCONSISTENCY = 6;
+
+    private static final String defProtocol = "http";
+    private static final String defHttpPort = "8383";
+    private static final String defHttpsPort = "8443";
+
+    private String protocol; //= defProtocol;
+    private String port; //defHttpPort; //defProtocol.equals("https") ? defHttpsPort : defHttpPort; // port that matches protocol as String
+    private String httpPort; //defHttpPort;
+    private String httpsPort; //defHttpsPort;
+    //private int portNum = -1; // port that matches protocol as int
+
+    private String errorMsg;
+    private int errorCode;
+
+    public String getProtocol() { return protocol; }
+    public String getPort() { return port; }
+    public String getHttpPort() { return httpPort; }
+    public String getHttpsPort() { return httpsPort; }
+    public int getPortNum() { return Integer.parseInt(port); }    
+
+    public String getErrorMsg() { return errorMsg; }
+    public int getErrorCode() { return errorCode; }
+
+    public boolean hadError() { return errorCode != ALL_CORRECT; }
+
+    // Won't attempt to recover on error.
+    // This means on error, port etc values will be invalid
+    public ProtocolPortProperties(Properties props) {
+	this(props, false);
+    }
+
+    public ProtocolPortProperties(Properties props, boolean recover)
+    {
+	StringBuffer msg = new StringBuffer();
+	
+	port = props.getProperty("tomcat.port");
+
+	// We could either be dealing with properties files from before https support was introduced, in which case we want to be backwards compatible
+	// Or we're dealing with properties files after https support was introduced. 
+	// To determine which, can ignore server.protocol: server.protocol was introduced at a time when tomcat.port was still in effect,
+	// server.protocol's presence does not indicate whether our GS3 installation supports https or not. Only the tomcat.port property
+	// indicates that: if tomcat.port exists it's an older GS3 that has no https support, so default to http. If there is no tomcat.port,
+	// but there is a server.protocol check for the newer tomcat.port.<protocol> properties.
+
+	if(port != null) { // tomcat.port exists, so this is a GS3 before https support.
+	    legacyMode = true;
+
+	    // Back when tomcat.port was used, server.protocol if specified
+	    // would always be treated as http regardless of what it was set to
+	    protocol = defProtocol;
+
+	    if(port.equals("")) {
+		errorCode =  OLD_TOMCATPORT_BUT_NO_VALUE;
+		msg.append("tomcat.port enabled but did not have a value.");
+		if(recover) {		    
+		    port = httpPort = defHttpPort;
+		}
+	    } else { // No issus: using tomcat.port is the pre-https way.		
+		errorCode = ALL_CORRECT;
+		httpPort = port;
+	    }
+	}
+	else {
+	    legacyMode = false;
+
+	    protocol = props.getProperty("server.protocol");
+	    if(protocol == null || (!protocol.equals("http") && !protocol.equals("https"))) {
+		// tomcat.port was null AND now server.protocol is null or wrong. Something very wrong with the properties file
+		if(protocol == null) {		    
+		    errorCode = NO_PROTOCOL_OR_PORT;
+		    msg.append("server.protocol not set. And can't determine port.");
+		} else {
+		    errorCode = INVALID_PROTOCOL;
+		    msg.append("server.protocol property must be http or https, but is set to invalid value. And can't determine port.");
+		}
+
+		if(recover) {
+		    protocol = defProtocol;
+		    port = httpPort = defHttpPort;
+		}
+
+	    } else { // server.protocol was explicitly set and set to an acceptable value, try to find matching tomcat.port
+	    
+		port = props.getProperty("tomcat.port."+protocol); // tomcat.port.http or tomcat.port.https, depending on server.protocol.
+
+		// Handle cases where there's some inconsistency in the properties file between protocol and port.
+		// i.e. if server.protocol=http, then tomcat.port.http must be set too.
+		if(port == null || port.equals("")) {
+		    errorCode = INVALID_PROTOCOL;
+		    msg.append("server.protocol="+protocol+", but matching tomcat.port."+protocol+"not enabled or set.");
+		
+		    if(recover) {
+			protocol = defProtocol;
+			if(protocol.startsWith("https")) { // server.protocol=https yet tomcat.port.https not provided
+			    port = httpsPort = defHttpsPort; // use default https port to set
+			} else {
+			    port = httpPort = defHttpPort;
+			}
+		    }		    
+
+		} else { //tomcat.port.<protocol> property matching server.protocol is set, not checking if it's an int and a valid port, though
+		    errorCode = ALL_CORRECT;
+		    // port is set
+
+		    if(protocol.startsWith("https")) {
+			httpsPort = port;
+			httpPort = props.getProperty("tomcat.port.http"); // httpPort will remain null if tomcat.port.http not set
+		    } else { // protocol=http
+			httpPort = port;
+			httpsPort = props.getProperty("tomcat.port.https"); // httpsPort will remain null if tomcat.port.https not set
+		    }
+		}
+	    }
+	}	
+	
+	if(errorCode == ALL_CORRECT) { // then check any assigned ports are valid
+	    if(httpPort != null) {
+		try {
+		    Integer.parseInt(httpPort);
+		} catch(NumberFormatException nfe) {
+		    msg.append("\nInvalid port specified for over http: not numeric.");
+		    if(port == httpPort) {
+			errorCode = INVALID_PRIMARY_PORT;
+			if(recover) {
+			    port = httpPort = defHttpPort;
+			} else { // no recovery requested, so if port for protocol is non-numeric, consider it a 'fatal' error
+			    port = httpPort = httpsPort = null;
+			}
+		    } else { // secondary protocol's port is non-numeric, not fatal?
+			errorCode = SECONDARY_PORT_NON_NUMERIC;
+			if(recover) {
+			    msg.append("\nNot using this port");
+			} 
+			httpPort = null;			
+		    }
+		}
+	    }
+	
+	    if(httpsPort != null) {
+		try {
+		    Integer.parseInt(httpsPort);
+		} catch(NumberFormatException nfe) {
+		    msg.append("\nInvalid port specified for over https: not numeric.");
+		    if(port == httpsPort) {
+			errorCode = INVALID_PRIMARY_PORT;
+			if(recover) {
+			    port = httpsPort = defHttpsPort;
+			} else { // primary port affected and not asked to recover, treat as fatal
+			    port = httpsPort = httpPort = null;
+			}
+		    } else { // non primary port is invalid/non-numeric, not fatal
+			errorCode = SECONDARY_PORT_NON_NUMERIC;
+			if(recover) {
+			    msg.append("\nNot using this port");
+			}
+			httpsPort = null;
+		    }
+		}
+	    }
+	}
+	
+
+	if(recover) {
+	    msg.append("\nFalling back to port ").append(port).append(" and protocol ").append(protocol).append(".");
+	}
+	// else if(errorCode == ALL_CORRECT) {
+	//    msg.append("\nUsing port ").append(port).append(" and protocol ").append(protocol).append(".");
+	//} // else invalid property value(s) and we've not been asked to recover. msg alreay set.
+	
+	errorMsg = msg.toString();
+    }
+    
+}
