Merged 5.1.N (5.1.1) to HEAD (5.1)

113251 adavis: Merged 5.0.N (5.0.3) to 5.1.N (5.1.1)
      113194 abalmus: Merged DEV to 5.0.N (5.0.3)
         113149: MNT-13706 : Admin console unusable after we set any  busy port in Port Number Value for subsystem
            - Fixed issue that caused ACE-4194


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@113287 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Alan Davis
2015-09-29 06:00:22 +00:00
parent 410c24d2d1
commit 0ccc05a0c6
7 changed files with 171 additions and 71 deletions

View File

@@ -494,11 +494,13 @@
</bean> </bean>
<bean id="imapPortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker"> <bean id="imapPortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="IMAP" /> <constructor-arg value="IMAP" />
<constructor-arg value="imap.server.host" />
<constructor-arg value="false" /> <constructor-arg value="false" />
<constructor-arg value="true" /> <constructor-arg value="true" />
</bean> </bean>
<bean id="imapsPortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker"> <bean id="imapsPortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="IMAPS" /> <constructor-arg value="IMAPS" />
<constructor-arg value="imap.server.host" />
<constructor-arg value="false" /> <constructor-arg value="false" />
<constructor-arg value="true" /> <constructor-arg value="true" />
</bean> </bean>

View File

@@ -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.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.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.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.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.ports_in_use=The following ports chosen for {0} are already in use: {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 # License
system.license.msg.unknown=Unknown system.license.msg.unknown=Unknown

View File

@@ -321,9 +321,9 @@ public abstract class AbstractPropertyBackedBean implements PropertyBackedBean,
/** /**
* Check properties for invalid values using {@link SubsystemEarlyPropertyChecker}s * Check properties for invalid values using {@link SubsystemEarlyPropertyChecker}s
* @param properties * @param properties
* @throws InvalidPropertyValueException * @return The complete error message in case of exceptions or empty string otherwise
*/ */
public void performEarlyPropertyChecks(Map<String, String> properties) throws InvalidPropertyValueException public String performEarlyPropertyChecks(Map<String, String> properties)
{ {
if (properties != null && !properties.isEmpty() && earlyPropertyCheckers != null) if (properties != null && !properties.isEmpty() && earlyPropertyCheckers != null)
{ {
@@ -339,7 +339,16 @@ public abstract class AbstractPropertyBackedBean implements PropertyBackedBean,
if (propertyChecker != null) 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) catch (InvalidPropertyValueException ipve)
@@ -363,9 +372,11 @@ public abstract class AbstractPropertyBackedBean implements PropertyBackedBean,
allExceptionsMessages += ipve.getLocalizedMessage(); allExceptionsMessages += ipve.getLocalizedMessage();
} }
throw new InvalidPropertyValueException(allExceptionsMessages); return allExceptionsMessages;
} }
} }
return "";
} }
/** /**

View File

@@ -18,6 +18,7 @@
*/ */
package org.alfresco.repo.management.subsystems; package org.alfresco.repo.management.subsystems;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import org.alfresco.util.PortUtil; import org.alfresco.util.PortUtil;
import org.apache.commons.logging.Log; 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 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 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 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 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 static final Log logger = LogFactory.getLog(PortEarlyPropertyChecker.class);
private final String subsystemName; private final String subsystemName;
private final String requiredPairedPropertyName;
private final boolean hasMultiplePorts; private final boolean hasMultiplePorts;
private final boolean shouldCheckForBlockedPort; 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 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 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). * @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) 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.subsystemName = subsystemName;
this.requiredPairedPropertyName = requiredPairedPropertyName;
this.hasMultiplePorts = hasMultiplePorts; this.hasMultiplePorts = hasMultiplePorts;
this.shouldCheckForBlockedPort = shouldCheckForBlockedPort; this.shouldCheckForBlockedPort = shouldCheckForBlockedPort;
} }
@@ -62,16 +82,19 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
* Implementation of checkPropertyValue() method for port checking. * Implementation of checkPropertyValue() method for port checking.
* @param propertyName Name of the property. * @param propertyName Name of the property.
* @param propertyValue Port value; if this contains multiple ports they must be separated by ",". * @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. * @throws InvalidPropertyValueException Raised if any of the checks fail.
*/ */
@Override @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()) 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 try
{ {
if (!hasMultiplePorts) if (!hasMultiplePorts)
@@ -80,27 +103,38 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
if (portNumber < 1 || portNumber > 65535) if (portNumber < 1 || portNumber > 65535)
{ {
InvalidPropertyValueException portOutOfBoundsException = createLogAndThrowAnInvalidPropertyValueException(PORT_OUT_OF_BOUNDS_MESSAGE, new String[] { subsystemName, "" + portNumber });
new InvalidPropertyValueException(PORT_OUT_OF_BOUNDS_MESSAGE, new String[] { subsystemName, "" + portNumber });
if (logger.isErrorEnabled())
{
logger.error(portOutOfBoundsException.getLocalizedMessage());
} }
else if (shouldCheckForBlockedPort)
throw portOutOfBoundsException;
}
else if (shouldCheckForBlockedPort && !PortUtil.isPortFree(portNumber))
{ {
InvalidPropertyValueException portInUseException = try
new InvalidPropertyValueException(PORT_IN_USE_MESSAGE, new String[] { subsystemName, "" + portNumber });
if (logger.isErrorEnabled())
{ {
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 else
@@ -109,6 +143,7 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
String portsInUse = ""; String portsInUse = "";
String portsOutOfBounds = ""; String portsOutOfBounds = "";
String portsWithNetworkingErrors = "";
for (String portStr : ports) for (String portStr : ports)
{ {
@@ -116,21 +151,26 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
if (portNumber < 1 || portNumber > 65535) if (portNumber < 1 || portNumber > 65535)
{ {
if (!portsOutOfBounds.equals("")) portsOutOfBounds = appendToErrorString(portsOutOfBounds, ", ", "" + portNumber);
{
portsOutOfBounds += ", ";
} }
else if (shouldCheckForBlockedPort)
portsOutOfBounds += portNumber;
}
else if (shouldCheckForBlockedPort && !PortUtil.isPortFree(portNumber))
{ {
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("")) if (!portsOutOfBounds.equals(""))
{ {
String portsOutOfBoundsDisplayMessage = String portsOutOfBoundsDisplayMessage = resolveMessage(PORTS_OUT_OF_BOUNDS_MESSAGE, new String[] { subsystemName,
resolveMessage(PORTS_OUT_OF_BOUNDS_MESSAGE, new String[] { subsystemName, portsOutOfBounds }); portsOutOfBounds });
completeErrorDisplayMessage += portsOutOfBoundsDisplayMessage; completeErrorDisplayMessage += portsOutOfBoundsDisplayMessage;
} }
@@ -148,12 +188,15 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
{ {
String portsInUseDisplayMessage = resolveMessage(PORTS_IN_USE_MESSAGE, new String[] { subsystemName, portsInUse }); String portsInUseDisplayMessage = resolveMessage(PORTS_IN_USE_MESSAGE, new String[] { subsystemName, portsInUse });
if (!completeErrorDisplayMessage.equals("")) completeErrorDisplayMessage = appendToErrorString(completeErrorDisplayMessage, " | ", portsInUseDisplayMessage);
{
completeErrorDisplayMessage += " | ";
} }
completeErrorDisplayMessage += portsInUseDisplayMessage; if (!portsWithNetworkingErrors.equals(""))
{
String portsWithNetworkingErrorsDisplayMessage = resolveMessage(PORTS_WITH_NETWORKING_ERRORS_MESSAGE, new String[] {
subsystemName, portsWithNetworkingErrors });
completeErrorDisplayMessage = appendToErrorString(completeErrorDisplayMessage, " | ", portsWithNetworkingErrorsDisplayMessage);
} }
if (!completeErrorDisplayMessage.equals("")) if (!completeErrorDisplayMessage.equals(""))
@@ -169,16 +212,32 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
InvalidPropertyValueException unableToParseException = createLogAndThrowAnInvalidPropertyValueException(UNABLE_TO_PARSE_PORT_MESSAGE, new String[] { subsystemName, propertyValue });
new InvalidPropertyValueException(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()) if (logger.isErrorEnabled())
{ {
logger.error(unableToParseException.getLocalizedMessage()); logger.error(invalidPropertyValueException.getLocalizedMessage());
} }
throw unableToParseException; throw invalidPropertyValueException;
}
} }
private String resolveMessage(String messageId, Object[] params) private String resolveMessage(String messageId, Object[] params)
@@ -197,4 +256,10 @@ public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
return message; return message;
} }
@Override
public String getPairedPropertyName()
{
return requiredPairedPropertyName;
}
} }

View File

@@ -26,11 +26,20 @@ package org.alfresco.repo.management.subsystems;
*/ */
public interface SubsystemEarlyPropertyChecker 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. * Check if a subsystem property is valid.
* @param propertyName * @param propertyName
* @param propertyValue * @param propertyValue
* @param pairedPropertyValue
* @throws InvalidPropertyValueException * @throws InvalidPropertyValueException
*/ */
void checkPropertyValue(String propertyName, String propertyValue) throws InvalidPropertyValueException; void checkPropertyValue(String propertyName, String propertyValue, String pairedPropertyValue) throws InvalidPropertyValueException;
} }

View File

@@ -19,7 +19,9 @@
package org.alfresco.util; package org.alfresco.util;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket; import java.net.ServerSocket;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -35,20 +37,22 @@ public class PortUtil
/** /**
* Check if specified port is free. * Check if specified port is free.
* @param port Port number to check. * @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; ServerSocket serverSocket = null;
try try
{
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); serverSocket = new ServerSocket(port);
} }
catch (IOException ioe)
{
isFree = false;
} }
finally finally
{ {
@@ -67,7 +71,5 @@ public class PortUtil
} }
} }
} }
return isFree;
} }
} }

View File

@@ -20,19 +20,26 @@
</property> </property>
<property name="earlyPropertyCheckers"> <property name="earlyPropertyCheckers">
<map> <map>
<entry key="test1.port" value-ref="testPortEarlyChecker" /> <entry key="test1.port" value-ref="testPortEarlyChecker1" />
<entry key="test2.port" value-ref="testPortEarlyChecker" /> <entry key="test2.port" value-ref="testPortEarlyChecker1" />
<entry key="test3.port" value-ref="testPortEarlyChecker" /> <entry key="test3.port" value-ref="testPortEarlyChecker1" />
<entry key="test4.port" value-ref="testPortEarlyChecker" /> <entry key="test4.port" value-ref="testPortEarlyChecker1" />
<entry key="test5.port" value-ref="testPortEarlyChecker" /> <entry key="test5.port" value-ref="testPortEarlyChecker1" />
<entry key="test_with_host.port" value-ref="testPortEarlyChecker2" />
</map> </map>
</property> </property>
</bean> </bean>
<bean id="testPortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker"> <bean id="testPortEarlyChecker1" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="TestSubsystem" /> <constructor-arg value="TestSubsystem" />
<constructor-arg value="false" /> <constructor-arg value="false" />
<constructor-arg value="true" /> <constructor-arg value="true" />
</bean> </bean>
<bean id="testPortEarlyChecker2" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="TestSubsystem" />
<constructor-arg value="test.subsystem.host" />
<constructor-arg value="false" />
<constructor-arg value="true" />
</bean>
<bean id="sampleService" class="org.alfresco.repo.management.subsystems.test.SampleService"> <bean id="sampleService" class="org.alfresco.repo.management.subsystems.test.SampleService">
</bean> </bean>