This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 3fe5742da6d2b803b4f71242982ce34045d5f396 Author: Mark Thomas <ma...@apache.org> AuthorDate: Wed Nov 13 19:22:42 2019 +0000 Back-port FindBugs fixes from 9.0.x (and a few obvious alignment fixes spotted along the way) --- .../catalina/core/ApplicationFilterConfig.java | 2 +- .../apache/catalina/ha/tcp/ReplicationValve.java | 46 +++++---- .../catalina/manager/LocalStrings.properties | 1 + .../catalina/manager/LocalStrings_fr.properties | 1 + .../catalina/manager/LocalStrings_ja.properties | 1 + .../catalina/manager/LocalStrings_ko.properties | 1 + .../catalina/manager/LocalStrings_ru.properties | 1 + .../catalina/manager/LocalStrings_zh_CN.properties | 1 + .../apache/catalina/manager/ManagerServlet.java | 8 +- .../catalina/manager/StatusManagerServlet.java | 7 -- .../mbeans/JmxRemoteLifecycleListener.java | 27 +++++ java/org/apache/catalina/tribes/Member.java | 4 +- res/findbugs/filter-false-positives.xml | 115 +++++++++++++++++++-- 13 files changed, 176 insertions(+), 39 deletions(-) diff --git a/java/org/apache/catalina/core/ApplicationFilterConfig.java b/java/org/apache/catalina/core/ApplicationFilterConfig.java index a8f960c..dc146fc 100644 --- a/java/org/apache/catalina/core/ApplicationFilterConfig.java +++ b/java/org/apache/catalina/core/ApplicationFilterConfig.java @@ -62,7 +62,7 @@ public final class ApplicationFilterConfig implements FilterConfig, Serializable static final StringManager sm = StringManager.getManager(Constants.Package); - private final Log log = LogFactory.getLog(ApplicationFilterConfig.class); // must not be static + private transient Log log = LogFactory.getLog(ApplicationFilterConfig.class); // must not be static /** * Empty String collection to serve as the basis for empty enumerations. diff --git a/java/org/apache/catalina/ha/tcp/ReplicationValve.java b/java/org/apache/catalina/ha/tcp/ReplicationValve.java index 8fac6b2..30308b5 100644 --- a/java/org/apache/catalina/ha/tcp/ReplicationValve.java +++ b/java/org/apache/catalina/ha/tcp/ReplicationValve.java @@ -93,13 +93,21 @@ public class ReplicationValve */ protected boolean doProcessingStats = false; - protected long totalRequestTime = 0; - protected long totalSendTime = 0; - protected long nrOfRequests = 0; - protected long lastSendTime = 0; - protected long nrOfFilterRequests = 0; - protected long nrOfSendRequests = 0; - protected long nrOfCrossContextSendRequests = 0; + /* + * Note: The statistics are volatile to ensure the concurrent updates do not + * corrupt them but it is still possible that: + * - some updates may be lost; + * - the individual statistics may not be consistent which each other. + * This is a deliberate design choice to reduce the requirement for + * synchronization. + */ + protected volatile long totalRequestTime = 0; + protected volatile long totalSendTime = 0; + protected volatile long nrOfRequests = 0; + protected volatile long lastSendTime = 0; + protected volatile long nrOfFilterRequests = 0; + protected volatile long nrOfSendRequests = 0; + protected volatile long nrOfCrossContextSendRequests = 0; /** * must primary change indicator set @@ -354,11 +362,11 @@ public class ReplicationValve * reset the active statistics */ public void resetStatistics() { - totalRequestTime = 0 ; - totalSendTime = 0 ; - lastSendTime = 0 ; - nrOfFilterRequests = 0 ; - nrOfRequests = 0 ; + totalRequestTime = 0; + totalSendTime = 0; + lastSendTime = 0; + nrOfFilterRequests = 0; + nrOfRequests = 0; nrOfSendRequests = 0; nrOfCrossContextSendRequests = 0; } @@ -422,8 +430,7 @@ public class ReplicationValve protected void sendCrossContextSession() { List<DeltaSession> sessions = crossContextSessions.get(); if(sessions != null && sessions.size() >0) { - for(Iterator<DeltaSession> iter = sessions.iterator(); iter.hasNext() ;) { - Session session = iter.next(); + for (DeltaSession session : sessions) { if(log.isDebugEnabled()) { log.debug(sm.getString("ReplicationValve.crossContext.sendDelta", session.getManager().getContext().getName() )); @@ -564,12 +571,11 @@ public class ReplicationValve protected void updateStats(long requestTime, long clusterTime) { // TODO: Async requests may trigger multiple replication requests. How, // if at all, should the stats handle this? - synchronized(this) { - lastSendTime=System.currentTimeMillis(); - totalSendTime+=lastSendTime - clusterTime; - totalRequestTime+=lastSendTime - requestTime; - nrOfRequests++; - } + long currentTime = System.currentTimeMillis(); + lastSendTime = currentTime; + totalSendTime += currentTime - clusterTime; + totalRequestTime += currentTime - requestTime; + nrOfRequests++; if(log.isInfoEnabled()) { if ( (nrOfRequests % 100) == 0 ) { log.info(sm.getString("ReplicationValve.stats", diff --git a/java/org/apache/catalina/manager/LocalStrings.properties b/java/org/apache/catalina/manager/LocalStrings.properties index fac641c..556e0c1 100644 --- a/java/org/apache/catalina/manager/LocalStrings.properties +++ b/java/org/apache/catalina/manager/LocalStrings.properties @@ -141,6 +141,7 @@ managerServlet.notSslConnector=SSL is not enabled for this connector managerServlet.objectNameFail=FAIL - Unable to register object name [{0}] for Manager Servlet managerServlet.postCommand=FAIL - Tried to use command [{0}] via a GET request but POST is required managerServlet.reloaded=OK - Reloaded application at context path [{0}] +managerServlet.renameFail=FAIL - Unable to rename [{0}] to [{1}]. This may cause problems for future deployments. managerServlet.resourcesAll=OK - Listed global resources of all types managerServlet.resourcesType=OK - Listed global resources of type [{0}] managerServlet.saveFail=FAIL - Configuration save failed: [{0}] diff --git a/java/org/apache/catalina/manager/LocalStrings_fr.properties b/java/org/apache/catalina/manager/LocalStrings_fr.properties index 03ce4d1..fc2baef 100644 --- a/java/org/apache/catalina/manager/LocalStrings_fr.properties +++ b/java/org/apache/catalina/manager/LocalStrings_fr.properties @@ -139,6 +139,7 @@ managerServlet.notSslConnector=SSL n'est pas activé pour ce connecteur managerServlet.objectNameFail=ECHEC - Le nom d''objet [{0}] n''a pas pu être enregistré pour le Servlet de Gestion managerServlet.postCommand=ECHEC - Tentative d''utilisation de la commande [{0}] via une requête GET, mais POST est requis managerServlet.reloaded=OK - L''application associée au chemin de contexte [{0}] a été rechargée +managerServlet.renameFail=ECHEC - N''a pas pu renommer [{0}] vers [{1}], cela pourrait causer des problèmes pour de prochains déploiements managerServlet.resourcesAll=OK - Liste des ressources globales de tout type managerServlet.resourcesType=OK - Liste des ressources globales de type [{0}] managerServlet.saveFail=ECHEC - La sauvegarde de la configuration a échoué: [{0}] diff --git a/java/org/apache/catalina/manager/LocalStrings_ja.properties b/java/org/apache/catalina/manager/LocalStrings_ja.properties index 8007ddf..662e25a 100644 --- a/java/org/apache/catalina/manager/LocalStrings_ja.properties +++ b/java/org/apache/catalina/manager/LocalStrings_ja.properties @@ -141,6 +141,7 @@ managerServlet.notSslConnector=このコネクターでは SSL が有効化さ managerServlet.objectNameFail=FAIL - オブジェクト名 [{0}] を ManagerServlet として登録できません。 managerServlet.postCommand=FAIL - コマンド [{0}] を GET リクエストで実行しようとしましたが、POST リクエストでなければなりません。 managerServlet.reloaded=OK - コンテキストパス [{0}] のアプリケーションを再ロードしました +managerServlet.renameFail=FAIL - [{0}]の名前を[{1}]に変更できません。 これにより、今後の展開で問題が発生する可能性があります。 managerServlet.resourcesAll=OK - すべてのタイプのグローバルリソースを列挙しました managerServlet.resourcesType=OK - タイプ [{0}] のグローバルリソースを列挙しました managerServlet.saveFail=FAIL - 設定の保存に失敗しました: [{0}] diff --git a/java/org/apache/catalina/manager/LocalStrings_ko.properties b/java/org/apache/catalina/manager/LocalStrings_ko.properties index 9d34ac1..bab468d 100644 --- a/java/org/apache/catalina/manager/LocalStrings_ko.properties +++ b/java/org/apache/catalina/manager/LocalStrings_ko.properties @@ -139,6 +139,7 @@ managerServlet.notSslConnector=SSL이 이 connector를 위해 사용 가능 상 managerServlet.objectNameFail=실패 - 매니저 서블릿을 위한 객체 이름 [{0}]을(를) 등록할 수 없습니다. managerServlet.postCommand=실패 - GET 요청을 통해 명령 [{0}]을(를) 사용하려 시도했으나, POST 요청이 요구됩니다. managerServlet.reloaded=OK - 컨텍스트 경로 [{0}]의 애플리케이션을 다시 로드했습니다. +managerServlet.renameFail=실패 - [{0}]을(를) [{1}](으)로 이름을 변경할 수 없습니다. 이는 이후의 배치 작업들에서 문제들을 일으킬 수 있습니다. managerServlet.resourcesAll=OK - 모든 타입들의 글로벌 리소스들이 목록으로 표시되었습니다. managerServlet.resourcesType=OK - 타입이 [{0}]인 글로벌 리소스들의 목록을 표시했습니다. managerServlet.saveFail=실패 - 설정을 저장하지 못했습니다: [{0}] diff --git a/java/org/apache/catalina/manager/LocalStrings_ru.properties b/java/org/apache/catalina/manager/LocalStrings_ru.properties index 4f0ab23..02bb71e 100644 --- a/java/org/apache/catalina/manager/LocalStrings_ru.properties +++ b/java/org/apache/catalina/manager/LocalStrings_ru.properties @@ -141,6 +141,7 @@ managerServlet.notSslConnector=Протокол SSL/TLS для этого кон managerServlet.objectNameFail=ОШИБКА - Не удалось зарегистрировать имя объекта [{0}] для Manager Servlet managerServlet.postCommand=ОШИБКА - Попытка использовать команду [{0}] через запрос GET но требуется POST managerServlet.reloaded=OK - Приложение по пути контекста [{0}] было перезагружено +managerServlet.renameFail=ОШИБКА - Невозможно переименовать [{0}] в [{1}]. Это может вызвать проблемы для будущих развертываний. managerServlet.resourcesAll=OK - Перечислены глобальные ресурсы всех видов managerServlet.resourcesType=OK - Перечислены глобальные ресурсы вида [{0}] managerServlet.saveFail=ОШИБКА - Не удалось сохранить настройки: [{0}] diff --git a/java/org/apache/catalina/manager/LocalStrings_zh_CN.properties b/java/org/apache/catalina/manager/LocalStrings_zh_CN.properties index 93d1a00..b3b1a40 100644 --- a/java/org/apache/catalina/manager/LocalStrings_zh_CN.properties +++ b/java/org/apache/catalina/manager/LocalStrings_zh_CN.properties @@ -138,6 +138,7 @@ managerServlet.notSslConnector=不允许SSL连接 managerServlet.objectNameFail=FAIL - 不能将为Manager Servlet 注册 object name [{0}] managerServlet.postCommand=失败 - 尝试通过GET请求使用命令[{0}],但需要POST managerServlet.reloaded=OK - 上下文路径[{0}]重新加载应用程序 +managerServlet.renameFail=失败 - 无法重命名[{0}]为[{1}],这可能这未来部署时出现问题。 managerServlet.resourcesAll=OK - 列出所有类型的全部资源 managerServlet.resourcesType=OK - [{0}]类型全局资源列入清单 managerServlet.saveFail=失败 - 配置保存失败:[{0}] diff --git a/java/org/apache/catalina/manager/ManagerServlet.java b/java/org/apache/catalina/manager/ManagerServlet.java index b3d84b0..73f3593 100644 --- a/java/org/apache/catalina/manager/ManagerServlet.java +++ b/java/org/apache/catalina/manager/ManagerServlet.java @@ -690,7 +690,6 @@ public class ManagerServlet extends HttpServlet implements ContainerServlet { log("managerServlet.storeConfig", e); writer.println(smClient.getString("managerServlet.exception", e.toString())); - return; } } else { String contextPath = path; @@ -713,7 +712,6 @@ public class ManagerServlet extends HttpServlet implements ContainerServlet { log("managerServlet.save[" + path + "]", e); writer.println(smClient.getString("managerServlet.exception", e.toString())); - return; } } } @@ -802,7 +800,11 @@ public class ManagerServlet extends HttpServlet implements ContainerServlet { return; } // Rename uploaded WAR file - uploadedWar.renameTo(deployedWar); + if (!uploadedWar.renameTo(deployedWar)) { + writer.println(smClient.getString("managerServlet.renameFail", + uploadedWar, deployedWar)); + return; + } } if (tag != null) { // Copy WAR to the host's appBase diff --git a/java/org/apache/catalina/manager/StatusManagerServlet.java b/java/org/apache/catalina/manager/StatusManagerServlet.java index 71806b9..1fc7be2 100644 --- a/java/org/apache/catalina/manager/StatusManagerServlet.java +++ b/java/org/apache/catalina/manager/StatusManagerServlet.java @@ -401,14 +401,7 @@ public class StatusManagerServlet requestProcessors.removeElement(objectName); } } - String j2eeType = objectName.getKeyProperty("j2eeType"); - if (j2eeType != null) { - - } } } - } - - } diff --git a/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java b/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java index 5795ec5..f3aefde 100644 --- a/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java +++ b/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java @@ -464,5 +464,32 @@ public class JmxRemoteLifecycleListener implements LifecycleListener { sslServerSocket.setNeedClientAuth(getNeedClientAuth()); return sslServerSocket; } + + // Super class defines hashCode() and equals(). Probably not used in + // Tomcat but for safety, override them here. + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((bindAddress == null) ? 0 : bindAddress.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + SslRmiServerBindSocketFactory other = (SslRmiServerBindSocketFactory) obj; + if (bindAddress == null) { + if (other.bindAddress != null) + return false; + } else if (!bindAddress.equals(other.bindAddress)) + return false; + return true; + } } } diff --git a/java/org/apache/catalina/tribes/Member.java b/java/org/apache/catalina/tribes/Member.java index 11484eb..638abf8 100644 --- a/java/org/apache/catalina/tribes/Member.java +++ b/java/org/apache/catalina/tribes/Member.java @@ -17,6 +17,8 @@ package org.apache.catalina.tribes; +import java.io.Serializable; + /** * The Member interface, defines a member in the group. * Each member can carry a set of properties, defined by the actual implementation.<BR> @@ -27,7 +29,7 @@ package org.apache.catalina.tribes; * since a member that has crashed and the starts up again on the same port/host is * not guaranteed to be the same member, so no state transfers will ever be confused */ -public interface Member { +public interface Member extends Serializable { /** * When a member leaves the cluster, the payload of the memberDisappeared member diff --git a/res/findbugs/filter-false-positives.xml b/res/findbugs/filter-false-positives.xml index f441fdf..659f87d 100644 --- a/res/findbugs/filter-false-positives.xml +++ b/res/findbugs/filter-false-positives.xml @@ -83,12 +83,7 @@ <Bug code="REC"/> </Match> <Match> - <Class name="org.apache.catalina.ant.jmx.JMXAccessorCondition"/> - <Method name="accessJMXValue"/> - <Bug code="REC"/> - </Match> - <Match> - <Class name="org.apache.catalina.ant.jmx.JMXAccessorEqualsCondition"/> + <Class name="org.apache.catalina.ant.jmx.JMXAccessorConditionBase"/> <Method name="accessJMXValue"/> <Bug code="REC"/> </Match> @@ -127,6 +122,12 @@ <Bug code="RCN"/> </Match> <Match> + <!-- False positive. It is lifecycle state that is being protected --> + <Class name="org.apache.catalina.authenticator.SingleSignOn" /> + <Field name="engine" /> + <Bug pattern="IS2_INCONSISTENT_SYNC" /> + </Match> + <Match> <!-- req.getRemoteUser(), req.getAuthType(), request.getQueryString() can return null because o.a.t.util.buf.MessageBytes.toString() can return NULL --> @@ -173,12 +174,53 @@ <Bug code="RCN"/> </Match> <Match> + <!-- Exception caught deliberately --> + <Class name="org.apache.catalina.core.NamingContextListener" /> + <Method name="constructEnvEntry" /> + <Bug pattern="REC_CATCH_EXCEPTION" /> + </Match> + <Match> + <!-- Code uses same approach as CopyOnWriteArrayList --> + <Class name="org.apache.catalina.core.StandardContext" /> + <Field name="constraints" /> + <Bug pattern="VO_VOLATILE_REFERENCE_TO_ARRAY" /> + </Match> + <Match> + <!-- Sync is for lifecycle state, not CookieProcessor --> + <Class name="org.apache.catalina.core.StandardContext" /> + <Field name="cookieProcessor" /> + <Bug pattern="IS2_INCONSISTENT_SYNC" /> + </Match> + <Match> + <!-- Calling sleep while holding a lock is deliberate --> + <Class name="org.apache.catalina.core.StandardContext" /> + <Method name="stopInternal" /> + <Bug pattern="SWL_SLEEP_WITH_LOCK_HELD" /> + </Match> + <Match> <!-- Have to trigger GC for leak detection to work. Clearly documented --> <Class name="org.apache.catalina.core.StandardHost" /> <Method name="findReloadedContextMemoryLeaks" /> <Bug code="Dm" /> </Match> <Match> + <!-- Sync not targeting these fields --> + <Class name="org.apache.catalina.core.StandardWrapper" /> + <Or> + <Field name="multipartConfigElement" /> + <Field name="servletClass" /> + <Field name="swallowOutput" /> + <Field name="unloadDelay" /> + </Or> + <Bug pattern="IS2_INCONSISTENT_SYNC" /> + </Match> + <Match> + <!-- There is only a single wait condition --> + <Class name="org.apache.catalina.core.StandardWrapper" /> + <Method name="deallocate" /> + <Bug pattern="NO_NOTIFY_NOT_NOTIFYALL" /> + </Match> + <Match> <!-- Sleep is of short duration and lock is required --> <Class name="org.apache.catalina.core.StandardWrapper" /> <Method name="unload" /> @@ -204,6 +246,12 @@ <Bug code="DE" /> </Match> <Match> + <!-- False positive. It is lifecycle state that is being protected --> + <Class name="org.apache.catalina.ha.authenticator.ClusterSingleSignOn" /> + <Field name="cluster" /> + <Bug pattern="IS2_INCONSISTENT_SYNC" /> + </Match> + <Match> <!-- shost will not be null in normal usage --> <Class name="org.apache.catalina.ha.backend.CollectedInfo" /> <Method name="init" /> @@ -225,6 +273,29 @@ <Bug code="DE" /> </Match> <Match> + <!-- False positive caused by additional method syncs --> + <Class name="org.apache.catalina.ha.session.DeltaManager" /> + <Field name="receiverQueue" /> + <Pattern code="IS2_INCONSISTENT_SYNC" /> + </Match> + <Match> + <!-- False positive caused by method syncs --> + <Class name="org.apache.catalina.ha.session.JvmRouteBinderValve" /> + <Field name="cluster" /> + <Pattern code="IS2_INCONSISTENT_SYNC" /> + </Match> + <Match> + <!-- Design choice to reduce need for syncs --> + <Class name="org.apache.catalina.ha.tcp.ReplicationValve" /> + <Or> + <Field name="nrOfCrossContextSendRequests" /> + <Field name="nrOfFilterRequests" /> + <Field name="nrOfRequests" /> + <Field name="nrOfSendRequests" /> + </Or> + <Pattern code="VO_VOLATILE_INCREMENT" /> + </Match> + <Match> <!-- Field is only modified during Servlet load --> <Class name="org.apache.catalina.manager.host.HostManagerServlet" /> <Bug code="MSF" /> @@ -236,6 +307,19 @@ <Bug code="REC" /> </Match> <Match> + <!-- The fields are only set in setWrapper() which Tomcat calls once during + initialisation. All other accesses are reads. --> + <Class name="org.apache.catalina.manager.ManagerServlet" /> + <Or> + <Field name="context" /> + <Field name="host" /> + <Field name="mBeanServer" /> + <Field name="oname" /> + <Field name="wrapper" /> + </Or> + <Bug pattern="MSF_MUTABLE_SERVLET_FIELD" /> + </Match> + <Match> <!-- SQL construction is safe since it is from trusted config --> <Or> <Class name="org.apache.catalina.realm.DataSourceRealm" /> @@ -243,6 +327,8 @@ </Or> <Or> <Method name="credentials" /> + <Method name="getPassword" /> + <Method name="getRoles" /> <Method name="roles" /> </Or> <Bug pattern="SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING" /> @@ -253,6 +339,15 @@ <Bug code="IS" /> </Match> <Match> + <!-- Sync is protecting preparedRoles, not these fields --> + <Class name="org.apache.catalina.realm.JDBCRealm" /> + <Or> + <Field name="roleNameCol" /> + <Field name="userRoleTable" /> + </Or> + <Bug pattern="IS2_INCONSISTENT_SYNC " /> + </Match> + <Match> <!-- roles will be initialized in addAttributeValues --> <Class name="org.apache.catalina.realm.JNDIRealm" /> <Or> @@ -262,6 +357,12 @@ <Bug code="NP" /> </Match> <Match> + <!-- Sync is protecting authenticate90, not this field --> + <Class name="org.apache.catalina.realm.JNDIRealm" /> + <Field name="userPatternFormatArray" /> + <Bug pattern="IS2_INCONSISTENT_SYNC " /> + </Match> + <Match> <!-- request.getRequestPathMB(), request.getQueryString() can be null because o.a.t.util.buf.MessageBytes.toString() can return NULL --> <Class name="org.apache.catalina.realm.RealmBase"/> @@ -1320,4 +1421,4 @@ </Or> <Bug pattern="DLS_DEAD_LOCAL_STORE"/> </Match> -</FindBugsFilter> \ No newline at end of file +</FindBugsFilter> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org