Merged HEAD-BUG-FIX (5.1/Cloud) to HEAD (5.1/Cloud)

108207: Merged 5.0.N (5.0.3) to HEAD-BUG-FIX (5.1/Cloud)
      108196: Merged DEV to 5.0.N (5.0.3)
         108195: MNT-13706 : Admin console unusable after we set any  busy port in Port Number Value for subsystem
            - New and improved fix.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@108223 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Alan Davis
2015-07-14 07:03:41 +00:00
parent f13dc0a415
commit 1458c2dbcf
9 changed files with 1656 additions and 1133 deletions

View File

@@ -435,8 +435,19 @@
</bean> </bean>
<!-- System Administration Parameters --> <!-- System Administration Parameters -->
<bean id="sysAdmin" class="org.alfresco.repo.management.subsystems.ChildApplicationContextFactory" parent="abstractPropertyBackedBean"/> <bean id="sysAdmin" class="org.alfresco.repo.management.subsystems.ChildApplicationContextFactory" parent="abstractPropertyBackedBean">
<property name="earlyPropertyCheckers">
<map>
<entry key="share.port" value-ref="sharePortEarlyChecker" />
</map>
</property>
</bean>
<bean id="sharePortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="Share" />
<constructor-arg value="false" />
<constructor-arg value="false" />
</bean>
<!-- File Servers Subsystem --> <!-- File Servers Subsystem -->
<bean id="fileServers" class="org.alfresco.repo.management.subsystems.ChildApplicationContextFactory" parent="abstractPropertyBackedBean"> <bean id="fileServers" class="org.alfresco.repo.management.subsystems.ChildApplicationContextFactory" parent="abstractPropertyBackedBean">
<property name="autoStart"> <property name="autoStart">
@@ -464,6 +475,16 @@
<property name="persister"> <property name="persister">
<bean class="org.alfresco.config.AlfrescoPropertiesPersister"/> <bean class="org.alfresco.config.AlfrescoPropertiesPersister"/>
</property> </property>
<property name="earlyPropertyCheckers">
<map>
<entry key="ftp.port" value-ref="ftpPortEarlyChecker" />
</map>
</property>
</bean>
<bean id="ftpPortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="FTP" />
<constructor-arg value="false" />
<constructor-arg value="true" />
</bean> </bean>
<bean id="fileServerConfiguration" class="org.alfresco.repo.management.subsystems.SubsystemProxyFactory"> <bean id="fileServerConfiguration" class="org.alfresco.repo.management.subsystems.SubsystemProxyFactory">
@@ -510,6 +531,22 @@
</entry> </entry>
</map> </map>
</property> </property>
<property name="earlyPropertyCheckers">
<map>
<entry key="imap.server.port" value-ref="imapPortEarlyChecker" />
<entry key="imap.server.imaps.port" value-ref="imapsPortEarlyChecker" />
</map>
</property>
</bean>
<bean id="imapPortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="IMAP" />
<constructor-arg value="false" />
<constructor-arg value="true" />
</bean>
<bean id="imapsPortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="IMAPS" />
<constructor-arg value="false" />
<constructor-arg value="true" />
</bean> </bean>
<!-- Outbound Email subsystem --> <!-- Outbound Email subsystem -->
@@ -546,6 +583,16 @@
<property name="autoStart"> <property name="autoStart">
<value>true</value> <value>true</value>
</property> </property>
<property name="earlyPropertyCheckers">
<map>
<entry key="email.server.port" value-ref="smtpPortEarlyChecker" />
</map>
</property>
</bean>
<bean id="smtpPortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="SMTP" />
<constructor-arg value="false" />
<constructor-arg value="true" />
</bean> </bean>
<!-- Subscription Service subsystem --> <!-- Subscription Service subsystem -->

View File

@@ -995,6 +995,22 @@
<value>solr</value> <value>solr</value>
</list> </list>
</property> </property>
<property name="earlyPropertyCheckers">
<map>
<entry key="solr.port" value-ref="solrPortEarlyChecker" />
<entry key="solr.port.ssl" value-ref="solrSSLPortEarlyChecker" />
</map>
</property>
</bean>
<bean id="solrPortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="Solr" />
<constructor-arg value="false" />
<constructor-arg value="false" />
</bean>
<bean id="solrSSLPortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="Solr SSL" />
<constructor-arg value="false" />
<constructor-arg value="false" />
</bean> </bean>
<bean id="solr4" class="org.alfresco.repo.search.impl.solr.SolrChildApplicationContextFactory" parent="abstractPropertyBackedBean"> <bean id="solr4" class="org.alfresco.repo.search.impl.solr.SolrChildApplicationContextFactory" parent="abstractPropertyBackedBean">
@@ -1020,6 +1036,22 @@
<value>solr4</value> <value>solr4</value>
</list> </list>
</property> </property>
<property name="earlyPropertyCheckers">
<map>
<entry key="solr.port" value-ref="solr4PortEarlyChecker" />
<entry key="solr.port.ssl" value-ref="solr4SSLPortEarlyChecker" />
</map>
</property>
</bean>
<bean id="solr4PortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="Solr" />
<constructor-arg value="false" />
<constructor-arg value="false" />
</bean>
<bean id="solr4SSLPortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="Solr SSL" />
<constructor-arg value="false" />
<constructor-arg value="false" />
</bean> </bean>
<bean id="buildonly" class="org.alfresco.repo.management.subsystems.LuceneChildApplicationContextFactory" parent="abstractPropertyBackedBean"> <bean id="buildonly" class="org.alfresco.repo.management.subsystems.LuceneChildApplicationContextFactory" parent="abstractPropertyBackedBean">

View File

@@ -89,6 +89,14 @@ system.usage.err.limit_documents_exceeded=The allowable content limit of {0} has
system.usage.err.limit_license_expiring=The Alfresco license will expire in {0} days. system.usage.err.limit_license_expiring=The Alfresco license will expire in {0} days.
system.usage.err.limit_license_expired=The Alfresco license has expired. system.usage.err.limit_license_expired=The Alfresco license has expired.
# Subsystems error messages
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}.
# License # License
system.license.msg.unknown=Unknown system.license.msg.unknown=Unknown
system.license.msg.unlimited=Unlimited system.license.msg.unlimited=Unlimited

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.management.subsystems;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Custom AlfrescoRuntimeException for invalid property values.
*
* @author abalmus
*/
public class InvalidPropertyValueException extends AlfrescoRuntimeException
{
private static final long serialVersionUID = -6026809919380879547L;
/**
* Creates a new InvalidPropertyValueException with custom message ID.
* @param msgId
*/
public InvalidPropertyValueException(String msgId)
{
super(msgId);
}
/**
* Creates a new InvalidPropertyValueException with custom message ID and custom message parameters.
* @param msgId
* @param msgParams
*/
public InvalidPropertyValueException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
}
}

View File

@@ -0,0 +1,200 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.management.subsystems;
import java.util.Arrays;
import org.alfresco.util.PortUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* "Early" checker for Port property value (checks for "null/empty", "out-of-bounds", "unable-to-parse", "already-in-use" problems).
* Also see the implemented interface {@link SubsystemEarlyPropertyChecker}
*
* @author abalmus
*/
public class PortEarlyPropertyChecker implements SubsystemEarlyPropertyChecker
{
private static final String PORT_CANT_BE_EMPTY_MESSAGE = "system.portcheck.err.empty_port";
private static final String UNABLE_TO_PARSE_PORT_MESSAGE = "system.portcheck.err.parse_port";
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 PORTS_IN_USE_MESSAGE = "system.portcheck.err.ports_in_use";
private static final Log logger = LogFactory.getLog(PortEarlyPropertyChecker.class);
private final String subsystemName;
private final boolean hasMultiplePorts;
private final boolean shouldCheckForBlockedPort;
/**
* Create a new {@link PortEarlyPropertyChecker}.
* @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 = subsystemName;
this.hasMultiplePorts = hasMultiplePorts;
this.shouldCheckForBlockedPort = shouldCheckForBlockedPort;
}
/**
* 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 ",".
* @throws InvalidPropertyValueException Raised if any of the checks fail.
*/
@Override
public void checkPropertyValue(String propertyName, String propertyValue) throws InvalidPropertyValueException
{
if (propertyValue == null || propertyValue.isEmpty())
{
throw new InvalidPropertyValueException(PORT_CANT_BE_EMPTY_MESSAGE, new String[] { subsystemName });
}
try
{
if (!hasMultiplePorts)
{
int portNumber = Integer.parseInt(propertyValue.trim());
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;
}
else if (shouldCheckForBlockedPort && !PortUtil.isPortFree(portNumber))
{
InvalidPropertyValueException portInUseException =
new InvalidPropertyValueException(PORT_IN_USE_MESSAGE, new String[] { subsystemName, "" + portNumber });
if (logger.isErrorEnabled())
{
logger.error(portInUseException.getLocalizedMessage());
}
throw portInUseException;
}
}
else
{
String[] ports = propertyValue.trim().split(",");
String portsInUse = "";
String portsOutOfBounds = "";
for (String portStr : ports)
{
int portNumber = Integer.parseInt(portStr.trim());
if (portNumber < 1 || portNumber > 65535)
{
if (!portsOutOfBounds.equals(""))
{
portsOutOfBounds += ", ";
}
portsOutOfBounds += portNumber;
}
else if (shouldCheckForBlockedPort && !PortUtil.isPortFree(portNumber))
{
if (!portsInUse.equals(""))
{
portsInUse += ", ";
}
portsInUse += portNumber;
}
}
String completeErrorDisplayMessage = "";
if (!portsOutOfBounds.equals(""))
{
String portsOutOfBoundsDisplayMessage =
resolveMessage(PORTS_OUT_OF_BOUNDS_MESSAGE, new String[] { subsystemName, portsOutOfBounds });
completeErrorDisplayMessage += portsOutOfBoundsDisplayMessage;
}
if (!portsInUse.equals(""))
{
String portsInUseDisplayMessage = resolveMessage(PORTS_IN_USE_MESSAGE, new String[] { subsystemName, portsInUse });
if (!completeErrorDisplayMessage.equals(""))
{
completeErrorDisplayMessage += " | ";
}
completeErrorDisplayMessage += portsInUseDisplayMessage;
}
if (!completeErrorDisplayMessage.equals(""))
{
if (logger.isErrorEnabled())
{
logger.error(completeErrorDisplayMessage);
}
throw new InvalidPropertyValueException(completeErrorDisplayMessage);
}
}
}
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;
}
}
private String resolveMessage(String messageId, Object[] params)
{
String message = I18NUtil.getMessage(messageId, params);
if (message == null)
{
message = messageId;
if (params != null)
{
message += " - " + Arrays.toString(params);
}
}
return message;
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.management.subsystems;
/**
* Interface that describes an "early" checker for subsystem properties.
* Useful when we want to check that a property value is valid before stopping / starting the subsystem.
*
* @author abalmus
*/
public interface SubsystemEarlyPropertyChecker
{
/**
* Check if a subsystem property is valid.
* @param propertyName
* @param propertyValue
* @throws InvalidPropertyValueException
*/
void checkPropertyValue(String propertyName, String propertyValue) throws InvalidPropertyValueException;
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.util;
import java.io.IOException;
import java.net.ServerSocket;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Alfresco port-related utility functions.
*
* @author abalmus
*/
public class PortUtil
{
private static Log logger = LogFactory.getLog(PortUtil.class);
/**
* 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.
*/
public static boolean isPortFree(int port)
{
boolean isFree = true;
ServerSocket serverSocket = null;
try
{
serverSocket = new ServerSocket(port);
}
catch (IOException ioe)
{
isFree = false;
}
finally
{
if (serverSocket != null)
{
try
{
serverSocket.close();
}
catch (IOException ioe)
{
if (logger.isDebugEnabled())
{
logger.debug(ioe.toString());
}
}
}
}
return isFree;
}
}

View File

@@ -18,9 +18,29 @@
</entry> </entry>
</map> </map>
</property> </property>
<property name="earlyPropertyCheckers">
<map>
<entry key="test1.port" value-ref="testPortEarlyChecker" />
<entry key="test2.port" value-ref="testPortEarlyChecker" />
<entry key="test3.port" value-ref="testPortEarlyChecker" />
<entry key="test4.port" value-ref="testPortEarlyChecker" />
<entry key="test5.port" value-ref="testPortEarlyChecker" />
</map>
</property>
</bean>
<bean id="testPortEarlyChecker" class="org.alfresco.repo.management.subsystems.PortEarlyPropertyChecker">
<constructor-arg value="TestSubsystem" />
<constructor-arg value="false" />
<constructor-arg value="true" />
</bean> </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>
<bean id="testPortNumber" class="java.lang.Integer">
<constructor-arg>
<value>65534</value>
</constructor-arg>
</bean>
</beans> </beans>