diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml
index f3f7df4c55..8bbdd6869c 100644
--- a/config/alfresco/bootstrap-context.xml
+++ b/config/alfresco/bootstrap-context.xml
@@ -494,11 +494,13 @@
+
+
diff --git a/config/alfresco/messages/system-messages.properties b/config/alfresco/messages/system-messages.properties
index 6542beb8ba..66fc98b023 100644
--- a/config/alfresco/messages/system-messages.properties
+++ b/config/alfresco/messages/system-messages.properties
@@ -94,8 +94,12 @@ system.portcheck.err.empty_port=The value for {0} port property cannot be empty.
system.portcheck.err.parse_port=Unable to parse value for {0} port property: {1}.
system.portcheck.err.port_out_of_bounds=The port chosen for {0} is outside the required range (1, 65535): {1}.
system.portcheck.err.ports_out_of_bounds=The following ports chosen for {0} are outside the required range (1, 65535): {1}.
-system.portcheck.err.port_in_use=The port chosen for {0} is already in use: {1}.
-system.portcheck.err.ports_in_use=The following ports chosen for {0} are already in use: {1}.
+system.portcheck.err.port_in_use=The port chosen for {0} is already in use or you don''t have permission to use it: {1}.
+system.portcheck.err.host_port_in_use=The address chosen for {0} is already in use or you don''t have permission: {1}:{2}.
+system.portcheck.err.ports_in_use=The following ports chosen for {0} are already in use or you don''t have permission to use them: {1}.
+system.portcheck.err.unknown_or_wrong_host=The hostname chosen for {0} is unknown or misspelled: {1}.
+system.portcheck.err.networking_error=In subsystem {0} a networking error was encountered: {1}.
+system.portcheck.err.ports_with_networking_errors=The following ports chosen for {0} have networking errors: {1}.
# License
system.license.msg.unknown=Unknown
diff --git a/source/java/org/alfresco/repo/management/subsystems/AbstractPropertyBackedBean.java b/source/java/org/alfresco/repo/management/subsystems/AbstractPropertyBackedBean.java
index db4ecb0ee8..e053d003e5 100644
--- a/source/java/org/alfresco/repo/management/subsystems/AbstractPropertyBackedBean.java
+++ b/source/java/org/alfresco/repo/management/subsystems/AbstractPropertyBackedBean.java
@@ -321,9 +321,9 @@ public abstract class AbstractPropertyBackedBean implements PropertyBackedBean,
/**
* Check properties for invalid values using {@link SubsystemEarlyPropertyChecker}s
* @param properties
- * @throws InvalidPropertyValueException
+ * @return The complete error message in case of exceptions or empty string otherwise
*/
- public void performEarlyPropertyChecks(Map properties) throws InvalidPropertyValueException
+ public String performEarlyPropertyChecks(Map properties)
{
if (properties != null && !properties.isEmpty() && earlyPropertyCheckers != null)
{
@@ -339,7 +339,16 @@ public abstract class AbstractPropertyBackedBean implements PropertyBackedBean,
if (propertyChecker != null)
{
- propertyChecker.checkPropertyValue(property, properties.get(property));
+ if (propertyChecker.getPairedPropertyName() != null
+ && properties.containsKey(propertyChecker.getPairedPropertyName()))
+ {
+ propertyChecker.checkPropertyValue(property, properties.get(property),
+ properties.get(propertyChecker.getPairedPropertyName()));
+ }
+ else
+ {
+ propertyChecker.checkPropertyValue(property, properties.get(property), null);
+ }
}
}
catch (InvalidPropertyValueException ipve)
@@ -363,9 +372,11 @@ public abstract class AbstractPropertyBackedBean implements PropertyBackedBean,
allExceptionsMessages += ipve.getLocalizedMessage();
}
- throw new InvalidPropertyValueException(allExceptionsMessages);
+ return allExceptionsMessages;
}
}
+
+ return "";
}
/**
diff --git a/source/java/org/alfresco/repo/management/subsystems/PortEarlyPropertyChecker.java b/source/java/org/alfresco/repo/management/subsystems/PortEarlyPropertyChecker.java
index 69904797c2..e05580e633 100644
--- a/source/java/org/alfresco/repo/management/subsystems/PortEarlyPropertyChecker.java
+++ b/source/java/org/alfresco/repo/management/subsystems/PortEarlyPropertyChecker.java
@@ -18,6 +18,7 @@
*/
package org.alfresco.repo.management.subsystems;
+import java.io.IOException;
import java.util.Arrays;
import org.alfresco.util.PortUtil;
import org.apache.commons.logging.Log;
@@ -37,23 +38,42 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
private static final String PORT_OUT_OF_BOUNDS_MESSAGE = "system.portcheck.err.port_out_of_bounds";
private static final String PORTS_OUT_OF_BOUNDS_MESSAGE = "system.portcheck.err.ports_out_of_bounds";
private static final String PORT_IN_USE_MESSAGE = "system.portcheck.err.port_in_use";
+ private static final String HOST_PORT_IN_USE_MESSAGE = "system.portcheck.err.host_port_in_use";
private static final String PORTS_IN_USE_MESSAGE = "system.portcheck.err.ports_in_use";
-
+ private static final String UNKNOWN_OR_WRONG_HOST_MESSAGE = "system.portcheck.err.unknown_or_wrong_host";
+ private static final String NETWORKING_ERROR_MESSAGE = "system.portcheck.err.networking_error";
+ private static final String PORTS_WITH_NETWORKING_ERRORS_MESSAGE = "system.portcheck.err.ports_with_networking_errors";
+
private static final Log logger = LogFactory.getLog(PortEarlyPropertyChecker.class);
private final String subsystemName;
+ private final String requiredPairedPropertyName;
+
private final boolean hasMultiplePorts;
private final boolean shouldCheckForBlockedPort;
/**
- * Create a new {@link PortEarlyPropertyChecker}.
+ * Create a new {@link PortEarlyPropertyChecker} w/o a paired property name.
* @param subsystemName Name of the subsystem; used for custom error messages.
* @param hasMultiplePorts Specify if the property value that will be checked is a list of ports (they must be separated by ",").
* @param shouldCheckForBlockedPort Enable/disable checking for port-already-in-use (i.e.: disable this for remote ports).
*/
public PortEarlyPropertyChecker(String subsystemName, boolean hasMultiplePorts, boolean shouldCheckForBlockedPort)
+ {
+ this(subsystemName, null, hasMultiplePorts, shouldCheckForBlockedPort);
+ }
+
+ /**
+ * Create a new {@link PortEarlyPropertyChecker}.
+ * @param subsystemName Name of the subsystem; used for custom error messages.
+ * @param requiredPairedPropertyName Name of the required paired property (see {@link SubsystemEarlyPropertyChecker#getPairedPropertyName()}).
+ * @param hasMultiplePorts Specify if the property value that will be checked is a list of ports (they must be separated by ",").
+ * @param shouldCheckForBlockedPort Enable/disable checking for port-already-in-use (i.e.: disable this for remote ports).
+ */
+ public PortEarlyPropertyChecker(String subsystemName, String requiredPairedPropertyName, boolean hasMultiplePorts, boolean shouldCheckForBlockedPort)
{
this.subsystemName = subsystemName;
+ this.requiredPairedPropertyName = requiredPairedPropertyName;
this.hasMultiplePorts = hasMultiplePorts;
this.shouldCheckForBlockedPort = shouldCheckForBlockedPort;
}
@@ -62,16 +82,19 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
* Implementation of checkPropertyValue() method for port checking.
* @param propertyName Name of the property.
* @param propertyValue Port value; if this contains multiple ports they must be separated by ",".
+ * @param pairedPropertyValue - Value of the paired property
* @throws InvalidPropertyValueException Raised if any of the checks fail.
*/
@Override
- public void checkPropertyValue(String propertyName, String propertyValue) throws InvalidPropertyValueException
+ public void checkPropertyValue(String propertyName, String propertyValue, String pairedPropertyValue) throws InvalidPropertyValueException
{
if (propertyValue == null || propertyValue.isEmpty())
{
- throw new InvalidPropertyValueException(PORT_CANT_BE_EMPTY_MESSAGE, new String[] { subsystemName });
+ createLogAndThrowAnInvalidPropertyValueException(PORT_CANT_BE_EMPTY_MESSAGE, new String[] { subsystemName });
}
+ String host = pairedPropertyValue;
+
try
{
if (!hasMultiplePorts)
@@ -80,27 +103,38 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
if (portNumber < 1 || portNumber > 65535)
{
- InvalidPropertyValueException portOutOfBoundsException =
- new InvalidPropertyValueException(PORT_OUT_OF_BOUNDS_MESSAGE, new String[] { subsystemName, "" + portNumber });
-
- if (logger.isErrorEnabled())
- {
- logger.error(portOutOfBoundsException.getLocalizedMessage());
- }
-
- throw portOutOfBoundsException;
+ createLogAndThrowAnInvalidPropertyValueException(PORT_OUT_OF_BOUNDS_MESSAGE, new String[] { subsystemName, "" + portNumber });
}
- else if (shouldCheckForBlockedPort && !PortUtil.isPortFree(portNumber))
+ else if (shouldCheckForBlockedPort)
{
- InvalidPropertyValueException portInUseException =
- new InvalidPropertyValueException(PORT_IN_USE_MESSAGE, new String[] { subsystemName, "" + portNumber });
-
- if (logger.isErrorEnabled())
+ try
{
- logger.error(portInUseException.getLocalizedMessage());
+ PortUtil.checkPort(portNumber, host);
+ }
+ catch (IOException ioe)
+ {
+ if (ioe instanceof java.net.BindException)
+ {
+ if (host == null || "0.0.0.0".equals(host))
+ {
+ createLogAndThrowAnInvalidPropertyValueException(PORT_IN_USE_MESSAGE, new String[] { subsystemName, "" + portNumber });
+ }
+ else
+ {
+ createLogAndThrowAnInvalidPropertyValueException(HOST_PORT_IN_USE_MESSAGE, new String[] { subsystemName, host,
+ "" + portNumber });
+ }
+ }
+ else if (host != null && ioe instanceof java.net.UnknownHostException)
+ {
+ createLogAndThrowAnInvalidPropertyValueException(UNKNOWN_OR_WRONG_HOST_MESSAGE, new String[] { subsystemName, "" + host });
+ }
+ else
+ {
+ createLogAndThrowAnInvalidPropertyValueException(NETWORKING_ERROR_MESSAGE,
+ new String[] { subsystemName, ioe.getLocalizedMessage() });
+ }
}
-
- throw portInUseException;
}
}
else
@@ -109,6 +143,7 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
String portsInUse = "";
String portsOutOfBounds = "";
+ String portsWithNetworkingErrors = "";
for (String portStr : ports)
{
@@ -116,21 +151,26 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
if (portNumber < 1 || portNumber > 65535)
{
- if (!portsOutOfBounds.equals(""))
- {
- portsOutOfBounds += ", ";
- }
-
- portsOutOfBounds += portNumber;
+ portsOutOfBounds = appendToErrorString(portsOutOfBounds, ", ", "" + portNumber);
}
- else if (shouldCheckForBlockedPort && !PortUtil.isPortFree(portNumber))
+ else if (shouldCheckForBlockedPort)
{
- if (!portsInUse.equals(""))
+ try
{
- portsInUse += ", ";
+ PortUtil.checkPort(portNumber, host);
+ }
+ catch (IOException ioe)
+ {
+ if (ioe instanceof java.net.BindException)
+ {
+ portsInUse = appendToErrorString(portsInUse, ", ", "" + portNumber);
+ }
+ else
+ {
+ portsWithNetworkingErrors = appendToErrorString(portsWithNetworkingErrors, " ; ",
+ portNumber + ": " + ioe.getLocalizedMessage());
+ }
}
-
- portsInUse += portNumber;
}
}
@@ -138,8 +178,8 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
if (!portsOutOfBounds.equals(""))
{
- String portsOutOfBoundsDisplayMessage =
- resolveMessage(PORTS_OUT_OF_BOUNDS_MESSAGE, new String[] { subsystemName, portsOutOfBounds });
+ String portsOutOfBoundsDisplayMessage = resolveMessage(PORTS_OUT_OF_BOUNDS_MESSAGE, new String[] { subsystemName,
+ portsOutOfBounds });
completeErrorDisplayMessage += portsOutOfBoundsDisplayMessage;
}
@@ -148,12 +188,15 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
{
String portsInUseDisplayMessage = resolveMessage(PORTS_IN_USE_MESSAGE, new String[] { subsystemName, portsInUse });
- if (!completeErrorDisplayMessage.equals(""))
- {
- completeErrorDisplayMessage += " | ";
- }
+ completeErrorDisplayMessage = appendToErrorString(completeErrorDisplayMessage, " | ", portsInUseDisplayMessage);
+ }
- completeErrorDisplayMessage += portsInUseDisplayMessage;
+ if (!portsWithNetworkingErrors.equals(""))
+ {
+ String portsWithNetworkingErrorsDisplayMessage = resolveMessage(PORTS_WITH_NETWORKING_ERRORS_MESSAGE, new String[] {
+ subsystemName, portsWithNetworkingErrors });
+
+ completeErrorDisplayMessage = appendToErrorString(completeErrorDisplayMessage, " | ", portsWithNetworkingErrorsDisplayMessage);
}
if (!completeErrorDisplayMessage.equals(""))
@@ -169,18 +212,34 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
}
catch (NumberFormatException nfe)
{
- InvalidPropertyValueException unableToParseException =
- new InvalidPropertyValueException(UNABLE_TO_PARSE_PORT_MESSAGE, new String[] { subsystemName, propertyValue });
-
- if (logger.isErrorEnabled())
- {
- logger.error(unableToParseException.getLocalizedMessage());
- }
-
- throw unableToParseException;
+ createLogAndThrowAnInvalidPropertyValueException(UNABLE_TO_PARSE_PORT_MESSAGE, new String[] { subsystemName, propertyValue });
}
}
+ private String appendToErrorString(String stringToAppendTo, String separator, String valueToAppend)
+ {
+ if (!stringToAppendTo.equals(""))
+ {
+ stringToAppendTo = stringToAppendTo + separator;
+ }
+
+ stringToAppendTo = stringToAppendTo + valueToAppend;
+
+ return stringToAppendTo;
+ }
+
+ private void createLogAndThrowAnInvalidPropertyValueException(String message, String[] messageParams)
+ {
+ InvalidPropertyValueException invalidPropertyValueException = new InvalidPropertyValueException(message, messageParams);
+
+ if (logger.isErrorEnabled())
+ {
+ logger.error(invalidPropertyValueException.getLocalizedMessage());
+ }
+
+ throw invalidPropertyValueException;
+ }
+
private String resolveMessage(String messageId, Object[] params)
{
String message = I18NUtil.getMessage(messageId, params);
@@ -197,4 +256,10 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
return message;
}
+
+ @Override
+ public String getPairedPropertyName()
+ {
+ return requiredPairedPropertyName;
+ }
}
diff --git a/source/java/org/alfresco/repo/management/subsystems/SubsystemEarlyPropertyChecker.java b/source/java/org/alfresco/repo/management/subsystems/SubsystemEarlyPropertyChecker.java
index 3490fc1a4c..26a812b8b7 100644
--- a/source/java/org/alfresco/repo/management/subsystems/SubsystemEarlyPropertyChecker.java
+++ b/source/java/org/alfresco/repo/management/subsystems/SubsystemEarlyPropertyChecker.java
@@ -26,11 +26,20 @@ package org.alfresco.repo.management.subsystems;
*/
public interface SubsystemEarlyPropertyChecker
{
+ /**
+ * Get the (optional) paired property name (e.g., if we want to check a port
+ * number we might want to do that together with a specific local address).
+ *
+ * @return The paired property name.
+ */
+ String getPairedPropertyName();
+
/**
* Check if a subsystem property is valid.
* @param propertyName
* @param propertyValue
+ * @param pairedPropertyValue
* @throws InvalidPropertyValueException
*/
- void checkPropertyValue(String propertyName, String propertyValue) throws InvalidPropertyValueException;
+ void checkPropertyValue(String propertyName, String propertyValue, String pairedPropertyValue) throws InvalidPropertyValueException;
}
diff --git a/source/java/org/alfresco/util/PortUtil.java b/source/java/org/alfresco/util/PortUtil.java
index 2d84a561dd..dd09902914 100644
--- a/source/java/org/alfresco/util/PortUtil.java
+++ b/source/java/org/alfresco/util/PortUtil.java
@@ -19,7 +19,9 @@
package org.alfresco.util;
import java.io.IOException;
+import java.net.InetAddress;
import java.net.ServerSocket;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -35,20 +37,22 @@ public class PortUtil
/**
* Check if specified port is free.
* @param port Port number to check.
- * @return true if port is free or false if it's already in use.
+ * @param host A local address to bind to; if null, "" or "0.0.0.0" then all local addresses will be considered.
*/
- public static boolean isPortFree(int port)
+ public static void checkPort(int port, String host) throws IOException
{
- boolean isFree = true;
ServerSocket serverSocket = null;
try
{
- serverSocket = new ServerSocket(port);
- }
- catch (IOException ioe)
- {
- isFree = false;
+ if (host != null && !host.equals("") && !"0.0.0.0".equals(host.trim()))
+ {
+ serverSocket = new ServerSocket(port, 0, InetAddress.getByName(host.trim()));
+ }
+ else
+ {
+ serverSocket = new ServerSocket(port);
+ }
}
finally
{
@@ -67,7 +71,5 @@ public class PortUtil
}
}
}
-
- return isFree;
}
}
diff --git a/source/test-resources/subsystem-test-context.xml b/source/test-resources/subsystem-test-context.xml
index 40c90c43cc..823ab03d50 100644
--- a/source/test-resources/subsystem-test-context.xml
+++ b/source/test-resources/subsystem-test-context.xml
@@ -20,19 +20,26 @@
-
+
+
+
+
+
+
+