source: main/trunk/greenstone3/src/java/org/greenstone/util/ProtocolPortProperties.java@ 32429

Last change on this file since 32429 was 32429, checked in by ak19, 6 years ago

solr should only be accessible locally (from localhost, specifically 127.0.0.1) which means over http. This conflicted with the previous design of the properties file for working with http and/or https. Now we have tomcat.port.https and localhost.port.http, both always set. In place of server.protocol that used to contain the default protocol, we now have server.protocols which can be set to a comma separated list of one or both of http and https. Drastic restructuring followed. I think I've tested all but https certification stuff.

File size: 8.3 KB
Line 
1/*
2 * ProtocolPortProperties.java
3 * Copyright (C) 2008 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.greenstone.util;
20
21import java.util.Properties;
22
23/*
24 * Utility class to set the protocol and port values from the Properties instance provided,
25 * which can be a Properties object loaded from either build.properties or global.properties
26 * Currently used by Server3.java, ServletRealmCheck, FedoraServiceProxy and solr java code
27 * GS2SolrSearch and SolrSearch.
28 * (Could perhaps also be used by GlobalProperties in future, if applicable.)
29 * Can adjust fallback behaviour in this one location to make them all work consistently.
30 *
31 * NOTE: although global.properties contains many additional programmatically set properties
32 * that could simplify this class, the fact that this class should work for both build.properties
33 * and global.properties means that this class will work only with the properties common to
34 * both property files.
35 */
36public class ProtocolPortProperties {
37
38 public static final int ALL_CORRECT = 0;
39 public static final int SECONDARY_PORT_NON_NUMERIC = 1;
40 public static final int INVALID_PRIMARY_PORT = 2;
41 public static final int NO_PROTOCOL = 3;
42 public static final int INVALID_PROTOCOL = 4;
43 public static final int NO_HTTP_PORT = 5;
44 public static final int NO_HTTPS_PORT = 6;
45
46 private static final String FALLBACK_PROTOCOL = "http";
47 private static final String FALLBACK_HTTP_PORT = "8383";
48 private static final String FALLBACK_HTTPS_PORT = "8443";
49
50 private String protocol;
51 private String port;
52 private String httpPort;
53 private String httpsPort;
54 //private int portNum = -1; // port that matches protocol as int
55
56 private String errorMsg;
57 private int errorCode = ALL_CORRECT;
58
59 private boolean httpRestrictedToLocal = true;
60 private boolean supportsHttps = false;
61 private String defaultPortPropertyName = "localhost.port.http";
62
63 // default protocol if multiple supported
64 public String getProtocol() { return protocol; }
65 // default port (port for default protocol)
66 public String getPort() { return port; }
67
68 // httpPort is always set, but http may or may not be public
69 public String getHttpPort() { return httpPort; }
70 // httpsPort is null if https not supported
71 public String getHttpsPort() { return httpsPort; }
72 public int getPortNum() { return Integer.parseInt(port); }
73
74 // http is always available locally (over 127.0.0.1). But http may or may not be public.
75 // Returns true if public http support requested
76 public boolean supportsHttp() { return !httpRestrictedToLocal; }
77 // true if https is supported
78 public boolean supportsHttps() { return supportsHttps; }
79
80 // used by Server3.java to know the name of the port property to load
81 public String getDefaultPortPropertyName() { return defaultPortPropertyName; }
82
83 public String getErrorMsg() { return errorMsg; }
84 public int getErrorCode() { return errorCode; }
85
86 public boolean hadError() { return errorCode != ALL_CORRECT; }
87
88 // Use 127.0.0.1 instead of localhost since localhost is unsafe (can be mapped
89 // to something other than 127.0.0.1). See https://letsencrypt.org/docs/certificates-for-localhost/
90 public String getLocalHttpBaseAddress() {
91 // httpPort is set during the constructor,
92 // so knowing httpPort, we can set the internal/local access http URL:
93 String portSuffix = httpPort.equals("80") ? "" : (":"+httpPort);
94 return "http://127.0.0.1"+portSuffix;
95
96 }
97
98 // Constructor that will throw an Exception on ports/protocol configuration error or inconsistency
99 public ProtocolPortProperties(Properties props) throws Exception {
100 this(props, false);
101 }
102
103 // If param recover is true, will attempt to fallback to sane values for protocol and ports.
104 // You can still check for error by calling hadError(), getErrorMsg() and getErrorCode().
105 // If param recover is false, will throw an Exception on bad ports/protocol configuration
106 // and the error message is available as the exception description.
107 public ProtocolPortProperties(Properties props, boolean recover) throws Exception
108 {
109 StringBuffer msg = new StringBuffer();
110
111 httpPort = props.getProperty("localhost.port.http");
112 if(httpPort == null || httpPort.equals("")) {
113 errorCode = NO_HTTP_PORT;
114 msg.append("compulsory property localhost.port.http has no value (must be set to a valid port number not already in use).");
115 httpPort = FALLBACK_HTTP_PORT;
116 }
117
118 String supportedProtocols = props.getProperty("server.protocols");
119 if(supportedProtocols == null || supportedProtocols.equals("")) {
120 errorCode = NO_PROTOCOL;
121 msg.append("server.protocols not set.");
122 protocol = FALLBACK_PROTOCOL; // fallback to http as default (and sole) protocol
123 port = httpPort; // set default port to httpPort
124 }
125 else { // supportedProtocols was assigned something
126
127 if(!supportedProtocols.contains("http")) {
128 errorCode = INVALID_PROTOCOL;
129 msg.append("server.protocols must contain http or https, or both (in order of preference) separated by commas.");
130 protocol = FALLBACK_PROTOCOL;
131 port = httpPort;
132 }
133
134 // set available protocols with their ports
135 if(supportedProtocols.contains("https")) {
136 supportsHttps = true;
137 httpsPort = props.getProperty("tomcat.port.https");
138 if(httpsPort == null || httpsPort.equals("")) {
139 errorCode = NO_HTTPS_PORT;
140 msg.append("server.protocols includes https but property tomcat.port.https has no value (must be set to a valid port number not already in use).");
141 httpsPort = FALLBACK_HTTPS_PORT;
142 }
143 }
144 if(supportedProtocols.matches("http(,|\\s+|$)")) {
145 httpRestrictedToLocal = false;
146 }
147
148 // set default protocol and default port: the first protocol in the supportedProtocols list
149 if(supportedProtocols.matches("^[,\\s]*https")) {
150 protocol = "https";
151 port = httpsPort;
152 } else {
153 protocol = "http";
154 port = httpPort;
155 }
156 }
157
158 if(!recover && errorCode == ALL_CORRECT) { // then check any assigned ports are valid
159 if(httpPort != null) {
160 try {
161 Integer.parseInt(httpPort);
162 } catch(NumberFormatException nfe) {
163 msg.append("\nInvalid localhost.port.http specified: must be numeric.");
164 if(port == httpPort) {
165 errorCode = INVALID_PRIMARY_PORT;
166 port = httpPort = FALLBACK_HTTP_PORT; // recovery values that can work with default protocol
167 } else { // secondary protocol's port is non-numeric, not fatal in recovery mode
168 errorCode = SECONDARY_PORT_NON_NUMERIC;
169 httpPort = null;
170 if(recover) msg.append("\nNot using this port");
171 }
172 }
173 }
174
175 if(httpsPort != null) {
176 try {
177 Integer.parseInt(httpsPort);
178 } catch(NumberFormatException nfe) {
179 msg.append("\nInvalid port specified for over https (tomcat.port.https): must be numeric.");
180 if(port == httpsPort) {
181 errorCode = INVALID_PRIMARY_PORT;
182 port = httpsPort = FALLBACK_HTTPS_PORT; // recovery values that work with default protocol
183 } else { // non primary port is invalid/non-numeric, not fatal in recovery mode
184 errorCode = SECONDARY_PORT_NON_NUMERIC;
185 httpsPort = null;
186 if(recover) msg.append("\nNot using this port");
187 }
188 }
189 }
190 }
191
192 // if the default port is the httpsPort, then modify the defaultPortPropertyName to match
193 // (else it will remain at the property name for the http port)
194 if(port == httpsPort) {
195 defaultPortPropertyName = "tomcat.port.https";
196 }
197
198 if(recover) {
199 msg.append("\nFalling back to port ").append(port).append(" and protocol ").append(protocol).append(".");
200 }
201
202 errorMsg = msg.toString();
203
204 if(!recover && errorCode != ALL_CORRECT) {
205 throw new Exception(errorMsg);
206 }
207 }
208
209}
Note: See TracBrowser for help on using the repository browser.