This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/10.1.x by this push:
     new 4cbe76f58a Code review fixes
4cbe76f58a is described below

commit 4cbe76f58a1ec9426310ff5d9228d1b6868b42d2
Author: remm <[email protected]>
AuthorDate: Thu Jun 11 16:57:36 2026 +0200

    Code review fixes
    
    Switch to thread safe structures in SimpleTcpCluster (just in case).
    Change check for WarWatcher.
    Better accept() check for ClusterListener.
---
 .../catalina/core/ApplicationFilterFactory.java    |  4 +++
 .../core/ApplicationFilterRegistration.java        | 18 ++++++++++----
 .../core/ApplicationServletRegistration.java       |  7 ++++--
 .../catalina/core/DefaultInstanceManager.java      |  2 +-
 .../apache/catalina/core/LocalStrings.properties   |  6 +++++
 .../catalina/core/NamingContextListener.java       |  3 ++-
 .../core/PropertiesRoleMappingListener.java        |  2 +-
 .../org/apache/catalina/filters/ExpiresFilter.java | 11 +++-----
 .../apache/catalina/filters/RateLimitFilter.java   | 12 ++++++---
 .../catalina/filters/RestCsrfPreventionFilter.java |  3 ++-
 java/org/apache/catalina/ha/ClusterListener.java   |  5 +++-
 java/org/apache/catalina/ha/ClusterValve.java      |  2 +-
 .../apache/catalina/ha/backend/CollectedInfo.java  |  9 +++++--
 .../catalina/ha/backend/MultiCastSender.java       |  2 +-
 java/org/apache/catalina/ha/backend/TcpSender.java | 14 ++++++-----
 .../catalina/ha/context/ReplicatedContext.java     |  4 +--
 .../apache/catalina/ha/deploy/FarmWarDeployer.java |  4 +--
 java/org/apache/catalina/ha/deploy/WarWatcher.java | 10 ++++----
 .../apache/catalina/ha/session/BackupManager.java  |  6 ++---
 .../apache/catalina/ha/session/DeltaManager.java   | 29 ++++++++++------------
 .../apache/catalina/ha/tcp/ReplicationValve.java   |  9 +------
 .../apache/catalina/ha/tcp/SimpleTcpCluster.java   |  9 +++----
 22 files changed, 96 insertions(+), 75 deletions(-)

diff --git a/java/org/apache/catalina/core/ApplicationFilterFactory.java 
b/java/org/apache/catalina/core/ApplicationFilterFactory.java
index 40c7627779..dc05ebdd04 100644
--- a/java/org/apache/catalina/core/ApplicationFilterFactory.java
+++ b/java/org/apache/catalina/core/ApplicationFilterFactory.java
@@ -92,6 +92,10 @@ public final class ApplicationFilterFactory {
 
         // Acquire the information we will need to match filter mappings
         DispatcherType dispatcher = (DispatcherType) 
request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);
+        if (dispatcher == null) {
+            dispatcher = DispatcherType.REQUEST;
+            
log.warn(sm.getString("applicationFilterFactory.noDispatcherType"));
+        }
 
         String requestPath = FilterUtil.getRequestPath(request);
 
diff --git a/java/org/apache/catalina/core/ApplicationFilterRegistration.java 
b/java/org/apache/catalina/core/ApplicationFilterRegistration.java
index 5616d612c4..29aeae0ec5 100644
--- a/java/org/apache/catalina/core/ApplicationFilterRegistration.java
+++ b/java/org/apache/catalina/core/ApplicationFilterRegistration.java
@@ -71,8 +71,11 @@ public class ApplicationFilterRegistration implements 
FilterRegistration.Dynamic
             }
         }
 
-        if (servletNames != null) {
+        if (servletNames != null && servletNames.length > 0) {
             for (String servletName : servletNames) {
+                if (servletName == null) {
+                    throw new 
IllegalArgumentException(sm.getString("applicationFilterRegistration.nullServletName"));
+                }
                 filterMap.addServletName(servletName);
             }
 
@@ -81,8 +84,9 @@ public class ApplicationFilterRegistration implements 
FilterRegistration.Dynamic
             } else {
                 context.addFilterMapBefore(filterMap);
             }
+        } else {
+            throw new 
IllegalArgumentException(sm.getString("applicationFilterRegistration.nullServletName"));
         }
-        // else error?
     }
 
     @Override
@@ -99,9 +103,12 @@ public class ApplicationFilterRegistration implements 
FilterRegistration.Dynamic
             }
         }
 
-        if (urlPatterns != null) {
-            // % decoded (if necessary) using UTF-8
+        if (urlPatterns != null && urlPatterns.length > 0) {
             for (String urlPattern : urlPatterns) {
+                if (urlPattern == null) {
+                    throw new 
IllegalArgumentException(sm.getString("applicationFilterRegistration.nullUrlPattern"));
+                }
+                // URL decoded using UTF-8 in addURLPattern
                 filterMap.addURLPattern(urlPattern);
             }
 
@@ -110,8 +117,9 @@ public class ApplicationFilterRegistration implements 
FilterRegistration.Dynamic
             } else {
                 context.addFilterMapBefore(filterMap);
             }
+        } else {
+            throw new 
IllegalArgumentException(sm.getString("applicationFilterRegistration.nullUrlPattern"));
         }
-        // else error?
 
     }
 
diff --git a/java/org/apache/catalina/core/ApplicationServletRegistration.java 
b/java/org/apache/catalina/core/ApplicationServletRegistration.java
index 43ee2e953a..3b758efabb 100644
--- a/java/org/apache/catalina/core/ApplicationServletRegistration.java
+++ b/java/org/apache/catalina/core/ApplicationServletRegistration.java
@@ -93,7 +93,7 @@ public class ApplicationServletRegistration implements 
ServletRegistration.Dynam
     public boolean setInitParameter(String name, String value) {
         if (name == null || value == null) {
             throw new IllegalArgumentException(
-                    
sm.getString("applicationFilterRegistration.nullInitParam", name, value));
+                    
sm.getString("applicationServletRegistration.nullInitParam", name, value));
         }
         if (getInitParameter(name) != null) {
             return false;
@@ -112,7 +112,7 @@ public class ApplicationServletRegistration implements 
ServletRegistration.Dynam
         for (Map.Entry<String,String> entry : initParameters.entrySet()) {
             if (entry.getKey() == null || entry.getValue() == null) {
                 throw new IllegalArgumentException(
-                        
sm.getString("applicationFilterRegistration.nullInitParams", entry.getKey(), 
entry.getValue()));
+                        
sm.getString("applicationServletRegistration.nullInitParams", entry.getKey(), 
entry.getValue()));
             }
             if (getInitParameter(entry.getKey()) != null) {
                 conflicts.add(entry.getKey());
@@ -177,6 +177,9 @@ public class ApplicationServletRegistration implements 
ServletRegistration.Dynam
 
         String[] decodedUrlPatterns = new String[urlPatterns.length];
         for (int i = 0; i < urlPatterns.length; i++) {
+            if (urlPatterns[i] == null) {
+                throw new 
IllegalArgumentException(sm.getString("applicationServletRegistration.nullUrlPattern"));
+            }
             decodedUrlPatterns[i] = UDecoder.URLDecode(urlPatterns[i], 
StandardCharsets.UTF_8);
         }
 
diff --git a/java/org/apache/catalina/core/DefaultInstanceManager.java 
b/java/org/apache/catalina/core/DefaultInstanceManager.java
index 3798704810..36a00aa107 100644
--- a/java/org/apache/catalina/core/DefaultInstanceManager.java
+++ b/java/org/apache/catalina/core/DefaultInstanceManager.java
@@ -276,7 +276,7 @@ public class DefaultInstanceManager implements 
InstanceManager {
             preDestroy(instance, superClass);
         }
 
-        // At the end the postconstruct annotated
+        // At the end the predestroy annotated
         // method is invoked
         AnnotationCacheEntry[] annotations = annotationCache.get(clazz);
         if (annotations == null) {
diff --git a/java/org/apache/catalina/core/LocalStrings.properties 
b/java/org/apache/catalina/core/LocalStrings.properties
index 85bec718e7..ea444cddef 100644
--- a/java/org/apache/catalina/core/LocalStrings.properties
+++ b/java/org/apache/catalina/core/LocalStrings.properties
@@ -59,10 +59,13 @@ applicationFilterConfig.jmxUnregisterFail=JMX 
de-registration failed for filter
 applicationFilterConfig.preDestroy=Failed the call to preDestroy for the 
filter named [{0}] of type [{1}]
 applicationFilterConfig.release=Failed to destroy the filter named [{0}] of 
type [{1}]
 
+applicationFilterFactory.noDispatcherType=Missing dispatcher type, defaulting 
to REQUEST
 applicationFilterFactory.noFilterConfig=No filter configuration found for [{0}]
 
 applicationFilterRegistration.nullInitParam=Unable to set initialisation 
parameter for filter due to null name and/or value. Name [{0}], Value [{1}]
 applicationFilterRegistration.nullInitParams=Unable to set initialisation 
parameters for filter due to null name and/or value. Name [{0}], Value [{1}]
+applicationFilterRegistration.nullServletName=Servlet names must not be null 
or empty
+applicationFilterRegistration.nullUrlPattern=URL patterns must not be null or 
empty
 
 applicationHttpRequest.fragmentInDispatchPath=The fragment in dispatch path 
[{0}] has been removed
 applicationHttpRequest.nullAttributeName=Attribute name may not be null
@@ -71,6 +74,9 @@ applicationHttpRequest.sessionEndAccessFail=Exception 
triggered ending access to
 applicationPushBuilder.methodInvalid=The HTTP method for a push request must 
be both cacheable and safe but [{0}] is not
 applicationPushBuilder.methodNotToken=HTTP methods must be tokens but [{0}] 
contains a non-token character
 
+applicationServletRegistration.nullInitParam=Unable to set initialisation 
parameter for servlet due to null name and/or value. Name [{0}], Value [{1}]
+applicationServletRegistration.nullInitParams=Unable to set initialisation 
parameters for servlet due to null name and/or value. Name [{0}], Value [{1}]
+applicationServletRegistration.nullUrlPattern=URL patterns must not be null or 
empty
 applicationServletRegistration.setServletSecurity.iae=Null constraint 
specified for servlet [{0}] deployed to context with name [{1}]
 applicationServletRegistration.setServletSecurity.ise=Security constraints 
can''t be added to servlet [{0}] deployed to context with name [{1}] as the 
context has already been initialised
 
diff --git a/java/org/apache/catalina/core/NamingContextListener.java 
b/java/org/apache/catalina/core/NamingContextListener.java
index 857677b894..27f9711a84 100644
--- a/java/org/apache/catalina/core/NamingContextListener.java
+++ b/java/org/apache/catalina/core/NamingContextListener.java
@@ -1218,8 +1218,9 @@ public class NamingContextListener implements 
LifecycleListener, PropertyChangeL
      */
     public void removeResourceLink(String name) {
 
+        javax.naming.Context ctx = "UserTransaction".equals(name) ? compCtx : 
envCtx;
         try {
-            envCtx.unbind(name);
+            ctx.unbind(name);
         } catch (NamingException e) {
             log.error(sm.getString("naming.unbindFailed", name), e);
         }
diff --git a/java/org/apache/catalina/core/PropertiesRoleMappingListener.java 
b/java/org/apache/catalina/core/PropertiesRoleMappingListener.java
index 4248094c96..c049ee3bfa 100644
--- a/java/org/apache/catalina/core/PropertiesRoleMappingListener.java
+++ b/java/org/apache/catalina/core/PropertiesRoleMappingListener.java
@@ -50,7 +50,7 @@ public class PropertiesRoleMappingListener implements 
LifecycleListener {
     /**
      * The string manager for this package.
      */
-    private static final StringManager sm = 
StringManager.getManager(ContextNamingInfoListener.class);
+    private static final StringManager sm = 
StringManager.getManager(PropertiesRoleMappingListener.class);
 
     private String roleMappingFile = WEBAPP_PROTOCOL + 
"/WEB-INF/role-mapping.properties";
     private String keyPrefix;
diff --git a/java/org/apache/catalina/filters/ExpiresFilter.java 
b/java/org/apache/catalina/filters/ExpiresFilter.java
index a33c439a8c..45bdd48c2a 100644
--- a/java/org/apache/catalina/filters/ExpiresFilter.java
+++ b/java/org/apache/catalina/filters/ExpiresFilter.java
@@ -1437,14 +1437,9 @@ public class ExpiresFilter extends FilterBase {
                 break;
             case LAST_MODIFICATION_TIME:
                 if (response.isLastModifiedHeaderSet()) {
-                    try {
-                        long lastModified = response.getLastModifiedHeader();
-                        calendar = Calendar.getInstance();
-                        calendar.setTimeInMillis(lastModified);
-                    } catch (NumberFormatException e) {
-                        // default to now
-                        calendar = Calendar.getInstance();
-                    }
+                    long lastModified = response.getLastModifiedHeader();
+                    calendar = Calendar.getInstance();
+                    calendar.setTimeInMillis(lastModified);
                 } else {
                     // Last-Modified header not found, use now
                     calendar = Calendar.getInstance();
diff --git a/java/org/apache/catalina/filters/RateLimitFilter.java 
b/java/org/apache/catalina/filters/RateLimitFilter.java
index d54a2f38a1..eca97fb27d 100644
--- a/java/org/apache/catalina/filters/RateLimitFilter.java
+++ b/java/org/apache/catalina/filters/RateLimitFilter.java
@@ -284,9 +284,11 @@ public class RateLimitFilter extends FilterBase {
         request.setAttribute(RATE_LIMIT_ATTRIBUTE_COUNT, 
Integer.valueOf(reqCount));
 
         if (exposeHeaders) {
-            ((HttpServletResponse) 
response).addHeader(HEADER_RATE_LIMIT_POLICY, rateLimiter.getPolicy());
-            if (enforce) {
-                ((HttpServletResponse) response).addHeader(HEADER_RATE_LIMIT, 
rateLimiter.getQuota(reqCount));
+            if (response instanceof HttpServletResponse) {
+                ((HttpServletResponse) 
response).addHeader(HEADER_RATE_LIMIT_POLICY, rateLimiter.getPolicy());
+                if (enforce) {
+                    ((HttpServletResponse) 
response).addHeader(HEADER_RATE_LIMIT, rateLimiter.getQuota(reqCount));
+                }
             }
         }
         if (reqCount > rateLimiter.getRequests()) {
@@ -295,7 +297,9 @@ public class RateLimitFilter extends FilterBase {
                     Integer.valueOf(rateLimiter.getRequests()), 
Integer.valueOf(rateLimiter.getDuration())));
 
             if (enforce) {
-                ((HttpServletResponse) response).sendError(statusCode, 
statusMessage);
+                if (response instanceof HttpServletResponse) {
+                    ((HttpServletResponse) response).sendError(statusCode, 
statusMessage);
+                }
                 return;
             }
         }
diff --git a/java/org/apache/catalina/filters/RestCsrfPreventionFilter.java 
b/java/org/apache/catalina/filters/RestCsrfPreventionFilter.java
index ed083fd5cb..fc5676d9eb 100644
--- a/java/org/apache/catalina/filters/RestCsrfPreventionFilter.java
+++ b/java/org/apache/catalina/filters/RestCsrfPreventionFilter.java
@@ -202,7 +202,8 @@ public class RestCsrfPreventionFilter extends 
CsrfPreventionFilterBase {
 
         @Override
         public boolean apply(HttpServletRequest request, HttpServletResponse 
response) {
-            if (fetchRequest.test(nonceFromRequestHeader.getNonce(request, 
Constants.CSRF_REST_NONCE_HEADER_NAME))) {
+            String nonceFromRequest = nonceFromRequestHeader.getNonce(request, 
Constants.CSRF_REST_NONCE_HEADER_NAME);
+            if (Objects.nonNull(nonceFromRequest) && 
fetchRequest.test(nonceFromRequest)) {
                 String nonceFromSessionStr = 
nonceFromSession.getNonce(request.getSession(false),
                         Constants.CSRF_REST_NONCE_SESSION_ATTR_NAME);
                 if (nonceFromSessionStr == null) {
diff --git a/java/org/apache/catalina/ha/ClusterListener.java 
b/java/org/apache/catalina/ha/ClusterListener.java
index a68290f9ce..3a1834739f 100644
--- a/java/org/apache/catalina/ha/ClusterListener.java
+++ b/java/org/apache/catalina/ha/ClusterListener.java
@@ -85,7 +85,10 @@ public abstract class ClusterListener implements 
ChannelListener {
 
     @Override
     public final boolean accept(Serializable msg, Member member) {
-        return msg instanceof ClusterMessage;
+        if (msg instanceof ClusterMessage) {
+            return accept((ClusterMessage) msg);
+        }
+        return false;
     }
 
 
diff --git a/java/org/apache/catalina/ha/ClusterValve.java 
b/java/org/apache/catalina/ha/ClusterValve.java
index 7c0e3d968c..bc3aaf7e11 100644
--- a/java/org/apache/catalina/ha/ClusterValve.java
+++ b/java/org/apache/catalina/ha/ClusterValve.java
@@ -31,7 +31,7 @@ public interface ClusterValve extends Valve {
     CatalinaCluster getCluster();
 
     /**
-     * Associates the cluster deployer with a cluster
+     * Associates the cluster valve with a cluster
      *
      * @param cluster CatalinaCluster
      */
diff --git a/java/org/apache/catalina/ha/backend/CollectedInfo.java 
b/java/org/apache/catalina/ha/backend/CollectedInfo.java
index 1a937a9a7f..dd3338cad3 100644
--- a/java/org/apache/catalina/ha/backend/CollectedInfo.java
+++ b/java/org/apache/catalina/ha/backend/CollectedInfo.java
@@ -102,7 +102,12 @@ public class CollectedInfo {
             // ajp-nio-10.36.116.209-8009
             String[] elenames = name.split("-");
             String sport = elenames[elenames.length - 1];
-            iport = Integer.parseInt(sport);
+            try {
+                iport = Integer.parseInt(sport);
+            } catch (NumberFormatException e) {
+                objName = null;
+                continue;
+            }
             if (elenames.length == 4) {
                 shost = elenames[2];
             }
@@ -145,6 +150,6 @@ public class CollectedInfo {
         Integer ibusy = (Integer) mBeanServer.getAttribute(objName, 
"currentThreadsBusy");
 
         busy = ibusy.intValue();
-        ready = imax.intValue() - ibusy.intValue();
+        ready = Math.max(imax.intValue() - ibusy.intValue(), 0);
     }
 }
diff --git a/java/org/apache/catalina/ha/backend/MultiCastSender.java 
b/java/org/apache/catalina/ha/backend/MultiCastSender.java
index 1758777361..5bfa55d8ae 100644
--- a/java/org/apache/catalina/ha/backend/MultiCastSender.java
+++ b/java/org/apache/catalina/ha/backend/MultiCastSender.java
@@ -37,7 +37,7 @@ public class MultiCastSender implements Sender {
     public MultiCastSender() {
     }
 
-    private static final Log log = LogFactory.getLog(HeartbeatListener.class);
+    private static final Log log = LogFactory.getLog(MultiCastSender.class);
     private static final StringManager sm = 
StringManager.getManager(MultiCastSender.class);
 
     HeartbeatListener config = null;
diff --git a/java/org/apache/catalina/ha/backend/TcpSender.java 
b/java/org/apache/catalina/ha/backend/TcpSender.java
index 8fd7e6f7b4..1c8a3c1bb9 100644
--- a/java/org/apache/catalina/ha/backend/TcpSender.java
+++ b/java/org/apache/catalina/ha/backend/TcpSender.java
@@ -30,9 +30,6 @@ import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.res.StringManager;
 
-/*
- * Sender to proxies using multicast socket.
- */
 /**
  * TCP-based sender for sending heartbeat messages to proxy servers.
  */
@@ -44,7 +41,7 @@ public class TcpSender implements Sender {
     public TcpSender() {
     }
 
-    private static final Log log = LogFactory.getLog(HeartbeatListener.class);
+    private static final Log log = LogFactory.getLog(TcpSender.class);
     private static final StringManager sm = 
StringManager.getManager(TcpSender.class);
 
     /**
@@ -87,8 +84,8 @@ public class TcpSender implements Sender {
                 throw new 
Exception(sm.getString("tcpSender.invalidProxyList"));
             }
             proxies[i] = new Proxy();
-            proxies[i].port = Integer.parseInt(token.substring(pos + 1));
             try {
+                proxies[i].port = Integer.parseInt(token.substring(pos + 1));
                 proxies[i].address = InetAddress.getByName(token.substring(0, 
pos));
             } catch (Exception e) {
                 throw new 
Exception(sm.getString("tcpSender.invalidProxyList"));
@@ -161,7 +158,12 @@ public class TcpSender implements Sender {
             } else {
                 responseStatus = 
responseStatus.substring(responseStatus.indexOf(' ') + 1,
                         responseStatus.indexOf(' ', responseStatus.indexOf(' 
') + 1));
-                int status = Integer.parseInt(responseStatus);
+                int status = 500;
+                try {
+                    status = Integer.parseInt(responseStatus);
+                } catch (NumberFormatException e) {
+                    // Ignore
+                }
                 if (status != 200) {
                     log.error(sm.getString("tcpSender.responseErrorCode", 
Integer.valueOf(status)));
                     close(i);
diff --git a/java/org/apache/catalina/ha/context/ReplicatedContext.java 
b/java/org/apache/catalina/ha/context/ReplicatedContext.java
index 9b2c91533d..4d0bb30037 100644
--- a/java/org/apache/catalina/ha/context/ReplicatedContext.java
+++ b/java/org/apache/catalina/ha/context/ReplicatedContext.java
@@ -94,7 +94,7 @@ public class ReplicatedContext extends StandardContext 
implements MapOwner {
     @Override
     protected void stopInternal() throws LifecycleException {
 
-        Map<String,Object> map = ((ReplApplContext) 
this.context).getAttributeMap();
+        Map<String,Object> map = this.context != null ? ((ReplApplContext) 
this.context).getAttributeMap() : null;
 
         super.stopInternal();
 
@@ -251,7 +251,7 @@ public class ReplicatedContext extends StandardContext 
implements MapOwner {
         @SuppressWarnings("unchecked")
         @Override
         public Enumeration<String> getAttributeNames() {
-            Set<String> names = new HashSet<>(attributes.keySet());
+            Set<String> names = new HashSet<>(tomcatAttributes.keySet());
 
             return new MultiEnumeration<String>(
                     new Enumeration[] { super.getAttributeNames(), 
Collections.enumeration(names) });
diff --git a/java/org/apache/catalina/ha/deploy/FarmWarDeployer.java 
b/java/org/apache/catalina/ha/deploy/FarmWarDeployer.java
index 51f72a9488..11c1aa8030 100644
--- a/java/org/apache/catalina/ha/deploy/FarmWarDeployer.java
+++ b/java/org/apache/catalina/ha/deploy/FarmWarDeployer.java
@@ -392,7 +392,7 @@ public class FarmWarDeployer extends ClusterListener 
implements ClusterDeployer,
             if (log.isTraceEnabled()) {
                 log.trace(sm.getString("farmWarDeployer.removeTxMsg", 
contextName));
             }
-            cluster.send(msg);
+            getCluster().send(msg);
         }
         // remove locally
         if (undeploy) {
@@ -437,10 +437,10 @@ public class FarmWarDeployer extends ClusterListener 
implements ClusterDeployer,
                     removeServiced(cn.getName());
                 }
                 check(cn.getName());
+                install(cn.getName(), deployWar);
             } else {
                 log.error(sm.getString("farmWarDeployer.servicingDeploy", 
cn.getName(), deployWar.getName()));
             }
-            install(cn.getName(), deployWar);
         } catch (Exception e) {
             log.error(sm.getString("farmWarDeployer.modInstallFail"), e);
         }
diff --git a/java/org/apache/catalina/ha/deploy/WarWatcher.java 
b/java/org/apache/catalina/ha/deploy/WarWatcher.java
index 8235b76d32..c76fbb7475 100644
--- a/java/org/apache/catalina/ha/deploy/WarWatcher.java
+++ b/java/org/apache/catalina/ha/deploy/WarWatcher.java
@@ -163,9 +163,9 @@ public class WarWatcher {
         protected final File war;
 
         /**
-         * The last time this file was checked.
+         * The last time this file was modified.
          */
-        protected long lastChecked;
+        protected long lastModified;
 
         /**
          * The last known state of the file.
@@ -179,7 +179,7 @@ public class WarWatcher {
          */
         public WarInfo(File war) {
             this.war = war;
-            this.lastChecked = war.lastModified();
+            this.lastModified = war.lastModified();
             if (!war.exists()) {
                 lastState = -1;
             }
@@ -191,7 +191,7 @@ public class WarWatcher {
          * @return {@code true} if the file has been modified
          */
         public boolean modified() {
-            return war.exists() && war.lastModified() > lastChecked;
+            return war.exists() && war.lastModified() != lastModified;
         }
 
         /**
@@ -216,6 +216,7 @@ public class WarWatcher {
                 // file has changed - timestamp
                 result = 1;
                 lastState = result;
+                lastModified = war.lastModified();
             } else if ((!exists()) && (!(lastState == -1))) {
                 // file was removed
                 result = -1;
@@ -225,7 +226,6 @@ public class WarWatcher {
                 result = 1;
                 lastState = result;
             }
-            this.lastChecked = System.currentTimeMillis();
             return result;
         }
 
diff --git a/java/org/apache/catalina/ha/session/BackupManager.java 
b/java/org/apache/catalina/ha/session/BackupManager.java
index 98502061e7..4a54a21543 100644
--- a/java/org/apache/catalina/ha/session/BackupManager.java
+++ b/java/org/apache/catalina/ha/session/BackupManager.java
@@ -142,10 +142,10 @@ public class BackupManager extends ClusterManagerBase 
implements MapOwner, Distr
 
         super.startInternal();
 
+        if (cluster == null) {
+            throw new 
LifecycleException(sm.getString("backupManager.noCluster", getName()));
+        }
         try {
-            if (cluster == null) {
-                throw new 
LifecycleException(sm.getString("backupManager.noCluster", getName()));
-            }
             LazyReplicatedMap<String,Session> map = new 
LazyReplicatedMap<>(this, cluster.getChannel(), rpcTimeout,
                     getMapName(), getClassLoaders(), terminateOnStartFailure);
             map.setChannelSendOptions(mapSendOptions);
diff --git a/java/org/apache/catalina/ha/session/DeltaManager.java 
b/java/org/apache/catalina/ha/session/DeltaManager.java
index 8583efd812..23eeafb4ab 100644
--- a/java/org/apache/catalina/ha/session/DeltaManager.java
+++ b/java/org/apache/catalina/ha/session/DeltaManager.java
@@ -787,31 +787,27 @@ public class DeltaManager extends ClusterManagerBase {
 
         super.startInternal();
 
+        if (cluster == null) {
+            throw new 
LifecycleException(sm.getString("deltaManager.noCluster", getName()));
+        }
+
         // Load unloaded sessions, if any
         try {
-            if (cluster == null) {
-                log.error(sm.getString("deltaManager.noCluster", getName()));
-                return;
-            } else {
-                if (log.isInfoEnabled()) {
-                    String type = "unknown";
-                    if (cluster.getContainer() instanceof Host) {
-                        type = "Host";
-                    } else if (cluster.getContainer() instanceof Engine) {
-                        type = "Engine";
-                    }
-                    log.info(sm.getString("deltaManager.registerCluster", 
getName(), type, cluster.getClusterName()));
-                }
-            }
             if (log.isInfoEnabled()) {
-                log.info(sm.getString("deltaManager.startClustering", 
getName()));
+                String type = "unknown";
+                if (cluster.getContainer() instanceof Host) {
+                    type = "Host";
+                } else if (cluster.getContainer() instanceof Engine) {
+                    type = "Engine";
+                }
+                log.info(sm.getString("deltaManager.registerCluster", 
getName(), type, cluster.getClusterName()));
             }
 
             getAllClusterSessions();
 
         } catch (Throwable t) {
             ExceptionUtils.handleThrowable(t);
-            log.error(sm.getString("deltaManager.managerLoad"), t);
+            throw new 
LifecycleException(sm.getString("deltaManager.managerLoad"), t);
         }
 
         setState(LifecycleState.STARTING);
@@ -1532,6 +1528,7 @@ public class DeltaManager extends ClusterManagerBase {
     public ClusterManager cloneFromTemplate() {
         DeltaManager result = new DeltaManager();
         clone(result);
+        result.enableStatistics = enableStatistics;
         result.expireSessionsOnShutdown = expireSessionsOnShutdown;
         result.notifySessionListenersOnReplication = 
notifySessionListenersOnReplication;
         result.notifyContainerListenersOnReplication = 
notifyContainerListenersOnReplication;
diff --git a/java/org/apache/catalina/ha/tcp/ReplicationValve.java 
b/java/org/apache/catalina/ha/tcp/ReplicationValve.java
index eb2ee2b44c..45c627a628 100644
--- a/java/org/apache/catalina/ha/tcp/ReplicationValve.java
+++ b/java/org/apache/catalina/ha/tcp/ReplicationValve.java
@@ -47,14 +47,7 @@ import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.res.StringManager;
 
 /**
- * Implementation of a Valve that logs interesting contents from the specified 
Request (before processing) and the
- * corresponding Response (after processing). It is especially useful in 
debugging problems related to headers and
- * cookies.
- * <p>
- * This Valve may be attached to any Container, depending on the granularity 
of the logging you wish to perform.
- * <p>
- * primaryIndicator=true, then the request attribute 
<i>org.apache.catalina.ha.tcp.isPrimarySession.</i> is set true,
- * when request processing is at sessions primary node.
+ * Valve that triggers session replication across the cluster.
  */
 public class ReplicationValve extends ValveBase implements ClusterValve {
 
diff --git a/java/org/apache/catalina/ha/tcp/SimpleTcpCluster.java 
b/java/org/apache/catalina/ha/tcp/SimpleTcpCluster.java
index 270eb38e24..b8245ea74c 100644
--- a/java/org/apache/catalina/ha/tcp/SimpleTcpCluster.java
+++ b/java/org/apache/catalina/ha/tcp/SimpleTcpCluster.java
@@ -18,11 +18,10 @@ package org.apache.catalina.ha.tcp;
 
 import java.beans.PropertyChangeSupport;
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 import javax.management.ObjectName;
 
@@ -156,14 +155,14 @@ public class SimpleTcpCluster extends LifecycleMBeanBase
     /**
      * The context name &lt;-&gt; manager association for distributed contexts.
      */
-    protected final Map<String,ClusterManager> managers = new HashMap<>();
+    protected final Map<String,ClusterManager> managers = new 
ConcurrentHashMap<>();
 
     /**
      * Template used to create new cluster managers for contexts.
      */
     protected ClusterManager managerTemplate = new DeltaManager();
 
-    private final List<Valve> valves = new ArrayList<>();
+    private final List<Valve> valves = new CopyOnWriteArrayList<>();
 
     private ClusterDeployer clusterDeployer;
     private ObjectName onameClusterDeployer;
@@ -171,7 +170,7 @@ public class SimpleTcpCluster extends LifecycleMBeanBase
     /**
      * Listeners of messages
      */
-    protected final List<ClusterListener> clusterListeners = new ArrayList<>();
+    protected final List<ClusterListener> clusterListeners = new 
CopyOnWriteArrayList<>();
 
     /**
      * Comment for <code>notifyLifecycleListenerOnFailure</code>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to